strapi-content-sync-pro 1.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.
- package/LICENSE +21 -0
- package/README.md +206 -0
- package/admin/src/components/ConfigTab.jsx +1038 -0
- package/admin/src/components/ContentTypesTab.jsx +160 -0
- package/admin/src/components/HelpTab.jsx +945 -0
- package/admin/src/components/LogsTab.jsx +136 -0
- package/admin/src/components/MediaTab.jsx +557 -0
- package/admin/src/components/SyncProfilesTab.jsx +715 -0
- package/admin/src/components/SyncTab.jsx +988 -0
- package/admin/src/index.js +31 -0
- package/admin/src/pages/App/index.jsx +129 -0
- package/admin/src/pluginId.js +3 -0
- package/package.json +84 -0
- package/server/src/bootstrap.js +151 -0
- package/server/src/config/index.js +5 -0
- package/server/src/content-types/index.js +7 -0
- package/server/src/content-types/sync-log/schema.json +24 -0
- package/server/src/controllers/alerts.js +59 -0
- package/server/src/controllers/config.js +292 -0
- package/server/src/controllers/content-type-discovery.js +9 -0
- package/server/src/controllers/dependencies.js +109 -0
- package/server/src/controllers/index.js +29 -0
- package/server/src/controllers/ping.js +7 -0
- package/server/src/controllers/sync-config.js +26 -0
- package/server/src/controllers/sync-enforcement.js +323 -0
- package/server/src/controllers/sync-execution.js +134 -0
- package/server/src/controllers/sync-log.js +18 -0
- package/server/src/controllers/sync-media.js +158 -0
- package/server/src/controllers/sync-profiles.js +182 -0
- package/server/src/controllers/sync.js +31 -0
- package/server/src/destroy.js +7 -0
- package/server/src/index.js +21 -0
- package/server/src/middlewares/verify-signature.js +32 -0
- package/server/src/register.js +7 -0
- package/server/src/routes/index.js +111 -0
- package/server/src/services/alerts.js +437 -0
- package/server/src/services/config.js +68 -0
- package/server/src/services/content-type-discovery.js +41 -0
- package/server/src/services/dependency-resolver.js +284 -0
- package/server/src/services/index.js +30 -0
- package/server/src/services/ping.js +7 -0
- package/server/src/services/sync-config.js +45 -0
- package/server/src/services/sync-enforcement.js +362 -0
- package/server/src/services/sync-execution.js +541 -0
- package/server/src/services/sync-log.js +56 -0
- package/server/src/services/sync-media.js +963 -0
- package/server/src/services/sync-profiles.js +380 -0
- package/server/src/services/sync.js +248 -0
- package/server/src/utils/applier.js +89 -0
- package/server/src/utils/comparator.js +83 -0
- package/server/src/utils/fetcher.js +142 -0
- package/server/src/utils/hmac.js +37 -0
- package/server/src/utils/pagination.js +51 -0
- package/server/src/utils/sync-guard.js +29 -0
- package/server/src/utils/sync-id.js +16 -0
|
@@ -0,0 +1,945 @@
|
|
|
1
|
+
import { Box, Typography, Tabs, Divider } from '@strapi/design-system';
|
|
2
|
+
|
|
3
|
+
const HelpSection = ({ title, children }) => (
|
|
4
|
+
<Box paddingBottom={6}>
|
|
5
|
+
<Typography variant="delta" tag="h3" paddingBottom={2}>{title}</Typography>
|
|
6
|
+
{children}
|
|
7
|
+
</Box>
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
const DocLink = ({ href, children }) => (
|
|
11
|
+
<Typography
|
|
12
|
+
variant="omega"
|
|
13
|
+
textColor="primary600"
|
|
14
|
+
tag="a"
|
|
15
|
+
href={href}
|
|
16
|
+
target="_blank"
|
|
17
|
+
rel="noopener noreferrer"
|
|
18
|
+
style={{ textDecoration: 'none' }}
|
|
19
|
+
>
|
|
20
|
+
{children} →
|
|
21
|
+
</Typography>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const CodeBlock = ({ children }) => (
|
|
25
|
+
<Box background="neutral150" padding={3} hasRadius marginTop={2} marginBottom={2}>
|
|
26
|
+
<Typography variant="pi" tag="pre" style={{ fontFamily: 'monospace', whiteSpace: 'pre-wrap' }}>
|
|
27
|
+
{children}
|
|
28
|
+
</Typography>
|
|
29
|
+
</Box>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const HelpTab = () => {
|
|
33
|
+
return (
|
|
34
|
+
<Box background="neutral0" padding={6} shadow="filterShadow" hasRadius>
|
|
35
|
+
<Box paddingBottom={4}>
|
|
36
|
+
<Typography variant="beta" tag="h2">Plugin Documentation</Typography>
|
|
37
|
+
<Typography variant="omega" textColor="neutral600">
|
|
38
|
+
Complete guide for configuring and using the Content Sync Pro plugin.
|
|
39
|
+
</Typography>
|
|
40
|
+
</Box>
|
|
41
|
+
|
|
42
|
+
<Tabs.Root defaultValue="overview">
|
|
43
|
+
<Tabs.List>
|
|
44
|
+
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
|
|
45
|
+
<Tabs.Trigger value="configuration">Configuration</Tabs.Trigger>
|
|
46
|
+
<Tabs.Trigger value="content-types">Content Types</Tabs.Trigger>
|
|
47
|
+
<Tabs.Trigger value="sync-profiles">Sync Profiles</Tabs.Trigger>
|
|
48
|
+
<Tabs.Trigger value="execution">Sync Execution</Tabs.Trigger>
|
|
49
|
+
<Tabs.Trigger value="media">Media</Tabs.Trigger>
|
|
50
|
+
<Tabs.Trigger value="enforcement">Enforcement</Tabs.Trigger>
|
|
51
|
+
<Tabs.Trigger value="alerts">Alerts</Tabs.Trigger>
|
|
52
|
+
<Tabs.Trigger value="troubleshooting">Troubleshooting</Tabs.Trigger>
|
|
53
|
+
</Tabs.List>
|
|
54
|
+
|
|
55
|
+
{/* Overview Tab */}
|
|
56
|
+
<Tabs.Content value="overview">
|
|
57
|
+
<Box paddingTop={4}>
|
|
58
|
+
<HelpSection title="What is Content Sync Pro?">
|
|
59
|
+
<Typography variant="omega">
|
|
60
|
+
This plugin enables data synchronization between two Strapi v5 instances. It provides a complete
|
|
61
|
+
solution for keeping content in sync across development, staging, and production environments.
|
|
62
|
+
</Typography>
|
|
63
|
+
<Typography variant="omega" paddingTop={2}>
|
|
64
|
+
<strong>Key Features:</strong>
|
|
65
|
+
</Typography>
|
|
66
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
67
|
+
<li><Typography variant="omega">Bi-directional sync (push, pull, or both)</Typography></li>
|
|
68
|
+
<li><Typography variant="omega">Sync Profiles for defining WHAT to sync</Typography></li>
|
|
69
|
+
<li><Typography variant="omega">Execution modes: On-demand, Scheduled, or Live (real-time)</Typography></li>
|
|
70
|
+
<li><Typography variant="omega">Field-level sync policies (Advanced mode)</Typography></li>
|
|
71
|
+
<li><Typography variant="omega">Conflict resolution strategies (Latest, Local, Remote wins)</Typography></li>
|
|
72
|
+
<li><Typography variant="omega">Dependency resolution - sync related entities automatically</Typography></li>
|
|
73
|
+
<li><Typography variant="omega">Enforcement checks - schema, version, and time validation</Typography></li>
|
|
74
|
+
<li><Typography variant="omega">Configurable alerts via email, webhook, or Strapi logs</Typography></li>
|
|
75
|
+
<li><Typography variant="omega">Secure communication via API tokens and HMAC signatures</Typography></li>
|
|
76
|
+
</ul>
|
|
77
|
+
</HelpSection>
|
|
78
|
+
|
|
79
|
+
<HelpSection title="Architecture Overview">
|
|
80
|
+
<Typography variant="omega">
|
|
81
|
+
The plugin separates concerns into distinct components:
|
|
82
|
+
</Typography>
|
|
83
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
84
|
+
<li><Typography variant="omega"><strong>Sync Profiles</strong> - Define WHAT to sync (direction, conflict strategy, field policies)</Typography></li>
|
|
85
|
+
<li><Typography variant="omega"><strong>Sync Execution</strong> - Define WHEN to sync (on-demand, scheduled, live) and dependency handling</Typography></li>
|
|
86
|
+
<li><Typography variant="omega"><strong>Enforcement</strong> - Pre-sync validation (schema match, version check, time sync)</Typography></li>
|
|
87
|
+
<li><Typography variant="omega"><strong>Alerts</strong> - Notifications for sync success/failure</Typography></li>
|
|
88
|
+
</ul>
|
|
89
|
+
</HelpSection>
|
|
90
|
+
|
|
91
|
+
<HelpSection title="Quick Start">
|
|
92
|
+
<ol style={{ paddingLeft: '20px', lineHeight: '2' }}>
|
|
93
|
+
<li><Typography variant="omega"><strong>Configuration Tab</strong> - Set up remote server URL, API token, and shared secret</Typography></li>
|
|
94
|
+
<li><Typography variant="omega"><strong>Content Types Tab</strong> - Enable content types for sync (auto-generates default profiles)</Typography></li>
|
|
95
|
+
<li><Typography variant="omega"><strong>Sync Profiles Tab</strong> - Customize sync behavior or use defaults</Typography></li>
|
|
96
|
+
<li><Typography variant="omega"><strong>Sync Tab</strong> - Configure execution settings and run sync operations</Typography></li>
|
|
97
|
+
</ol>
|
|
98
|
+
</HelpSection>
|
|
99
|
+
|
|
100
|
+
<Box paddingTop={2}>
|
|
101
|
+
<DocLink href="https://docs.strapi.io/dev-docs/plugins">
|
|
102
|
+
Strapi Plugin Development Guide
|
|
103
|
+
</DocLink>
|
|
104
|
+
</Box>
|
|
105
|
+
</Box>
|
|
106
|
+
</Tabs.Content>
|
|
107
|
+
|
|
108
|
+
{/* Configuration Tab */}
|
|
109
|
+
<Tabs.Content value="configuration">
|
|
110
|
+
<Box paddingTop={4}>
|
|
111
|
+
<HelpSection title="Connection Settings">
|
|
112
|
+
<Typography variant="omega" paddingBottom={2}>
|
|
113
|
+
Configure the connection to the remote Strapi instance in the <strong>Connection</strong> sub-tab.
|
|
114
|
+
</Typography>
|
|
115
|
+
|
|
116
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
117
|
+
<Typography variant="sigma" textColor="neutral800">Base URL</Typography>
|
|
118
|
+
<Typography variant="omega" paddingTop={1}>
|
|
119
|
+
The full URL of the remote Strapi instance. Examples:
|
|
120
|
+
</Typography>
|
|
121
|
+
<CodeBlock>https://api.example.com
|
|
122
|
+
http://localhost:1337</CodeBlock>
|
|
123
|
+
<Typography variant="pi" textColor="warning600">
|
|
124
|
+
Do not include trailing slashes or API paths.
|
|
125
|
+
</Typography>
|
|
126
|
+
</Box>
|
|
127
|
+
|
|
128
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
129
|
+
<Typography variant="sigma" textColor="neutral800">API Token</Typography>
|
|
130
|
+
<Typography variant="omega" paddingTop={1}>
|
|
131
|
+
The API token for authenticating with the remote server. This token must have
|
|
132
|
+
appropriate permissions for the content types you want to sync.
|
|
133
|
+
</Typography>
|
|
134
|
+
</Box>
|
|
135
|
+
|
|
136
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
137
|
+
<Typography variant="sigma" textColor="neutral800">Instance ID</Typography>
|
|
138
|
+
<Typography variant="omega" paddingTop={1}>
|
|
139
|
+
A unique identifier for this Strapi instance. Used to track sync state and prevent loops.
|
|
140
|
+
Example: <code>production-server-1</code> or <code>dev-local</code>
|
|
141
|
+
</Typography>
|
|
142
|
+
</Box>
|
|
143
|
+
|
|
144
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
145
|
+
<Typography variant="sigma" textColor="neutral800">Shared Secret (HMAC)</Typography>
|
|
146
|
+
<Typography variant="omega" paddingTop={1}>
|
|
147
|
+
A shared secret key used to cryptographically sign requests between instances.
|
|
148
|
+
Both instances must use the exact same secret.
|
|
149
|
+
</Typography>
|
|
150
|
+
<Typography variant="pi" textColor="warning600" paddingTop={2}>
|
|
151
|
+
Use a strong, random string (32+ characters recommended). You can generate one with:
|
|
152
|
+
</Typography>
|
|
153
|
+
<CodeBlock>node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"</CodeBlock>
|
|
154
|
+
</Box>
|
|
155
|
+
</HelpSection>
|
|
156
|
+
|
|
157
|
+
<HelpSection title="How to Generate API Tokens">
|
|
158
|
+
<ol style={{ paddingLeft: '20px', lineHeight: '2' }}>
|
|
159
|
+
<li><Typography variant="omega">Log in to your <strong>remote</strong> Strapi Admin Panel</Typography></li>
|
|
160
|
+
<li><Typography variant="omega">Go to <strong>Settings</strong> → <strong>Global Settings</strong> → <strong>API Tokens</strong></Typography></li>
|
|
161
|
+
<li><Typography variant="omega">Click <strong>Create new API Token</strong></Typography></li>
|
|
162
|
+
<li><Typography variant="omega">Set <strong>Name</strong>: "Data Sync Token"</Typography></li>
|
|
163
|
+
<li><Typography variant="omega">Set <strong>Token duration</strong>: <strong>Unlimited</strong> (recommended for sync)</Typography></li>
|
|
164
|
+
<li>
|
|
165
|
+
<Typography variant="omega">Set <strong>Token type</strong>:</Typography>
|
|
166
|
+
<ul style={{ paddingLeft: '20px', marginTop: '4px' }}>
|
|
167
|
+
<li><Typography variant="omega"><em>Full Access</em> - required for push/pull operations</Typography></li>
|
|
168
|
+
<li><Typography variant="omega"><em>Custom</em> - select specific content types if needed</Typography></li>
|
|
169
|
+
</ul>
|
|
170
|
+
</li>
|
|
171
|
+
<li><Typography variant="omega">Click <strong>Save</strong> and <strong>copy the token immediately</strong> (it won't be shown again)</Typography></li>
|
|
172
|
+
</ol>
|
|
173
|
+
</HelpSection>
|
|
174
|
+
|
|
175
|
+
<Box paddingTop={2}>
|
|
176
|
+
<DocLink href="https://docs.strapi.io/user-docs/settings/api-tokens">
|
|
177
|
+
Strapi API Tokens Documentation
|
|
178
|
+
</DocLink>
|
|
179
|
+
</Box>
|
|
180
|
+
</Box>
|
|
181
|
+
</Tabs.Content>
|
|
182
|
+
|
|
183
|
+
{/* Content Types Tab */}
|
|
184
|
+
<Tabs.Content value="content-types">
|
|
185
|
+
<Box paddingTop={4}>
|
|
186
|
+
<HelpSection title="Enabling Content Types">
|
|
187
|
+
<Typography variant="omega">
|
|
188
|
+
The Content Types tab is where you enable or disable content types for synchronization.
|
|
189
|
+
This is a simple on/off toggle - all sync behavior configuration happens in Sync Profiles.
|
|
190
|
+
</Typography>
|
|
191
|
+
<Typography variant="omega" paddingTop={2}>
|
|
192
|
+
Only <code>api::*</code> content types are shown (your custom content types).
|
|
193
|
+
Plugin and admin content types are excluded for safety.
|
|
194
|
+
</Typography>
|
|
195
|
+
</HelpSection>
|
|
196
|
+
|
|
197
|
+
<HelpSection title="Auto-Generated Profiles">
|
|
198
|
+
<Typography variant="omega">
|
|
199
|
+
When you enable a content type, three default profiles are automatically created:
|
|
200
|
+
</Typography>
|
|
201
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
202
|
+
<li><Typography variant="omega"><strong>Full Push</strong> - Push all data to remote (local wins)</Typography></li>
|
|
203
|
+
<li><Typography variant="omega"><strong>Full Pull</strong> - Pull all data from remote (remote wins)</Typography></li>
|
|
204
|
+
<li><Typography variant="omega"><strong>Bidirectional</strong> - Two-way sync (latest wins) - <em>active by default</em></Typography></li>
|
|
205
|
+
</ul>
|
|
206
|
+
<Box paddingTop={2}>
|
|
207
|
+
<Typography variant="omega">
|
|
208
|
+
You can customize these profiles or create new ones in the <strong>Sync Profiles</strong> tab.
|
|
209
|
+
</Typography>
|
|
210
|
+
</Box>
|
|
211
|
+
</HelpSection>
|
|
212
|
+
|
|
213
|
+
<HelpSection title="Content Type Status Display">
|
|
214
|
+
<Typography variant="omega">
|
|
215
|
+
Each content type card shows:
|
|
216
|
+
</Typography>
|
|
217
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
218
|
+
<li><Typography variant="omega">Number of sync profiles configured</Typography></li>
|
|
219
|
+
<li><Typography variant="omega">Currently active profile name</Typography></li>
|
|
220
|
+
<li><Typography variant="omega">Enable/disable toggle switch</Typography></li>
|
|
221
|
+
</ul>
|
|
222
|
+
</HelpSection>
|
|
223
|
+
|
|
224
|
+
<Box paddingTop={2}>
|
|
225
|
+
<DocLink href="https://docs.strapi.io/dev-docs/backend-customization/models">
|
|
226
|
+
Strapi Content Types Documentation
|
|
227
|
+
</DocLink>
|
|
228
|
+
</Box>
|
|
229
|
+
</Box>
|
|
230
|
+
</Tabs.Content>
|
|
231
|
+
|
|
232
|
+
{/* Sync Profiles Tab */}
|
|
233
|
+
<Tabs.Content value="sync-profiles">
|
|
234
|
+
<Box paddingTop={4}>
|
|
235
|
+
<HelpSection title="What are Sync Profiles?">
|
|
236
|
+
<Typography variant="omega">
|
|
237
|
+
Sync Profiles define <strong>WHAT</strong> to sync and <strong>HOW</strong> conflicts are resolved.
|
|
238
|
+
They do NOT control when sync runs - that's configured in the Sync tab (Execution).
|
|
239
|
+
</Typography>
|
|
240
|
+
<Typography variant="omega" paddingTop={2}>
|
|
241
|
+
Each profile specifies:
|
|
242
|
+
</Typography>
|
|
243
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
244
|
+
<li><Typography variant="omega"><strong>Direction</strong> - Push, Pull, or Bidirectional</Typography></li>
|
|
245
|
+
<li><Typography variant="omega"><strong>Conflict Strategy</strong> - Latest wins, Local wins, or Remote wins</Typography></li>
|
|
246
|
+
<li><Typography variant="omega"><strong>Field Policies</strong> (Advanced) - Per-field direction control</Typography></li>
|
|
247
|
+
</ul>
|
|
248
|
+
</HelpSection>
|
|
249
|
+
|
|
250
|
+
<HelpSection title="Simple vs Advanced Mode">
|
|
251
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
252
|
+
<Typography variant="sigma" textColor="neutral800">Simple Mode</Typography>
|
|
253
|
+
<Typography variant="omega" paddingTop={1}>
|
|
254
|
+
Choose from preset configurations. All fields sync with the same direction.
|
|
255
|
+
Best for straightforward sync scenarios.
|
|
256
|
+
</Typography>
|
|
257
|
+
<Typography variant="omega" paddingTop={2}>
|
|
258
|
+
<strong>Available Presets:</strong>
|
|
259
|
+
</Typography>
|
|
260
|
+
<ul style={{ paddingLeft: '20px', marginTop: '4px' }}>
|
|
261
|
+
<li><Typography variant="omega">Full Push - Push all, local wins</Typography></li>
|
|
262
|
+
<li><Typography variant="omega">Full Pull - Pull all, remote wins</Typography></li>
|
|
263
|
+
<li><Typography variant="omega">Bidirectional - Both ways, latest wins</Typography></li>
|
|
264
|
+
</ul>
|
|
265
|
+
</Box>
|
|
266
|
+
|
|
267
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
268
|
+
<Typography variant="sigma" textColor="neutral800">Advanced Mode</Typography>
|
|
269
|
+
<Typography variant="omega" paddingTop={1}>
|
|
270
|
+
Configure individual field-level policies. Each field can have its own direction:
|
|
271
|
+
</Typography>
|
|
272
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px' }}>
|
|
273
|
+
<li><Typography variant="omega"><strong>Both</strong> - Field syncs in both directions</Typography></li>
|
|
274
|
+
<li><Typography variant="omega"><strong>Push</strong> - Field only pushes to remote</Typography></li>
|
|
275
|
+
<li><Typography variant="omega"><strong>Pull</strong> - Field only pulls from remote</Typography></li>
|
|
276
|
+
<li><Typography variant="omega"><strong>Exclude</strong> - Field is never synced</Typography></li>
|
|
277
|
+
</ul>
|
|
278
|
+
</Box>
|
|
279
|
+
</HelpSection>
|
|
280
|
+
|
|
281
|
+
<HelpSection title="Profile Settings Explained">
|
|
282
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
283
|
+
<Typography variant="sigma" textColor="neutral800">Sync Direction</Typography>
|
|
284
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px' }}>
|
|
285
|
+
<li><Typography variant="omega"><strong>Push Only</strong> - Send local changes to remote, never receive</Typography></li>
|
|
286
|
+
<li><Typography variant="omega"><strong>Pull Only</strong> - Receive remote changes locally, never send</Typography></li>
|
|
287
|
+
<li><Typography variant="omega"><strong>Bidirectional</strong> - Two-way sync (changes flow both ways)</Typography></li>
|
|
288
|
+
</ul>
|
|
289
|
+
</Box>
|
|
290
|
+
|
|
291
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
292
|
+
<Typography variant="sigma" textColor="neutral800">Conflict Strategy</Typography>
|
|
293
|
+
<Typography variant="omega" paddingTop={1}>
|
|
294
|
+
Determines what happens when the same record is modified on both sides:
|
|
295
|
+
</Typography>
|
|
296
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px' }}>
|
|
297
|
+
<li><Typography variant="omega"><strong>Latest Wins</strong> - The most recently updated version is kept (based on updatedAt)</Typography></li>
|
|
298
|
+
<li><Typography variant="omega"><strong>Local Wins</strong> - Local version always takes priority</Typography></li>
|
|
299
|
+
<li><Typography variant="omega"><strong>Remote Wins</strong> - Remote version always takes priority</Typography></li>
|
|
300
|
+
</ul>
|
|
301
|
+
</Box>
|
|
302
|
+
</HelpSection>
|
|
303
|
+
|
|
304
|
+
<HelpSection title="Use Case Examples">
|
|
305
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
306
|
+
<Typography variant="sigma" textColor="neutral800">Example 1: Content Approval Workflow</Typography>
|
|
307
|
+
<Typography variant="omega" paddingTop={1}>
|
|
308
|
+
Content created locally, pushed for approval. Only <code>approval_status</code> and
|
|
309
|
+
<code>approved_by</code> fields are pulled back.
|
|
310
|
+
</Typography>
|
|
311
|
+
<Typography variant="pi" textColor="primary600" paddingTop={2}>
|
|
312
|
+
→ Use Advanced mode: All fields Push, approval fields Pull
|
|
313
|
+
</Typography>
|
|
314
|
+
</Box>
|
|
315
|
+
|
|
316
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
317
|
+
<Typography variant="sigma" textColor="neutral800">Example 2: E-commerce Orders</Typography>
|
|
318
|
+
<Typography variant="omega" paddingTop={1}>
|
|
319
|
+
Orders pulled from e-commerce platform, only <code>shipping_status</code> and
|
|
320
|
+
<code>tracking_number</code> pushed back to update customers.
|
|
321
|
+
</Typography>
|
|
322
|
+
<Typography variant="pi" textColor="primary600" paddingTop={2}>
|
|
323
|
+
→ Use Advanced mode: All fields Pull, shipping fields Push
|
|
324
|
+
</Typography>
|
|
325
|
+
</Box>
|
|
326
|
+
|
|
327
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
328
|
+
<Typography variant="sigma" textColor="neutral800">Example 3: Full Backup Sync</Typography>
|
|
329
|
+
<Typography variant="omega" paddingTop={1}>
|
|
330
|
+
Production data mirrored to backup server for disaster recovery.
|
|
331
|
+
</Typography>
|
|
332
|
+
<Typography variant="pi" textColor="primary600" paddingTop={2}>
|
|
333
|
+
→ Use Simple mode: Full Push preset
|
|
334
|
+
</Typography>
|
|
335
|
+
</Box>
|
|
336
|
+
</HelpSection>
|
|
337
|
+
|
|
338
|
+
<HelpSection title="Active Profiles">
|
|
339
|
+
<Typography variant="omega">
|
|
340
|
+
Only <strong>one profile can be active</strong> per content type at any time.
|
|
341
|
+
The active profile determines the sync behavior when that content type is synced.
|
|
342
|
+
</Typography>
|
|
343
|
+
<Typography variant="omega" paddingTop={2}>
|
|
344
|
+
To change the active profile, click the <strong>Activate</strong> button on any inactive profile.
|
|
345
|
+
This will deactivate the currently active profile automatically.
|
|
346
|
+
</Typography>
|
|
347
|
+
</HelpSection>
|
|
348
|
+
</Box>
|
|
349
|
+
</Tabs.Content>
|
|
350
|
+
|
|
351
|
+
{/* Sync Execution Tab */}
|
|
352
|
+
<Tabs.Content value="execution">
|
|
353
|
+
<Box paddingTop={4}>
|
|
354
|
+
<HelpSection title="Execution Modes">
|
|
355
|
+
<Typography variant="omega">
|
|
356
|
+
Execution modes determine <strong>WHEN</strong> sync operations run. Configure these in the
|
|
357
|
+
<strong> Sync</strong> tab by clicking the settings icon on each profile.
|
|
358
|
+
</Typography>
|
|
359
|
+
|
|
360
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
361
|
+
<Typography variant="sigma" textColor="neutral800">On Demand (Manual)</Typography>
|
|
362
|
+
<Typography variant="omega" paddingTop={1}>
|
|
363
|
+
Sync only runs when you manually trigger it by clicking "Run Now" or "Sync All".
|
|
364
|
+
Best for controlled deployments and testing.
|
|
365
|
+
</Typography>
|
|
366
|
+
</Box>
|
|
367
|
+
|
|
368
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
369
|
+
<Typography variant="sigma" textColor="neutral800">Scheduled</Typography>
|
|
370
|
+
<Typography variant="omega" paddingTop={1}>
|
|
371
|
+
Sync runs automatically on a schedule. You can pick one of four{' '}
|
|
372
|
+
<strong>schedule types</strong>, each with different reliability tradeoffs:
|
|
373
|
+
</Typography>
|
|
374
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
375
|
+
<li><Typography variant="omega"><strong>Interval (setInterval)</strong> — Fires every N minutes. Simple and lightweight. Can overlap if a run takes longer than the interval, and drifts slightly over time. Good for small, frequent syncs.</Typography></li>
|
|
376
|
+
<li><Typography variant="omega"><strong>Timeout (chained setTimeout)</strong> — Waits for the previous run to finish before scheduling the next. Cannot overlap. Recommended when individual syncs can take a long time.</Typography></li>
|
|
377
|
+
<li><Typography variant="omega"><strong>Cron (wall-clock)</strong> — Uses Strapi's built-in <code>strapi.cron</code> (node-schedule) with a standard cron expression (e.g. <code>0 */2 * * *</code>). Recommended for production and larger datasets because runs are tied to wall-clock time rather than process uptime.</Typography></li>
|
|
378
|
+
<li><Typography variant="omega"><strong>External scheduler</strong> — The plugin runs <em>no</em> in-process timer. An external system (system cron, Windows Task Scheduler, Kubernetes CronJob, cloud scheduler, CI) calls the execute endpoint on a schedule. Most reliable for very large datasets or multi-node / HA deployments where you cannot rely on a single Node process.</Typography></li>
|
|
379
|
+
</ul>
|
|
380
|
+
<Typography variant="pi" textColor="neutral600" paddingTop={2}>
|
|
381
|
+
Tip: If your sync regularly takes longer than a few minutes or must survive restarts predictably, prefer <strong>Cron</strong> or <strong>External</strong> over Interval/Timeout.
|
|
382
|
+
</Typography>
|
|
383
|
+
</Box>
|
|
384
|
+
|
|
385
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
386
|
+
<Typography variant="sigma" textColor="neutral800">External Scheduled Jobs (how-to)</Typography>
|
|
387
|
+
<Typography variant="omega" paddingTop={1}>
|
|
388
|
+
Select schedule type <strong>External</strong> on a profile, then configure any scheduler you already trust to POST to the execute endpoint:
|
|
389
|
+
</Typography>
|
|
390
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={2} marginBottom={2}>
|
|
391
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
392
|
+
POST {'{BASE_URL}'}/api/strapi-content-sync-pro/sync-execution/execute/{'{profileId}'}<br />
|
|
393
|
+
Authorization: Bearer {'{STRAPI_API_TOKEN}'}<br />
|
|
394
|
+
Content-Type: application/json
|
|
395
|
+
</Typography>
|
|
396
|
+
</Box>
|
|
397
|
+
<Typography variant="omega" paddingTop={1}><strong>Linux cron</strong> (every hour):</Typography>
|
|
398
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={1} marginBottom={2}>
|
|
399
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
400
|
+
0 * * * * curl -fsS -X POST -H "Authorization: Bearer $TOKEN" https://cms.example.com/api/strapi-content-sync-pro/sync-execution/execute/PROFILE_ID
|
|
401
|
+
</Typography>
|
|
402
|
+
</Box>
|
|
403
|
+
<Typography variant="omega" paddingTop={1}><strong>Windows Task Scheduler</strong> (PowerShell):</Typography>
|
|
404
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={1} marginBottom={2}>
|
|
405
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
406
|
+
{"$a = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-Command \"Invoke-RestMethod -Method Post -Uri https://cms.example.com/api/strapi-content-sync-pro/sync-execution/execute/PROFILE_ID -Headers @{Authorization=''Bearer ''+$env:SYNC_TOKEN}\"'"}<br />
|
|
407
|
+
{'$t = New-ScheduledTaskTrigger -Daily -At 2am'}<br />
|
|
408
|
+
{'Register-ScheduledTask -TaskName "StrapiDataSync" -Action $a -Trigger $t'}
|
|
409
|
+
</Typography>
|
|
410
|
+
</Box>
|
|
411
|
+
<Typography variant="omega" paddingTop={1}><strong>systemd timer</strong> (unit + timer):</Typography>
|
|
412
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={1} marginBottom={2}>
|
|
413
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
414
|
+
# /etc/systemd/system/strapi-sync.service<br />
|
|
415
|
+
[Service]<br />
|
|
416
|
+
Type=oneshot<br />
|
|
417
|
+
ExecStart=/usr/bin/curl -fsS -X POST -H "Authorization: Bearer %i" https://cms.example.com/api/strapi-content-sync-pro/sync-execution/execute/PROFILE_ID<br /><br />
|
|
418
|
+
# /etc/systemd/system/strapi-sync.timer<br />
|
|
419
|
+
[Timer]<br />
|
|
420
|
+
OnCalendar=hourly<br />
|
|
421
|
+
Unit=strapi-sync.service<br />
|
|
422
|
+
[Install]<br />
|
|
423
|
+
WantedBy=timers.target
|
|
424
|
+
</Typography>
|
|
425
|
+
</Box>
|
|
426
|
+
<Typography variant="omega" paddingTop={1}><strong>Kubernetes CronJob</strong>:</Typography>
|
|
427
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={1} marginBottom={2}>
|
|
428
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
429
|
+
apiVersion: batch/v1<br />
|
|
430
|
+
kind: CronJob<br />
|
|
431
|
+
metadata: {'{'} name: strapi-data-sync {'}'}<br />
|
|
432
|
+
spec:<br />
|
|
433
|
+
schedule: "0 * * * *"<br />
|
|
434
|
+
jobTemplate:<br />
|
|
435
|
+
spec:<br />
|
|
436
|
+
template:<br />
|
|
437
|
+
spec:<br />
|
|
438
|
+
restartPolicy: OnFailure<br />
|
|
439
|
+
containers:<br />
|
|
440
|
+
- name: sync<br />
|
|
441
|
+
image: curlimages/curl:latest<br />
|
|
442
|
+
args: ["-fsS","-X","POST","-H","Authorization: Bearer $(TOKEN)","https://cms.example.com/api/strapi-content-sync-pro/sync-execution/execute/PROFILE_ID"]
|
|
443
|
+
</Typography>
|
|
444
|
+
</Box>
|
|
445
|
+
<Typography variant="omega" paddingTop={1}><strong>GitHub Actions</strong> (scheduled workflow):</Typography>
|
|
446
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={1} marginBottom={2}>
|
|
447
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
448
|
+
on:<br />
|
|
449
|
+
schedule:<br />
|
|
450
|
+
- cron: "0 * * * *"<br />
|
|
451
|
+
jobs:<br />
|
|
452
|
+
sync:<br />
|
|
453
|
+
runs-on: ubuntu-latest<br />
|
|
454
|
+
steps:<br />
|
|
455
|
+
{' - run: curl -fsS -X POST -H "Authorization: Bearer ${{ secrets.SYNC_TOKEN }}" https://cms.example.com/api/strapi-content-sync-pro/sync-execution/execute/PROFILE_ID'}
|
|
456
|
+
</Typography>
|
|
457
|
+
</Box>
|
|
458
|
+
<Typography variant="pi" textColor="neutral600" paddingTop={2}>
|
|
459
|
+
The API token must have permission to access the plugin's content-api routes. Generate it in Strapi under <strong>Settings → API Tokens</strong>, or via the Connection tab's "Login & Create Token" helper.
|
|
460
|
+
</Typography>
|
|
461
|
+
</Box>
|
|
462
|
+
|
|
463
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={4}>
|
|
464
|
+
<Typography variant="sigma" textColor="neutral800">Live (Real-time)</Typography>
|
|
465
|
+
<Typography variant="omega" paddingTop={1}>
|
|
466
|
+
Sync triggers immediately when content changes (create, update, delete).
|
|
467
|
+
Uses lifecycle hooks to detect changes.
|
|
468
|
+
</Typography>
|
|
469
|
+
<Typography variant="pi" textColor="warning600" paddingTop={2}>
|
|
470
|
+
Note: Increases server load. Use for critical content only.
|
|
471
|
+
</Typography>
|
|
472
|
+
</Box>
|
|
473
|
+
</HelpSection>
|
|
474
|
+
|
|
475
|
+
<HelpSection title="Dependency Syncing">
|
|
476
|
+
<Typography variant="omega">
|
|
477
|
+
When enabled, the system automatically syncs related entities along with the main content.
|
|
478
|
+
</Typography>
|
|
479
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
480
|
+
<li><Typography variant="omega"><strong>Relations</strong> - Related content types (oneToOne, oneToMany, etc.)</Typography></li>
|
|
481
|
+
<li><Typography variant="omega"><strong>Components</strong> - Embedded component data</Typography></li>
|
|
482
|
+
<li><Typography variant="omega"><strong>Dynamic Zones</strong> - Dynamic zone component data</Typography></li>
|
|
483
|
+
</ul>
|
|
484
|
+
<Typography variant="omega" paddingTop={2}>
|
|
485
|
+
<strong>Dependency Depth:</strong> Controls how many levels of relations to follow (1-5).
|
|
486
|
+
Higher depth = more complete sync, but slower and more data transferred.
|
|
487
|
+
</Typography>
|
|
488
|
+
</HelpSection>
|
|
489
|
+
|
|
490
|
+
<HelpSection title="Running Sync Operations">
|
|
491
|
+
<Typography variant="omega">
|
|
492
|
+
The Sync tab provides two ways to trigger sync:
|
|
493
|
+
</Typography>
|
|
494
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
495
|
+
<li><Typography variant="omega"><strong>Sync All Active Profiles</strong> - Runs all active profiles for all enabled content types</Typography></li>
|
|
496
|
+
<li><Typography variant="omega"><strong>Run Now</strong> (per profile) - Runs a specific profile immediately</Typography></li>
|
|
497
|
+
</ul>
|
|
498
|
+
</HelpSection>
|
|
499
|
+
|
|
500
|
+
<HelpSection title="Execution Status">
|
|
501
|
+
<Typography variant="omega">
|
|
502
|
+
The Status tab in Sync shows the current state of all profiles:
|
|
503
|
+
</Typography>
|
|
504
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
505
|
+
<li><Typography variant="omega"><strong>Execution Mode</strong> - Current mode (On Demand, Scheduled, Live)</Typography></li>
|
|
506
|
+
<li><Typography variant="omega"><strong>Enabled</strong> - Whether automatic execution is enabled</Typography></li>
|
|
507
|
+
<li><Typography variant="omega"><strong>Last Run</strong> - When sync last executed</Typography></li>
|
|
508
|
+
<li><Typography variant="omega"><strong>Next Run</strong> - When scheduled sync will run next</Typography></li>
|
|
509
|
+
<li><Typography variant="omega"><strong>Status</strong> - Running or Idle</Typography></li>
|
|
510
|
+
</ul>
|
|
511
|
+
</HelpSection>
|
|
512
|
+
</Box>
|
|
513
|
+
</Tabs.Content>
|
|
514
|
+
|
|
515
|
+
{/* Media Tab */}
|
|
516
|
+
<Tabs.Content value="media">
|
|
517
|
+
<Box paddingTop={4}>
|
|
518
|
+
<HelpSection title="Pagination for Large Datasets">
|
|
519
|
+
<Typography variant="omega">
|
|
520
|
+
Content-type sync is paginated end-to-end. The global <strong>Page size</strong>
|
|
521
|
+
(<code>syncPageSize</code>, default 100) controls how many records the local Document Service and
|
|
522
|
+
the remote REST API return per request. Both sides fetch in the same page-size chunks
|
|
523
|
+
and records are processed in bounded memory, so syncing millions of entries does not
|
|
524
|
+
spike memory.
|
|
525
|
+
</Typography>
|
|
526
|
+
<Typography variant="omega" paddingTop={2}>
|
|
527
|
+
Tune it from the <strong>Sync</strong> tab's global execution settings. Larger pages
|
|
528
|
+
are faster but use more memory per chunk; smaller pages are safer on constrained hosts.
|
|
529
|
+
</Typography>
|
|
530
|
+
</HelpSection>
|
|
531
|
+
|
|
532
|
+
<HelpSection title="Media Sync Profiles">
|
|
533
|
+
<Typography variant="omega">
|
|
534
|
+
Media sync now uses the same <strong>profile-based model</strong> as content-type sync.
|
|
535
|
+
Each media profile defines:
|
|
536
|
+
</Typography>
|
|
537
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
538
|
+
<li><Typography variant="omega"><strong>Strategy</strong> - URL (HTTP), rsync (file copy), or Disabled</Typography></li>
|
|
539
|
+
<li><Typography variant="omega"><strong>Direction</strong> - Push, Pull, or Both</Typography></li>
|
|
540
|
+
<li><Typography variant="omega"><strong>Conflict Strategy</strong> - Latest Wins, Local Wins, or Remote Wins</Typography></li>
|
|
541
|
+
<li><Typography variant="omega"><strong>Sync Scope</strong> - DB rows (metadata), file bytes, or both</Typography></li>
|
|
542
|
+
<li><Typography variant="omega"><strong>File Type Filters</strong> - Include/exclude by MIME type and filename patterns</Typography></li>
|
|
543
|
+
<li><Typography variant="omega"><strong>Execution Settings</strong> - On Demand, Scheduled (interval/timeout/cron/external), or Live</Typography></li>
|
|
544
|
+
</ul>
|
|
545
|
+
<Typography variant="omega" paddingTop={2}>
|
|
546
|
+
Only <strong>one media profile can be active</strong> at a time. The active profile is used
|
|
547
|
+
when running "Sync All Active" or when scheduled/live execution triggers.
|
|
548
|
+
</Typography>
|
|
549
|
+
</HelpSection>
|
|
550
|
+
|
|
551
|
+
<HelpSection title="Default Profiles & File Types">
|
|
552
|
+
<Typography variant="omega">
|
|
553
|
+
Three default profiles are auto-generated on first use:
|
|
554
|
+
</Typography>
|
|
555
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
556
|
+
<li><Typography variant="omega"><strong>Full Push (Media)</strong> - Push all, local wins</Typography></li>
|
|
557
|
+
<li><Typography variant="omega"><strong>Full Pull (Media)</strong> - Pull all, remote wins</Typography></li>
|
|
558
|
+
<li><Typography variant="omega"><strong>Bidirectional (Media)</strong> - Both ways, latest wins (active by default)</Typography></li>
|
|
559
|
+
</ul>
|
|
560
|
+
<Typography variant="omega" paddingTop={2}>
|
|
561
|
+
All default profiles include common file types:
|
|
562
|
+
</Typography>
|
|
563
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
564
|
+
<li><Typography variant="omega"><strong>Images</strong> - All image/* MIME types</Typography></li>
|
|
565
|
+
<li><Typography variant="omega"><strong>Videos</strong> - MP4, WebM, AVI, QuickTime (MOV), Matroska (MKV), OGG, 3GPP</Typography></li>
|
|
566
|
+
<li><Typography variant="omega"><strong>Documents</strong> - PDF, Word (DOC/DOCX), Excel (XLS/XLSX), PowerPoint (PPT/PPTX), OpenDocument (ODT/ODS), CSV, Plain Text</Typography></li>
|
|
567
|
+
</ul>
|
|
568
|
+
<Typography variant="pi" textColor="neutral600" paddingTop={2}>
|
|
569
|
+
You can customize MIME filters per profile to include or exclude specific file types.
|
|
570
|
+
</Typography>
|
|
571
|
+
</HelpSection>
|
|
572
|
+
|
|
573
|
+
<HelpSection title="Sync Scope: DB Rows vs File Bytes">
|
|
574
|
+
<Typography variant="omega">
|
|
575
|
+
Each profile can sync two distinct aspects of media:
|
|
576
|
+
</Typography>
|
|
577
|
+
<Box background="neutral100" padding={4} hasRadius marginTop={2} marginBottom={2}>
|
|
578
|
+
<Typography variant="sigma" textColor="neutral800">DB Rows (Metadata)</Typography>
|
|
579
|
+
<Typography variant="omega" paddingTop={1}>
|
|
580
|
+
Syncs the <code>plugin::upload.file</code> table data: name, caption, alternative text,
|
|
581
|
+
MIME type, size, dimensions, formats, folder path, etc. This ensures both instances
|
|
582
|
+
have matching upload records even if file bytes are managed separately.
|
|
583
|
+
</Typography>
|
|
584
|
+
</Box>
|
|
585
|
+
<Box background="neutral100" padding={4} hasRadius marginBottom={2}>
|
|
586
|
+
<Typography variant="sigma" textColor="neutral800">File Bytes (Assets)</Typography>
|
|
587
|
+
<Typography variant="omega" paddingTop={1}>
|
|
588
|
+
Syncs the actual media files via the chosen strategy (URL download/upload or rsync).
|
|
589
|
+
Enable this when both instances need the physical files, not just database references.
|
|
590
|
+
</Typography>
|
|
591
|
+
</Box>
|
|
592
|
+
<Typography variant="pi" textColor="warning600">
|
|
593
|
+
For complete media synchronization, enable <strong>both</strong> DB rows and file bytes.
|
|
594
|
+
If you only need metadata references (e.g., both sides use the same S3 bucket), you can
|
|
595
|
+
sync DB rows only.
|
|
596
|
+
</Typography>
|
|
597
|
+
</HelpSection>
|
|
598
|
+
|
|
599
|
+
<HelpSection title="URL strategy (HTTP)">
|
|
600
|
+
<Typography variant="omega">
|
|
601
|
+
Works with any upload provider on either side (local, S3, Cloudinary, ...). The plugin
|
|
602
|
+
lists files via the remote <code>/api/upload/files</code> endpoint, downloads bytes via
|
|
603
|
+
the file's URL, and re-uploads them with <code>POST /api/upload</code> using the
|
|
604
|
+
configured API token. Files are deduped by <code>hash + name</code>, and optionally
|
|
605
|
+
skipped when <code>size</code> and <code>hash</code> match.
|
|
606
|
+
</Typography>
|
|
607
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={2}>
|
|
608
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
609
|
+
Required remote API token permissions: <strong>Upload: find, findOne, upload</strong>.
|
|
610
|
+
</Typography>
|
|
611
|
+
</Box>
|
|
612
|
+
<Typography variant="pi" textColor="neutral600" paddingTop={2}>
|
|
613
|
+
Best for: small/medium libraries, cross-provider setups, environments without SSH.
|
|
614
|
+
</Typography>
|
|
615
|
+
</HelpSection>
|
|
616
|
+
|
|
617
|
+
<HelpSection title="rsync strategy (file-level copy)">
|
|
618
|
+
<Typography variant="omega">
|
|
619
|
+
The plugin spawns the <code>rsync</code> binary on the host running Strapi. Both sides
|
|
620
|
+
must use the local upload provider and the paths must be reachable (SSH target or a
|
|
621
|
+
locally-mounted share). The plugin does NOT manage SSH keys; configure them on the host.
|
|
622
|
+
</Typography>
|
|
623
|
+
<Box background="neutral0" padding={3} hasRadius marginTop={2} marginBottom={2}>
|
|
624
|
+
<Typography variant="pi" style={{ fontFamily: 'monospace' }}>
|
|
625
|
+
Local media path: ./public/uploads<br />
|
|
626
|
+
Remote media path: deploy@cms.example.com:/srv/strapi/public/uploads<br />
|
|
627
|
+
rsync args: -avz --delete-after<br />
|
|
628
|
+
Example (push): rsync -avz --delete-after ./public/uploads/ deploy@cms.example.com:/srv/strapi/public/uploads
|
|
629
|
+
</Typography>
|
|
630
|
+
</Box>
|
|
631
|
+
<Typography variant="pi" textColor="warning600" paddingTop={2}>
|
|
632
|
+
<strong>Note:</strong> rsync only copies file bytes. Enable <strong>DB rows sync</strong> on
|
|
633
|
+
the profile as well if the destination needs matching <code>plugin::upload.file</code> records.
|
|
634
|
+
</Typography>
|
|
635
|
+
</HelpSection>
|
|
636
|
+
|
|
637
|
+
<HelpSection title="Media Execution Settings">
|
|
638
|
+
<Typography variant="omega">
|
|
639
|
+
Each media profile has its own execution settings, identical to content-type profiles:
|
|
640
|
+
</Typography>
|
|
641
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
642
|
+
<li><Typography variant="omega"><strong>On Demand</strong> - Manual trigger via "Run" button or API</Typography></li>
|
|
643
|
+
<li><Typography variant="omega"><strong>Scheduled</strong> - Interval, Timeout, Cron, or External scheduler</Typography></li>
|
|
644
|
+
<li><Typography variant="omega"><strong>Live</strong> - Triggers on upload file changes (create/update/delete)</Typography></li>
|
|
645
|
+
</ul>
|
|
646
|
+
<Typography variant="omega" paddingTop={2}>
|
|
647
|
+
For per-profile execution: <code>POST /api/strapi-content-sync-pro/media-sync/profiles/:id/run</code>
|
|
648
|
+
</Typography>
|
|
649
|
+
<Typography variant="omega" paddingTop={1}>
|
|
650
|
+
For all active profiles: <code>POST /api/strapi-content-sync-pro/media-sync/run-active</code>
|
|
651
|
+
</Typography>
|
|
652
|
+
</HelpSection>
|
|
653
|
+
|
|
654
|
+
<HelpSection title="Dry run & testing">
|
|
655
|
+
<Typography variant="omega">
|
|
656
|
+
Toggle <strong>Dry run</strong> on a profile to list what would change without transferring any
|
|
657
|
+
bytes (rsync passes <code>--dry-run</code>; URL strategy skips the actual
|
|
658
|
+
upload/download). Use <strong>Test connection</strong> to quickly verify the remote
|
|
659
|
+
token (URL) or the rsync binary (rsync) before a real run.
|
|
660
|
+
</Typography>
|
|
661
|
+
</HelpSection>
|
|
662
|
+
</Box>
|
|
663
|
+
</Tabs.Content>
|
|
664
|
+
|
|
665
|
+
{/* Enforcement Tab */}
|
|
666
|
+
<Tabs.Content value="enforcement">
|
|
667
|
+
<Box paddingTop={4}>
|
|
668
|
+
<HelpSection title="Pre-Sync Validation">
|
|
669
|
+
<Typography variant="omega">
|
|
670
|
+
Enforcement checks run before each sync operation to ensure compatibility between instances.
|
|
671
|
+
Configure these in <strong>Configuration → Enforcement</strong>.
|
|
672
|
+
</Typography>
|
|
673
|
+
</HelpSection>
|
|
674
|
+
|
|
675
|
+
<HelpSection title="Schema Match">
|
|
676
|
+
<Typography variant="omega">
|
|
677
|
+
Verifies that content type schemas are compatible between local and remote instances.
|
|
678
|
+
</Typography>
|
|
679
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
680
|
+
<li><Typography variant="omega"><strong>Strict</strong> - Schemas must match exactly (same fields, same types)</Typography></li>
|
|
681
|
+
<li><Typography variant="omega"><strong>Compatible</strong> - Extra fields allowed, but common fields must match types</Typography></li>
|
|
682
|
+
<li><Typography variant="omega"><strong>None</strong> - Skip schema checking entirely</Typography></li>
|
|
683
|
+
</ul>
|
|
684
|
+
<Typography variant="pi" textColor="warning600" paddingTop={2}>
|
|
685
|
+
Recommended: Use "Strict" during development, "Compatible" in production if schemas may drift.
|
|
686
|
+
</Typography>
|
|
687
|
+
</HelpSection>
|
|
688
|
+
|
|
689
|
+
<HelpSection title="Version Check">
|
|
690
|
+
<Typography variant="omega">
|
|
691
|
+
Ensures Strapi versions are compatible between instances.
|
|
692
|
+
</Typography>
|
|
693
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
694
|
+
<li><Typography variant="omega"><strong>Exact</strong> - Versions must match exactly (e.g., both 5.0.0)</Typography></li>
|
|
695
|
+
<li><Typography variant="omega"><strong>Minor</strong> - Major version must match (e.g., 5.0.0 and 5.1.0 are OK)</Typography></li>
|
|
696
|
+
<li><Typography variant="omega"><strong>Major</strong> - Any version allowed (not recommended)</Typography></li>
|
|
697
|
+
<li><Typography variant="omega"><strong>None</strong> - Skip version checking</Typography></li>
|
|
698
|
+
</ul>
|
|
699
|
+
</HelpSection>
|
|
700
|
+
|
|
701
|
+
<HelpSection title="DateTime Sync">
|
|
702
|
+
<Typography variant="omega">
|
|
703
|
+
Verifies that server clocks are synchronized. Important for "Latest Wins" conflict resolution.
|
|
704
|
+
</Typography>
|
|
705
|
+
<Typography variant="omega" paddingTop={2}>
|
|
706
|
+
<strong>Max Time Drift:</strong> Maximum allowed difference in milliseconds (default: 60000ms = 1 minute).
|
|
707
|
+
</Typography>
|
|
708
|
+
<Typography variant="pi" textColor="neutral600" paddingTop={2}>
|
|
709
|
+
If servers are in different time zones, ensure they use NTP for clock synchronization.
|
|
710
|
+
</Typography>
|
|
711
|
+
</HelpSection>
|
|
712
|
+
|
|
713
|
+
<HelpSection title="Block on Failure">
|
|
714
|
+
<Typography variant="omega">
|
|
715
|
+
When enabled, sync operations are blocked if any enforcement check fails.
|
|
716
|
+
When disabled, warnings are logged but sync proceeds anyway.
|
|
717
|
+
</Typography>
|
|
718
|
+
</HelpSection>
|
|
719
|
+
</Box>
|
|
720
|
+
</Tabs.Content>
|
|
721
|
+
|
|
722
|
+
{/* Alerts Tab */}
|
|
723
|
+
<Tabs.Content value="alerts">
|
|
724
|
+
<Box paddingTop={4}>
|
|
725
|
+
<HelpSection title="Alert Channels">
|
|
726
|
+
<Typography variant="omega">
|
|
727
|
+
Configure notifications for sync success and failure events in <strong>Configuration → Alerts</strong>.
|
|
728
|
+
</Typography>
|
|
729
|
+
</HelpSection>
|
|
730
|
+
|
|
731
|
+
<HelpSection title="Strapi Notifications">
|
|
732
|
+
<Typography variant="omega">
|
|
733
|
+
Logs sync events to the plugin's sync log, visible in the <strong>Logs</strong> tab.
|
|
734
|
+
Also logs to the Strapi server console.
|
|
735
|
+
</Typography>
|
|
736
|
+
<Typography variant="omega" paddingTop={2}>
|
|
737
|
+
This is the simplest notification method and is enabled by default.
|
|
738
|
+
</Typography>
|
|
739
|
+
</HelpSection>
|
|
740
|
+
|
|
741
|
+
<HelpSection title="Email Notifications">
|
|
742
|
+
<Typography variant="omega">
|
|
743
|
+
Send email alerts using Strapi's built-in email plugin. This plugin leverages whatever
|
|
744
|
+
email provider you have configured in your Strapi instance.
|
|
745
|
+
</Typography>
|
|
746
|
+
|
|
747
|
+
<Box background="neutral100" padding={4} hasRadius marginTop={4} marginBottom={4}>
|
|
748
|
+
<Typography variant="sigma" textColor="neutral800">Supported Email Providers</Typography>
|
|
749
|
+
<Typography variant="omega" paddingTop={1}>
|
|
750
|
+
Strapi supports several email providers. Install and configure one of:
|
|
751
|
+
</Typography>
|
|
752
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px' }}>
|
|
753
|
+
<li><Typography variant="omega"><strong>@strapi/provider-email-sendgrid</strong> - SendGrid (recommended for production)</Typography></li>
|
|
754
|
+
<li><Typography variant="omega"><strong>@strapi/provider-email-mailgun</strong> - Mailgun</Typography></li>
|
|
755
|
+
<li><Typography variant="omega"><strong>@strapi/provider-email-amazon-ses</strong> - Amazon SES</Typography></li>
|
|
756
|
+
<li><Typography variant="omega"><strong>@strapi/provider-email-nodemailer</strong> - Any SMTP server (Gmail, custom, etc.)</Typography></li>
|
|
757
|
+
</ul>
|
|
758
|
+
</Box>
|
|
759
|
+
|
|
760
|
+
<Box background="warning100" padding={4} hasRadius marginBottom={4}>
|
|
761
|
+
<Typography variant="sigma" textColor="warning700">Setup Instructions</Typography>
|
|
762
|
+
<Typography variant="omega" paddingTop={1}>
|
|
763
|
+
To enable email alerts:
|
|
764
|
+
</Typography>
|
|
765
|
+
<ol style={{ paddingLeft: '20px', marginTop: '8px' }}>
|
|
766
|
+
<li><Typography variant="omega">Install a provider: <code>npm install @strapi/provider-email-sendgrid</code></Typography></li>
|
|
767
|
+
<li><Typography variant="omega">Configure in <code>config/plugins.js</code></Typography></li>
|
|
768
|
+
<li><Typography variant="omega">Add your API key or credentials</Typography></li>
|
|
769
|
+
<li><Typography variant="omega">Restart Strapi</Typography></li>
|
|
770
|
+
</ol>
|
|
771
|
+
<Typography variant="pi" paddingTop={2}>
|
|
772
|
+
See: <a href="https://docs.strapi.io/dev-docs/providers" target="_blank" rel="noopener noreferrer">Strapi Email Providers Documentation</a>
|
|
773
|
+
</Typography>
|
|
774
|
+
</Box>
|
|
775
|
+
|
|
776
|
+
<Typography variant="omega">
|
|
777
|
+
<strong>Recipients:</strong> Enter comma-separated email addresses to receive alerts.
|
|
778
|
+
The sender address uses your email plugin's default, or you can override it.
|
|
779
|
+
</Typography>
|
|
780
|
+
</HelpSection>
|
|
781
|
+
|
|
782
|
+
<HelpSection title="Webhook Notifications">
|
|
783
|
+
<Typography variant="omega">
|
|
784
|
+
Send alerts to any HTTP endpoint (Slack, Discord, custom systems, etc.).
|
|
785
|
+
</Typography>
|
|
786
|
+
<Typography variant="omega" paddingTop={2}>
|
|
787
|
+
The webhook receives a POST request with JSON body:
|
|
788
|
+
</Typography>
|
|
789
|
+
<CodeBlock>{`{
|
|
790
|
+
"event": "sync_success" | "sync_failure",
|
|
791
|
+
"timestamp": "2024-01-15T10:30:00.000Z",
|
|
792
|
+
"data": {
|
|
793
|
+
"profile": "Full Push",
|
|
794
|
+
"contentType": "api::article.article",
|
|
795
|
+
"duration": 5000,
|
|
796
|
+
"error": "Error message (only on failure)"
|
|
797
|
+
}
|
|
798
|
+
}`}</CodeBlock>
|
|
799
|
+
</HelpSection>
|
|
800
|
+
|
|
801
|
+
<HelpSection title="Alert Triggers">
|
|
802
|
+
<Typography variant="omega">
|
|
803
|
+
Each channel can be configured to trigger on:
|
|
804
|
+
</Typography>
|
|
805
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
806
|
+
<li><Typography variant="omega"><strong>On Success</strong> - Alert when sync completes successfully</Typography></li>
|
|
807
|
+
<li><Typography variant="omega"><strong>On Failure</strong> - Alert when sync fails with an error</Typography></li>
|
|
808
|
+
</ul>
|
|
809
|
+
<Typography variant="pi" textColor="neutral600" paddingTop={2}>
|
|
810
|
+
Tip: Enable "On Failure" for all channels, but only enable "On Success" where needed to avoid alert fatigue.
|
|
811
|
+
</Typography>
|
|
812
|
+
</HelpSection>
|
|
813
|
+
|
|
814
|
+
<HelpSection title="Testing Alerts">
|
|
815
|
+
<Typography variant="omega">
|
|
816
|
+
Use the <strong>Test</strong> button next to each channel to send a test notification.
|
|
817
|
+
This helps verify your configuration before relying on it for real alerts.
|
|
818
|
+
</Typography>
|
|
819
|
+
</HelpSection>
|
|
820
|
+
</Box>
|
|
821
|
+
</Tabs.Content>
|
|
822
|
+
|
|
823
|
+
{/* Troubleshooting Tab */}
|
|
824
|
+
<Tabs.Content value="troubleshooting">
|
|
825
|
+
<Box paddingTop={4}>
|
|
826
|
+
<HelpSection title="Common Issues">
|
|
827
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
828
|
+
<Typography variant="sigma" textColor="danger700">Remote server not configured</Typography>
|
|
829
|
+
<Typography variant="omega" paddingTop={1}>
|
|
830
|
+
Go to Configuration → Connection and enter the Base URL and API Token for the remote server.
|
|
831
|
+
</Typography>
|
|
832
|
+
</Box>
|
|
833
|
+
|
|
834
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
835
|
+
<Typography variant="sigma" textColor="danger700">No content types configured for sync</Typography>
|
|
836
|
+
<Typography variant="omega" paddingTop={1}>
|
|
837
|
+
Go to Content Types tab and enable at least one content type for synchronization.
|
|
838
|
+
</Typography>
|
|
839
|
+
</Box>
|
|
840
|
+
|
|
841
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
842
|
+
<Typography variant="sigma" textColor="danger700">401 Unauthorized</Typography>
|
|
843
|
+
<Typography variant="omega" paddingTop={1}>
|
|
844
|
+
The API token is invalid or expired. Generate a new token on the remote server and update
|
|
845
|
+
Configuration → Connection → API Token.
|
|
846
|
+
</Typography>
|
|
847
|
+
</Box>
|
|
848
|
+
|
|
849
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
850
|
+
<Typography variant="sigma" textColor="danger700">HMAC signature verification failed</Typography>
|
|
851
|
+
<Typography variant="omega" paddingTop={1}>
|
|
852
|
+
The shared secret does not match between instances. Ensure both instances have exactly
|
|
853
|
+
the same value in Configuration → Connection → Shared Secret.
|
|
854
|
+
</Typography>
|
|
855
|
+
</Box>
|
|
856
|
+
|
|
857
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
858
|
+
<Typography variant="sigma" textColor="danger700">Content type not found on remote</Typography>
|
|
859
|
+
<Typography variant="omega" paddingTop={1}>
|
|
860
|
+
The content type exists locally but not on the remote server. Ensure both instances
|
|
861
|
+
have matching content type definitions.
|
|
862
|
+
</Typography>
|
|
863
|
+
</Box>
|
|
864
|
+
|
|
865
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
866
|
+
<Typography variant="sigma" textColor="danger700">Schema mismatch error</Typography>
|
|
867
|
+
<Typography variant="omega" paddingTop={1}>
|
|
868
|
+
Content type schemas don't match between instances. Either update schemas to match,
|
|
869
|
+
or change Enforcement → Schema Match to "Compatible" or "None".
|
|
870
|
+
</Typography>
|
|
871
|
+
</Box>
|
|
872
|
+
|
|
873
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
874
|
+
<Typography variant="sigma" textColor="danger700">Email test failed - SMTP not configured</Typography>
|
|
875
|
+
<Typography variant="omega" paddingTop={1}>
|
|
876
|
+
Complete all SMTP fields in Configuration → Alerts → Email including host, username,
|
|
877
|
+
password, and from address.
|
|
878
|
+
</Typography>
|
|
879
|
+
</Box>
|
|
880
|
+
|
|
881
|
+
<Box background="danger100" padding={4} hasRadius marginBottom={4}>
|
|
882
|
+
<Typography variant="sigma" textColor="danger700">Time sync check failed</Typography>
|
|
883
|
+
<Typography variant="omega" paddingTop={1}>
|
|
884
|
+
Server clocks are too far apart. Sync server times using NTP, or increase the
|
|
885
|
+
Max Time Drift in Enforcement settings.
|
|
886
|
+
</Typography>
|
|
887
|
+
</Box>
|
|
888
|
+
</HelpSection>
|
|
889
|
+
|
|
890
|
+
<HelpSection title="Best Practices">
|
|
891
|
+
<ul style={{ paddingLeft: '20px', lineHeight: '2' }}>
|
|
892
|
+
<li><Typography variant="omega">Use <strong>Unlimited</strong> token duration to avoid sync failures from expired tokens</Typography></li>
|
|
893
|
+
<li><Typography variant="omega">Start with a single content type to test sync before enabling more</Typography></li>
|
|
894
|
+
<li><Typography variant="omega">Use <strong>On Demand</strong> mode initially to validate configuration</Typography></li>
|
|
895
|
+
<li><Typography variant="omega">Monitor the <strong>Logs</strong> tab regularly for errors</Typography></li>
|
|
896
|
+
<li><Typography variant="omega">Keep content type schemas identical on both instances</Typography></li>
|
|
897
|
+
<li><Typography variant="omega">Use strong, unique shared secrets (32+ random characters)</Typography></li>
|
|
898
|
+
<li><Typography variant="omega">Configure email alerts for failures at minimum</Typography></li>
|
|
899
|
+
<li><Typography variant="omega">Test with non-critical content types first</Typography></li>
|
|
900
|
+
<li><Typography variant="omega">Use <strong>Latest Wins</strong> conflict strategy unless you have a specific need</Typography></li>
|
|
901
|
+
</ul>
|
|
902
|
+
</HelpSection>
|
|
903
|
+
|
|
904
|
+
<HelpSection title="Viewing Logs">
|
|
905
|
+
<Typography variant="omega">
|
|
906
|
+
The <strong>Logs</strong> tab shows a detailed history of all sync operations:
|
|
907
|
+
</Typography>
|
|
908
|
+
<ul style={{ paddingLeft: '20px', marginTop: '8px', lineHeight: '1.8' }}>
|
|
909
|
+
<li><Typography variant="omega">Timestamp of each operation</Typography></li>
|
|
910
|
+
<li><Typography variant="omega">Content type and record identifier</Typography></li>
|
|
911
|
+
<li><Typography variant="omega">Direction (push/pull/system)</Typography></li>
|
|
912
|
+
<li><Typography variant="omega">Status (success/error)</Typography></li>
|
|
913
|
+
<li><Typography variant="omega">Error messages for failed operations</Typography></li>
|
|
914
|
+
</ul>
|
|
915
|
+
</HelpSection>
|
|
916
|
+
|
|
917
|
+
<Box paddingTop={4}>
|
|
918
|
+
<Typography variant="delta" tag="h3">External Resources</Typography>
|
|
919
|
+
<Box paddingTop={2}>
|
|
920
|
+
<DocLink href="https://docs.strapi.io/dev-docs/api/rest">
|
|
921
|
+
Strapi REST API Documentation
|
|
922
|
+
</DocLink>
|
|
923
|
+
</Box>
|
|
924
|
+
<Box paddingTop={2}>
|
|
925
|
+
<DocLink href="https://docs.strapi.io/dev-docs/backend-customization/middlewares">
|
|
926
|
+
Strapi Middlewares Documentation
|
|
927
|
+
</DocLink>
|
|
928
|
+
</Box>
|
|
929
|
+
<Box paddingTop={2}>
|
|
930
|
+
<DocLink href="https://docs.strapi.io/user-docs/settings/api-tokens">
|
|
931
|
+
API Tokens Guide
|
|
932
|
+
</DocLink>
|
|
933
|
+
</Box>
|
|
934
|
+
<Box paddingTop={2}>
|
|
935
|
+
<DocLink href="https://github.com/eharain/strapi-plugins-strapi-content-sync-pro/issues">
|
|
936
|
+
Report an Issue on GitHub
|
|
937
|
+
</DocLink>
|
|
938
|
+
</Box>
|
|
939
|
+
</Box>
|
|
940
|
+
</Box>
|
|
941
|
+
</Tabs.Content>
|
|
942
|
+
</Tabs.Root>
|
|
943
|
+
</Box>
|
|
944
|
+
);
|
|
945
|
+
};
|