@localazy/strapi-plugin 1.4.0 → 1.7.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/README.md +30 -0
- package/dist/_chunks/{FetchIdentity-BpFOT163.js → FetchIdentity-D89DgpbN.js} +24 -32
- package/dist/_chunks/{FetchIdentity-Cor4ooZv.mjs → FetchIdentity-DkHj24S5.mjs} +36 -44
- package/dist/_chunks/{LanguagesSelector-CC1ecWnc.js → LanguagesSelector-638KGQYw.js} +3 -2
- package/dist/_chunks/{LanguagesSelector-BbrMKwQY.mjs → LanguagesSelector-CR_7I2R1.mjs} +4 -3
- package/dist/_chunks/{LocalazyApp-D0JGRQeF.js → LocalazyApp-Benn8pkA.js} +75 -39
- package/dist/_chunks/{LocalazyApp-DpFR8p10.mjs → LocalazyApp-DM3zg5E4.mjs} +70 -34
- package/dist/_chunks/{LocalazyContentTransferSetup-Dael1Q4w.mjs → LocalazyContentTransferSetup-BA_rtSBM.mjs} +58 -22
- package/dist/_chunks/{LocalazyContentTransferSetup-Cr7D-BUi.js → LocalazyContentTransferSetup-CWchyGdD.js} +62 -26
- package/dist/_chunks/{LocalazyGlobalSettings-D3nG4zl7.js → LocalazyGlobalSettings-88jqQbD4.js} +56 -25
- package/dist/_chunks/{LocalazyGlobalSettings-DzBI5M-K.mjs → LocalazyGlobalSettings-BWF0s9tM.mjs} +56 -25
- package/dist/_chunks/{LocalazyPanel-W6j8N1WC.mjs → LocalazyPanel-4HRa1jNl.mjs} +12 -6
- package/dist/_chunks/{LocalazyPanel-KQPLxTDz.js → LocalazyPanel-D0w9JSIS.js} +14 -8
- package/dist/_chunks/{LocalazyStatusColumn-B7Q_U2Lu.js → LocalazyStatusColumn-BR3f8rKp.js} +10 -4
- package/dist/_chunks/{LocalazyStatusColumn-CrhsCjgp.mjs → LocalazyStatusColumn-D4-rZZUK.mjs} +10 -4
- package/dist/_chunks/{RequireLocalazyAuth-D3GeZPDh.js → RequireLocalazyAuth-C442750b.js} +30 -3
- package/dist/_chunks/{RequireLocalazyAuth-BwoGRfJq.mjs → RequireLocalazyAuth-DbNjEOq-.mjs} +32 -5
- package/dist/_chunks/{entry-exclusion-service-D7gaRHPE.mjs → entry-exclusion-service-Bd3mUDde.mjs} +1 -1
- package/dist/_chunks/{entry-exclusion-service-Bwruvyce.js → entry-exclusion-service-CAIcybXX.js} +1 -1
- package/dist/_chunks/{has-model-changed-Dp2Vkwjw.mjs → has-model-changed-BNs3d9q5.mjs} +4 -3
- package/dist/_chunks/{has-model-changed-5IV9WI_-.js → has-model-changed-BrDeyHFt.js} +4 -3
- package/dist/_chunks/{i18n-o24yXf-j.mjs → i18n-76ox2llT.mjs} +4 -1
- package/dist/_chunks/{i18n-C_5tJvr0.js → i18n-C5ucROBh.js} +4 -1
- package/dist/_chunks/{index-C9hN3KbD.mjs → index-C9Px4v-A.mjs} +34 -12
- package/dist/_chunks/{index-jAg6jjCu.js → index-DwFm1TyM.js} +33 -11
- package/dist/_chunks/{index-BjL9XpRh.mjs → index-shryj0jT.mjs} +16 -16
- package/dist/_chunks/{strapi-api-base-IG3Pe5Sg.js → strapi-api-base-BWZYbxxj.js} +1 -1
- package/dist/_chunks/{strapi-api-base-CAzGcwF6.mjs → strapi-api-base-lPo7wq6I.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/LocalazyStatusColumn.d.ts +1 -1
- package/dist/admin/src/constants/permissions.d.ts +29 -0
- package/dist/admin/src/modules/@common/components/LanguagesSelector.d.ts +1 -0
- package/dist/admin/src/modules/@common/models/supported-content-type-fields.d.ts +1 -1
- package/dist/admin/src/modules/login/locale/en.d.ts +1 -0
- package/dist/admin/src/modules/plugin-settings/components/Tree.d.ts +1 -0
- package/dist/admin/src/modules/plugin-settings/components/TreeItem.d.ts +1 -0
- package/dist/admin/src/modules/plugin-settings/components/WebhookSetup.d.ts +4 -1
- package/dist/admin/src/modules/plugin-settings/locale/en.d.ts +2 -0
- package/dist/admin/src/modules/plugin-settings/services/plugin-settings-service.d.ts +4 -0
- package/dist/server/index.js +422 -213
- package/dist/server/index.mjs +422 -213
- package/dist/server/src/bootstrap.d.ts +1 -1
- package/dist/server/src/constants/permissions.d.ts +38 -0
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/controllers/plugin-settings-controller.d.ts +1 -0
- package/dist/server/src/core/index.d.ts +3 -1
- package/dist/server/src/index.d.ts +57 -8
- package/dist/server/src/routes/activity-logs-routes.d.ts +20 -3
- package/dist/server/src/routes/debug-bundle-routes.d.ts +6 -1
- package/dist/server/src/routes/entry-exclusion-routes.d.ts +20 -3
- package/dist/server/src/routes/index.d.ts +52 -6
- package/dist/server/src/routes/localazy-auth-routes.d.ts +6 -1
- package/dist/server/src/routes/localazy-project-routes.d.ts +20 -3
- package/dist/server/src/routes/localazy-transfer-routes.d.ts +6 -1
- package/dist/server/src/routes/localazy-user-routes.d.ts +20 -3
- package/dist/server/src/routes/plugin-settings-routes.d.ts +20 -3
- package/dist/server/src/routes/strapi-routes.d.ts +20 -3
- package/dist/server/src/services/index.d.ts +3 -1
- package/dist/server/src/services/localazy-transfer-download-service.d.ts +2 -1
- package/dist/server/src/services/plugin-settings-service.d.ts +4 -0
- package/dist/server/src/utils/blocks-to-translatable.d.ts +34 -0
- package/dist/server/src/utils/model-utils.d.ts +2 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -20534,7 +20534,7 @@ var distExports = dist$1.exports;
|
|
|
20534
20534
|
const io = /* @__PURE__ */ getDefaultExportFromCjs(distExports);
|
|
20535
20535
|
const { Server: Server2, Namespace, Socket: Socket3 } = io;
|
|
20536
20536
|
const name = "@localazy/strapi-plugin";
|
|
20537
|
-
const version = "1.
|
|
20537
|
+
const version = "1.7.0";
|
|
20538
20538
|
const description = "The official Strapi Plugin by Localazy.";
|
|
20539
20539
|
const keywords = [
|
|
20540
20540
|
"strapi",
|
|
@@ -20718,7 +20718,60 @@ const _package$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
20718
20718
|
version
|
|
20719
20719
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
20720
20720
|
const PLUGIN_NAME = strapi$1.name;
|
|
20721
|
-
const
|
|
20721
|
+
const PERMISSION_UIDS = {
|
|
20722
|
+
READ: `plugin::${PLUGIN_NAME}.read`,
|
|
20723
|
+
TRANSFER: `plugin::${PLUGIN_NAME}.transfer`,
|
|
20724
|
+
SETTINGS_UPDATE: `plugin::${PLUGIN_NAME}.settings.update`
|
|
20725
|
+
};
|
|
20726
|
+
const LOCALAZY_RBAC_ACTIONS = [
|
|
20727
|
+
{
|
|
20728
|
+
section: "plugins",
|
|
20729
|
+
subCategory: "General",
|
|
20730
|
+
pluginName: PLUGIN_NAME,
|
|
20731
|
+
displayName: "Read",
|
|
20732
|
+
uid: "read"
|
|
20733
|
+
},
|
|
20734
|
+
{
|
|
20735
|
+
section: "plugins",
|
|
20736
|
+
subCategory: "General",
|
|
20737
|
+
pluginName: PLUGIN_NAME,
|
|
20738
|
+
displayName: "Transfer",
|
|
20739
|
+
uid: "transfer"
|
|
20740
|
+
},
|
|
20741
|
+
{
|
|
20742
|
+
section: "plugins",
|
|
20743
|
+
subCategory: "Settings",
|
|
20744
|
+
pluginName: PLUGIN_NAME,
|
|
20745
|
+
displayName: "Read settings",
|
|
20746
|
+
uid: "settings.read"
|
|
20747
|
+
},
|
|
20748
|
+
{
|
|
20749
|
+
section: "plugins",
|
|
20750
|
+
subCategory: "Settings",
|
|
20751
|
+
pluginName: PLUGIN_NAME,
|
|
20752
|
+
displayName: "Update settings",
|
|
20753
|
+
uid: "settings.update"
|
|
20754
|
+
}
|
|
20755
|
+
];
|
|
20756
|
+
const registerRbacActions = async (strapi2) => {
|
|
20757
|
+
try {
|
|
20758
|
+
const permissionService = strapi2.service("admin::permission");
|
|
20759
|
+
const actionProvider = permissionService?.actionProvider;
|
|
20760
|
+
if (!actionProvider?.registerMany) {
|
|
20761
|
+
strapi2.log.warn(
|
|
20762
|
+
`[${PLUGIN_NAME}] admin::permission.actionProvider unavailable — skipping RBAC action registration`
|
|
20763
|
+
);
|
|
20764
|
+
return;
|
|
20765
|
+
}
|
|
20766
|
+
await actionProvider.registerMany(LOCALAZY_RBAC_ACTIONS);
|
|
20767
|
+
} catch (error) {
|
|
20768
|
+
strapi2.log.error(
|
|
20769
|
+
`[${PLUGIN_NAME}] Failed to register RBAC actions — plugin permissions will not appear in role editor: ${error instanceof Error ? error.message : String(error)}`
|
|
20770
|
+
);
|
|
20771
|
+
}
|
|
20772
|
+
};
|
|
20773
|
+
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
20774
|
+
await registerRbacActions(strapi2);
|
|
20722
20775
|
if (strapi2.plugin(PLUGIN_NAME)?.config("enableSocketIO", true)) {
|
|
20723
20776
|
process.nextTick(async () => {
|
|
20724
20777
|
const io2 = new Server2(strapi2.server.httpServer, {
|
|
@@ -24301,6 +24354,9 @@ const PluginSettingsController = ({ strapi: _strapi }) => ({
|
|
|
24301
24354
|
async updatePluginSettings(ctx) {
|
|
24302
24355
|
ctx.body = await getPluginSettingsService().updatePluginSettings(ctx.request.body);
|
|
24303
24356
|
},
|
|
24357
|
+
async updatePluginSettingsUiPrefs(ctx) {
|
|
24358
|
+
ctx.body = await getPluginSettingsService().updatePluginSettingsUiPrefs(ctx.request.body);
|
|
24359
|
+
},
|
|
24304
24360
|
async getSyncCursor(ctx) {
|
|
24305
24361
|
ctx.body = await getPluginSettingsService().getSyncCursor();
|
|
24306
24362
|
}
|
|
@@ -24400,6 +24456,8 @@ const LocalazyTransferController = ({ strapi: strapi2 }) => ({
|
|
|
24400
24456
|
try {
|
|
24401
24457
|
const LocalazyTransferDownloadService2 = getLocalazyTransferDownloadService();
|
|
24402
24458
|
let fullSync = ctx.request.body?.fullSync === true;
|
|
24459
|
+
const rawUiLanguages = ctx.request.body?.uiLanguages;
|
|
24460
|
+
const requestedUiLanguages = Array.isArray(rawUiLanguages) && rawUiLanguages.every((code) => typeof code === "string") ? rawUiLanguages : void 0;
|
|
24403
24461
|
const requestInitiatorHelper = new RequestInitiatorHelper(strapi2);
|
|
24404
24462
|
if (requestInitiatorHelper.isInitiatedByLocalazyWebhook()) {
|
|
24405
24463
|
const pluginSettingsServiceHelper = new PluginSettingsServiceHelper();
|
|
@@ -24409,7 +24467,8 @@ const LocalazyTransferController = ({ strapi: strapi2 }) => ({
|
|
|
24409
24467
|
setTimeout(
|
|
24410
24468
|
() => LocalazyTransferDownloadService2.download({
|
|
24411
24469
|
notificationService: JobNotificationService$1,
|
|
24412
|
-
fullSync
|
|
24470
|
+
fullSync,
|
|
24471
|
+
requestedUiLanguages
|
|
24413
24472
|
}),
|
|
24414
24473
|
1e3
|
|
24415
24474
|
);
|
|
@@ -24978,13 +25037,17 @@ const middlewares = {
|
|
|
24978
25037
|
};
|
|
24979
25038
|
const policies = {};
|
|
24980
25039
|
const ROUTE_PREFIX$8 = "/user";
|
|
25040
|
+
const readPolicy$6 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25041
|
+
const settingsUpdatePolicy$4 = [
|
|
25042
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25043
|
+
];
|
|
24981
25044
|
const LocalazyUserRoutes = [
|
|
24982
25045
|
{
|
|
24983
25046
|
method: "GET",
|
|
24984
25047
|
path: `${ROUTE_PREFIX$8}`,
|
|
24985
25048
|
handler: "LocalazyUserController.getUser",
|
|
24986
25049
|
config: {
|
|
24987
|
-
policies:
|
|
25050
|
+
policies: readPolicy$6
|
|
24988
25051
|
}
|
|
24989
25052
|
},
|
|
24990
25053
|
{
|
|
@@ -24992,7 +25055,7 @@ const LocalazyUserRoutes = [
|
|
|
24992
25055
|
path: `${ROUTE_PREFIX$8}`,
|
|
24993
25056
|
handler: "LocalazyUserController.updateUser",
|
|
24994
25057
|
config: {
|
|
24995
|
-
policies:
|
|
25058
|
+
policies: settingsUpdatePolicy$4
|
|
24996
25059
|
}
|
|
24997
25060
|
},
|
|
24998
25061
|
{
|
|
@@ -25000,18 +25063,21 @@ const LocalazyUserRoutes = [
|
|
|
25000
25063
|
path: `${ROUTE_PREFIX$8}`,
|
|
25001
25064
|
handler: "LocalazyUserController.deleteUser",
|
|
25002
25065
|
config: {
|
|
25003
|
-
policies:
|
|
25066
|
+
policies: settingsUpdatePolicy$4
|
|
25004
25067
|
}
|
|
25005
25068
|
}
|
|
25006
25069
|
];
|
|
25007
25070
|
const ROUTE_PREFIX$7 = "/auth";
|
|
25071
|
+
const settingsUpdatePolicy$3 = [
|
|
25072
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25073
|
+
];
|
|
25008
25074
|
const LocalazyAuthRoutes = [
|
|
25009
25075
|
{
|
|
25010
25076
|
method: "GET",
|
|
25011
25077
|
path: `${ROUTE_PREFIX$7}/generate-keys`,
|
|
25012
25078
|
handler: "LocalazyAuthController.generateKeys",
|
|
25013
25079
|
config: {
|
|
25014
|
-
policies:
|
|
25080
|
+
policies: settingsUpdatePolicy$3
|
|
25015
25081
|
}
|
|
25016
25082
|
},
|
|
25017
25083
|
{
|
|
@@ -25019,18 +25085,26 @@ const LocalazyAuthRoutes = [
|
|
|
25019
25085
|
path: `${ROUTE_PREFIX$7}/continuous-poll`,
|
|
25020
25086
|
handler: "LocalazyAuthController.continuousPoll",
|
|
25021
25087
|
config: {
|
|
25022
|
-
policies:
|
|
25088
|
+
policies: settingsUpdatePolicy$3
|
|
25023
25089
|
}
|
|
25024
25090
|
}
|
|
25025
25091
|
];
|
|
25026
25092
|
const ROUTE_PREFIX$6 = "/plugin-settings";
|
|
25093
|
+
const readPolicy$5 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25094
|
+
const settingsUpdatePolicy$2 = [
|
|
25095
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25096
|
+
];
|
|
25027
25097
|
const PluginSettingsRoutes = [
|
|
25028
25098
|
{
|
|
25029
25099
|
method: "GET",
|
|
25030
25100
|
path: `${ROUTE_PREFIX$6}/content-transfer-setup`,
|
|
25031
25101
|
handler: "PluginSettingsController.getContentTransferSetup",
|
|
25032
25102
|
config: {
|
|
25033
|
-
|
|
25103
|
+
// Upload/Download pages call this to detect "model changed" before
|
|
25104
|
+
// transferring. Gating on `settings.read` would lock transfer-only
|
|
25105
|
+
// roles out of the transfer pages, so the read is open to any plugin
|
|
25106
|
+
// user. The destructive PUT below stays on `settings.update`.
|
|
25107
|
+
policies: readPolicy$5
|
|
25034
25108
|
}
|
|
25035
25109
|
},
|
|
25036
25110
|
{
|
|
@@ -25038,7 +25112,7 @@ const PluginSettingsRoutes = [
|
|
|
25038
25112
|
path: `${ROUTE_PREFIX$6}/content-transfer-setup`,
|
|
25039
25113
|
handler: "PluginSettingsController.updateContentTransferSetup",
|
|
25040
25114
|
config: {
|
|
25041
|
-
policies:
|
|
25115
|
+
policies: settingsUpdatePolicy$2
|
|
25042
25116
|
}
|
|
25043
25117
|
},
|
|
25044
25118
|
{
|
|
@@ -25046,7 +25120,7 @@ const PluginSettingsRoutes = [
|
|
|
25046
25120
|
path: `${ROUTE_PREFIX$6}/plugin-settings`,
|
|
25047
25121
|
handler: "PluginSettingsController.getPluginSettings",
|
|
25048
25122
|
config: {
|
|
25049
|
-
policies:
|
|
25123
|
+
policies: readPolicy$5
|
|
25050
25124
|
}
|
|
25051
25125
|
},
|
|
25052
25126
|
{
|
|
@@ -25054,7 +25128,20 @@ const PluginSettingsRoutes = [
|
|
|
25054
25128
|
path: `${ROUTE_PREFIX$6}/plugin-settings`,
|
|
25055
25129
|
handler: "PluginSettingsController.updatePluginSettings",
|
|
25056
25130
|
config: {
|
|
25057
|
-
|
|
25131
|
+
// Persists destructive Global Settings (webhookConfig, download.*, upload.*).
|
|
25132
|
+
// UI-pref-only writes use `PUT /plugin-settings/ui-prefs` (read-gated) below.
|
|
25133
|
+
policies: settingsUpdatePolicy$2
|
|
25134
|
+
}
|
|
25135
|
+
},
|
|
25136
|
+
{
|
|
25137
|
+
method: "PUT",
|
|
25138
|
+
path: `${ROUTE_PREFIX$6}/ui-prefs`,
|
|
25139
|
+
handler: "PluginSettingsController.updatePluginSettingsUiPrefs",
|
|
25140
|
+
config: {
|
|
25141
|
+
// Per-user UI state (last visited route, sort prefs). Service-side filters
|
|
25142
|
+
// the body to a fixed allowlist so a `read`-only caller cannot reach the
|
|
25143
|
+
// destructive fields that share the same plugin-settings store.
|
|
25144
|
+
policies: readPolicy$5
|
|
25058
25145
|
}
|
|
25059
25146
|
},
|
|
25060
25147
|
{
|
|
@@ -25062,18 +25149,22 @@ const PluginSettingsRoutes = [
|
|
|
25062
25149
|
path: `${ROUTE_PREFIX$6}/sync-cursor`,
|
|
25063
25150
|
handler: "PluginSettingsController.getSyncCursor",
|
|
25064
25151
|
config: {
|
|
25065
|
-
policies:
|
|
25152
|
+
policies: readPolicy$5
|
|
25066
25153
|
}
|
|
25067
25154
|
}
|
|
25068
25155
|
];
|
|
25069
25156
|
const ROUTE_PREFIX$5 = "/strapi";
|
|
25157
|
+
const readPolicy$4 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25158
|
+
const settingsUpdatePolicy$1 = [
|
|
25159
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25160
|
+
];
|
|
25070
25161
|
const StrapiRoutes = [
|
|
25071
25162
|
{
|
|
25072
25163
|
method: "GET",
|
|
25073
25164
|
path: `${ROUTE_PREFIX$5}/models`,
|
|
25074
25165
|
handler: "StrapiController.getModels",
|
|
25075
25166
|
config: {
|
|
25076
|
-
policies:
|
|
25167
|
+
policies: readPolicy$4
|
|
25077
25168
|
}
|
|
25078
25169
|
},
|
|
25079
25170
|
{
|
|
@@ -25081,7 +25172,7 @@ const StrapiRoutes = [
|
|
|
25081
25172
|
path: `${ROUTE_PREFIX$5}/localizable-models`,
|
|
25082
25173
|
handler: "StrapiController.getLocalizableModels",
|
|
25083
25174
|
config: {
|
|
25084
|
-
policies:
|
|
25175
|
+
policies: readPolicy$4
|
|
25085
25176
|
}
|
|
25086
25177
|
},
|
|
25087
25178
|
{
|
|
@@ -25089,7 +25180,7 @@ const StrapiRoutes = [
|
|
|
25089
25180
|
path: `${ROUTE_PREFIX$5}/lifecycle/localazy-webhooks`,
|
|
25090
25181
|
handler: "StrapiController.postLifecycleLocalazyWebhooks",
|
|
25091
25182
|
config: {
|
|
25092
|
-
policies:
|
|
25183
|
+
policies: settingsUpdatePolicy$1
|
|
25093
25184
|
}
|
|
25094
25185
|
},
|
|
25095
25186
|
{
|
|
@@ -25097,18 +25188,19 @@ const StrapiRoutes = [
|
|
|
25097
25188
|
path: `${ROUTE_PREFIX$5}/version`,
|
|
25098
25189
|
handler: "StrapiController.getPluginVersion",
|
|
25099
25190
|
config: {
|
|
25100
|
-
policies:
|
|
25191
|
+
policies: readPolicy$4
|
|
25101
25192
|
}
|
|
25102
25193
|
}
|
|
25103
25194
|
];
|
|
25104
25195
|
const ROUTE_PREFIX$4 = "/transfer";
|
|
25196
|
+
const transferPolicy$2 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.TRANSFER] } }];
|
|
25105
25197
|
const LocalazyTransferRoutes = [
|
|
25106
25198
|
{
|
|
25107
25199
|
method: "POST",
|
|
25108
25200
|
path: `${ROUTE_PREFIX$4}/upload`,
|
|
25109
25201
|
handler: "LocalazyTransferController.upload",
|
|
25110
25202
|
config: {
|
|
25111
|
-
policies:
|
|
25203
|
+
policies: transferPolicy$2
|
|
25112
25204
|
}
|
|
25113
25205
|
},
|
|
25114
25206
|
{
|
|
@@ -25116,18 +25208,22 @@ const LocalazyTransferRoutes = [
|
|
|
25116
25208
|
path: `${ROUTE_PREFIX$4}/download`,
|
|
25117
25209
|
handler: "LocalazyTransferController.download",
|
|
25118
25210
|
config: {
|
|
25119
|
-
policies:
|
|
25211
|
+
policies: transferPolicy$2
|
|
25120
25212
|
}
|
|
25121
25213
|
}
|
|
25122
25214
|
];
|
|
25123
25215
|
const ROUTE_PREFIX$3 = "/project";
|
|
25216
|
+
const readPolicy$3 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25217
|
+
const settingsUpdatePolicy = [
|
|
25218
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25219
|
+
];
|
|
25124
25220
|
const LocalazyProjectRoutes = [
|
|
25125
25221
|
{
|
|
25126
25222
|
method: "GET",
|
|
25127
25223
|
path: `${ROUTE_PREFIX$3}`,
|
|
25128
25224
|
handler: "LocalazyProjectController.getConnectedProject",
|
|
25129
25225
|
config: {
|
|
25130
|
-
policies:
|
|
25226
|
+
policies: readPolicy$3
|
|
25131
25227
|
}
|
|
25132
25228
|
},
|
|
25133
25229
|
{
|
|
@@ -25135,7 +25231,7 @@ const LocalazyProjectRoutes = [
|
|
|
25135
25231
|
path: `${ROUTE_PREFIX$3}/webhooks`,
|
|
25136
25232
|
handler: "LocalazyProjectController.getWebhookStatus",
|
|
25137
25233
|
config: {
|
|
25138
|
-
policies:
|
|
25234
|
+
policies: readPolicy$3
|
|
25139
25235
|
}
|
|
25140
25236
|
},
|
|
25141
25237
|
{
|
|
@@ -25143,7 +25239,7 @@ const LocalazyProjectRoutes = [
|
|
|
25143
25239
|
path: `${ROUTE_PREFIX$3}/webhooks/setup`,
|
|
25144
25240
|
handler: "LocalazyProjectController.setupWebhook",
|
|
25145
25241
|
config: {
|
|
25146
|
-
policies:
|
|
25242
|
+
policies: settingsUpdatePolicy
|
|
25147
25243
|
}
|
|
25148
25244
|
},
|
|
25149
25245
|
{
|
|
@@ -25151,7 +25247,7 @@ const LocalazyProjectRoutes = [
|
|
|
25151
25247
|
path: `${ROUTE_PREFIX$3}/strapi-url`,
|
|
25152
25248
|
handler: "LocalazyProjectController.getStrapiUrl",
|
|
25153
25249
|
config: {
|
|
25154
|
-
policies:
|
|
25250
|
+
policies: readPolicy$3
|
|
25155
25251
|
}
|
|
25156
25252
|
}
|
|
25157
25253
|
];
|
|
@@ -25170,13 +25266,15 @@ const LocalazyPublicTransferRoutes = [
|
|
|
25170
25266
|
}
|
|
25171
25267
|
];
|
|
25172
25268
|
const ROUTE_PREFIX$1 = "/entry-exclusion";
|
|
25269
|
+
const readPolicy$2 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25270
|
+
const transferPolicy$1 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.TRANSFER] } }];
|
|
25173
25271
|
const EntryExclusionRoutes = [
|
|
25174
25272
|
{
|
|
25175
25273
|
method: "GET",
|
|
25176
25274
|
path: `${ROUTE_PREFIX$1}/:contentType/:documentId`,
|
|
25177
25275
|
handler: "EntryExclusionController.getEntryExclusion",
|
|
25178
25276
|
config: {
|
|
25179
|
-
policies:
|
|
25277
|
+
policies: readPolicy$2
|
|
25180
25278
|
}
|
|
25181
25279
|
},
|
|
25182
25280
|
{
|
|
@@ -25184,7 +25282,7 @@ const EntryExclusionRoutes = [
|
|
|
25184
25282
|
path: `${ROUTE_PREFIX$1}/:contentType/:documentId`,
|
|
25185
25283
|
handler: "EntryExclusionController.setEntryExclusion",
|
|
25186
25284
|
config: {
|
|
25187
|
-
policies:
|
|
25285
|
+
policies: transferPolicy$1
|
|
25188
25286
|
}
|
|
25189
25287
|
},
|
|
25190
25288
|
{
|
|
@@ -25192,18 +25290,20 @@ const EntryExclusionRoutes = [
|
|
|
25192
25290
|
path: `${ROUTE_PREFIX$1}/:contentType`,
|
|
25193
25291
|
handler: "EntryExclusionController.getContentTypeExclusions",
|
|
25194
25292
|
config: {
|
|
25195
|
-
policies:
|
|
25293
|
+
policies: readPolicy$2
|
|
25196
25294
|
}
|
|
25197
25295
|
}
|
|
25198
25296
|
];
|
|
25199
25297
|
const ROUTE_PREFIX = "/activity-logs";
|
|
25298
|
+
const readPolicy$1 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25299
|
+
const transferPolicy = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.TRANSFER] } }];
|
|
25200
25300
|
const ActivityLogsRoutes = [
|
|
25201
25301
|
{
|
|
25202
25302
|
method: "GET",
|
|
25203
25303
|
path: `${ROUTE_PREFIX}`,
|
|
25204
25304
|
handler: "ActivityLogsController.getSessions",
|
|
25205
25305
|
config: {
|
|
25206
|
-
policies:
|
|
25306
|
+
policies: readPolicy$1
|
|
25207
25307
|
}
|
|
25208
25308
|
},
|
|
25209
25309
|
{
|
|
@@ -25211,7 +25311,7 @@ const ActivityLogsRoutes = [
|
|
|
25211
25311
|
path: `${ROUTE_PREFIX}/export`,
|
|
25212
25312
|
handler: "ActivityLogsController.exportSessions",
|
|
25213
25313
|
config: {
|
|
25214
|
-
policies:
|
|
25314
|
+
policies: readPolicy$1
|
|
25215
25315
|
}
|
|
25216
25316
|
},
|
|
25217
25317
|
{
|
|
@@ -25219,7 +25319,7 @@ const ActivityLogsRoutes = [
|
|
|
25219
25319
|
path: `${ROUTE_PREFIX}/:sessionId`,
|
|
25220
25320
|
handler: "ActivityLogsController.getSession",
|
|
25221
25321
|
config: {
|
|
25222
|
-
policies:
|
|
25322
|
+
policies: readPolicy$1
|
|
25223
25323
|
}
|
|
25224
25324
|
},
|
|
25225
25325
|
{
|
|
@@ -25227,23 +25327,28 @@ const ActivityLogsRoutes = [
|
|
|
25227
25327
|
path: `${ROUTE_PREFIX}`,
|
|
25228
25328
|
handler: "ActivityLogsController.clearSessions",
|
|
25229
25329
|
config: {
|
|
25230
|
-
policies:
|
|
25330
|
+
policies: transferPolicy
|
|
25231
25331
|
}
|
|
25232
25332
|
}
|
|
25233
25333
|
];
|
|
25334
|
+
const readPolicy = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25234
25335
|
const DebugBundleRoutes = [
|
|
25235
25336
|
{
|
|
25236
25337
|
method: "GET",
|
|
25237
25338
|
path: "/activity-logs/:sessionId/bundle",
|
|
25238
25339
|
handler: "DebugBundleController.getBundle",
|
|
25239
25340
|
config: {
|
|
25240
|
-
policies:
|
|
25341
|
+
policies: readPolicy
|
|
25241
25342
|
}
|
|
25242
25343
|
}
|
|
25243
25344
|
];
|
|
25345
|
+
const withoutAdminPolicies = (routes2) => routes2.map((route) => ({
|
|
25346
|
+
...route,
|
|
25347
|
+
config: { ...route.config, policies: [] }
|
|
25348
|
+
}));
|
|
25244
25349
|
const routes = {
|
|
25245
25350
|
"content-api": {
|
|
25246
|
-
routes:
|
|
25351
|
+
routes: withoutAdminPolicies(StrapiRoutes)
|
|
25247
25352
|
},
|
|
25248
25353
|
admin: {
|
|
25249
25354
|
type: "admin",
|
|
@@ -25455,6 +25560,7 @@ const KEY$1 = "sync-cursor";
|
|
|
25455
25560
|
const emptySyncCursor = {
|
|
25456
25561
|
processedKeys: {}
|
|
25457
25562
|
};
|
|
25563
|
+
const UI_PREF_FIELDS = ["defaultRoute", "activityLogsSort"];
|
|
25458
25564
|
const PluginSettingsService = ({ strapi: strapi2 }) => ({
|
|
25459
25565
|
async getContentTransferSetup() {
|
|
25460
25566
|
const pluginStore = getStrapiStore(strapi2);
|
|
@@ -25491,6 +25597,20 @@ const PluginSettingsService = ({ strapi: strapi2 }) => ({
|
|
|
25491
25597
|
});
|
|
25492
25598
|
return newSettings;
|
|
25493
25599
|
},
|
|
25600
|
+
// Counterpart to `updatePluginSettings` for the `read`-gated UI-prefs route.
|
|
25601
|
+
// Drops any field outside `UI_PREF_FIELDS` server-side so a `read`-only caller
|
|
25602
|
+
// cannot reach `webhookConfig` / `download.*` / `upload.*` via the merge.
|
|
25603
|
+
async updatePluginSettingsUiPrefs(prefs) {
|
|
25604
|
+
const sanitized = {};
|
|
25605
|
+
if (prefs && typeof prefs === "object") {
|
|
25606
|
+
for (const field of UI_PREF_FIELDS) {
|
|
25607
|
+
if (field in prefs) {
|
|
25608
|
+
sanitized[field] = prefs[field];
|
|
25609
|
+
}
|
|
25610
|
+
}
|
|
25611
|
+
}
|
|
25612
|
+
return this.updatePluginSettings(sanitized);
|
|
25613
|
+
},
|
|
25494
25614
|
async getSyncCursor() {
|
|
25495
25615
|
const pluginStore = getStrapiStore(strapi2);
|
|
25496
25616
|
const cursor = await pluginStore.get({ key: KEY$1 });
|
|
@@ -25505,182 +25625,6 @@ const PluginSettingsService = ({ strapi: strapi2 }) => ({
|
|
|
25505
25625
|
return cursor;
|
|
25506
25626
|
}
|
|
25507
25627
|
});
|
|
25508
|
-
const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
25509
|
-
async upload({ notificationService }) {
|
|
25510
|
-
console.time("upload");
|
|
25511
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25512
|
-
message: "Upload started"
|
|
25513
|
-
});
|
|
25514
|
-
const activityLogsService = getActivityLogsService();
|
|
25515
|
-
const sessionId = await activityLogsService.startSession("upload", "Strapi User");
|
|
25516
|
-
await activityLogsService.addEntry(sessionId, "Upload started");
|
|
25517
|
-
let success = true;
|
|
25518
|
-
const StrapiService2 = getStrapiService();
|
|
25519
|
-
const StrapiI18nService2 = getStrapiI18nService();
|
|
25520
|
-
const LocalazyUploadService2 = getLocalazyUploadService();
|
|
25521
|
-
const EntryExclusionService2 = getEntryExclusionService();
|
|
25522
|
-
const contentTransferSetup = await getPluginSettingsService().getContentTransferSetup();
|
|
25523
|
-
if (!contentTransferSetup.has_setup) {
|
|
25524
|
-
const message = "Content transfer setup is not set up.";
|
|
25525
|
-
success = false;
|
|
25526
|
-
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
25527
|
-
success,
|
|
25528
|
-
message
|
|
25529
|
-
});
|
|
25530
|
-
await activityLogsService.addEntry(sessionId, message);
|
|
25531
|
-
await activityLogsService.finishSession(sessionId, "failed", message);
|
|
25532
|
-
strapi2.log.info(message);
|
|
25533
|
-
return;
|
|
25534
|
-
}
|
|
25535
|
-
const { setup: setup2 } = contentTransferSetup;
|
|
25536
|
-
const collectionsNames = getCollectionsNames(setup2);
|
|
25537
|
-
const models = await StrapiService2.getModels();
|
|
25538
|
-
const strapiDefaultLocaleCode = await StrapiI18nService2.getDefaultLocaleCode();
|
|
25539
|
-
const attemptedTuples = [];
|
|
25540
|
-
let pickedFlattenStrapiContent = {};
|
|
25541
|
-
for (const collectionName of collectionsNames) {
|
|
25542
|
-
const currentModel = models.find((model) => model.collectionName === collectionName);
|
|
25543
|
-
const modelUid = currentModel.uid;
|
|
25544
|
-
if (!currentModel) {
|
|
25545
|
-
strapi2.log.warn(`Model with uid ${modelUid} is not found.`);
|
|
25546
|
-
continue;
|
|
25547
|
-
}
|
|
25548
|
-
const transferSetupModel = findSetupModelByCollectionName(setup2, collectionName);
|
|
25549
|
-
if (!isCollectionTransferEnabled(setup2, collectionName)) {
|
|
25550
|
-
const message2 = `Collection ${collectionName} transfer is disabled.`;
|
|
25551
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25552
|
-
message: message2
|
|
25553
|
-
});
|
|
25554
|
-
await activityLogsService.addEntry(sessionId, message2);
|
|
25555
|
-
strapi2.log.info(message2);
|
|
25556
|
-
continue;
|
|
25557
|
-
}
|
|
25558
|
-
const currentTransferSetupModel = transferSetupModel[collectionName];
|
|
25559
|
-
const pickPaths = getPickPathsWithComponents(currentTransferSetupModel);
|
|
25560
|
-
if (!pickPaths.length) {
|
|
25561
|
-
const message2 = `No fields for collection ${collectionName} transfer are enabled.`;
|
|
25562
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25563
|
-
message: message2
|
|
25564
|
-
});
|
|
25565
|
-
await activityLogsService.addEntry(sessionId, message2);
|
|
25566
|
-
strapi2.log.warn(message2);
|
|
25567
|
-
continue;
|
|
25568
|
-
}
|
|
25569
|
-
const pickPathsWithUid = pickPaths.map((pickPath) => `${modelUid}.${pickPath}`);
|
|
25570
|
-
let entries = await strapi2.documents(modelUid).findMany({
|
|
25571
|
-
locUploadPLevel: 6,
|
|
25572
|
-
status: "draft"
|
|
25573
|
-
});
|
|
25574
|
-
if (!entries.length) {
|
|
25575
|
-
strapi2.log.info(`No entries found for model ${modelUid}`);
|
|
25576
|
-
continue;
|
|
25577
|
-
}
|
|
25578
|
-
const excludedEntries = await EntryExclusionService2.getContentTypeExclusions(modelUid);
|
|
25579
|
-
const filteredEntries = [];
|
|
25580
|
-
for (const entry of entries) {
|
|
25581
|
-
const isExcluded = excludedEntries.includes(entry.documentId);
|
|
25582
|
-
if (!isExcluded) {
|
|
25583
|
-
filteredEntries.push(entry);
|
|
25584
|
-
}
|
|
25585
|
-
}
|
|
25586
|
-
entries = filteredEntries;
|
|
25587
|
-
if (!entries.length) {
|
|
25588
|
-
const message2 = `All entries for model ${collectionName} are excluded from translation`;
|
|
25589
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25590
|
-
message: message2
|
|
25591
|
-
});
|
|
25592
|
-
await activityLogsService.addEntry(sessionId, message2);
|
|
25593
|
-
strapi2.log.info(message2);
|
|
25594
|
-
continue;
|
|
25595
|
-
}
|
|
25596
|
-
const message = `Excluding ${excludedEntries.length} entries for model ${collectionName} from upload. Entries to translate: ${entries.length}.`;
|
|
25597
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25598
|
-
message
|
|
25599
|
-
});
|
|
25600
|
-
await activityLogsService.addEntry(sessionId, message);
|
|
25601
|
-
strapi2.log.info(message);
|
|
25602
|
-
if (strapiDefaultLocaleCode) {
|
|
25603
|
-
for (const entry of entries) {
|
|
25604
|
-
attemptedTuples.push({
|
|
25605
|
-
uid: modelUid,
|
|
25606
|
-
documentId: entry.documentId,
|
|
25607
|
-
locale: strapiDefaultLocaleCode
|
|
25608
|
-
});
|
|
25609
|
-
}
|
|
25610
|
-
}
|
|
25611
|
-
entries = omitDeep(entries, ["locale", "createdAt", "updatedAt", "publishedAt"]);
|
|
25612
|
-
entries.forEach((entry) => {
|
|
25613
|
-
const flatten = flattenObject({
|
|
25614
|
-
[modelUid]: entry
|
|
25615
|
-
});
|
|
25616
|
-
const pickedFlatten = pickEntries(flatten, pickPathsWithUid);
|
|
25617
|
-
pickedFlattenStrapiContent = {
|
|
25618
|
-
...pickedFlattenStrapiContent,
|
|
25619
|
-
...pickedFlatten
|
|
25620
|
-
};
|
|
25621
|
-
});
|
|
25622
|
-
const characterLimitsMetadata = getCharacterLimitsMetadata(pickedFlattenStrapiContent, modelUid);
|
|
25623
|
-
pickedFlattenStrapiContent = {
|
|
25624
|
-
...pickedFlattenStrapiContent,
|
|
25625
|
-
...characterLimitsMetadata
|
|
25626
|
-
};
|
|
25627
|
-
}
|
|
25628
|
-
const localazyLocaleCode = strapiDefaultLocaleCode ? isoStrapiToLocalazy(strapiDefaultLocaleCode) : config.default.LOCALAZY_DEFAULT_LOCALE;
|
|
25629
|
-
const importFile = LocalazyUploadService2.createImportFileRepresentation(
|
|
25630
|
-
localazyLocaleCode,
|
|
25631
|
-
pickedFlattenStrapiContent
|
|
25632
|
-
);
|
|
25633
|
-
const uploadConfig = {
|
|
25634
|
-
contentOptions: {
|
|
25635
|
-
type: config.default.LOCALAZY_DEFAULT_FILE_EXTENSION
|
|
25636
|
-
},
|
|
25637
|
-
i18nOptions: { deprecate: "file" },
|
|
25638
|
-
fileOptions: {
|
|
25639
|
-
name: config.default.LOCALAZY_DEFAULT_FILE_NAME,
|
|
25640
|
-
path: config.default.LOCALAZY_DEFAULT_FILE_PATH
|
|
25641
|
-
}
|
|
25642
|
-
};
|
|
25643
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25644
|
-
message: "Uploading collections to Localazy..."
|
|
25645
|
-
});
|
|
25646
|
-
await activityLogsService.addEntry(sessionId, "Uploading collections to Localazy...");
|
|
25647
|
-
try {
|
|
25648
|
-
await LocalazyUploadService2.upload(importFile, uploadConfig);
|
|
25649
|
-
await activityLogsService.recordAttemptedEntries(
|
|
25650
|
-
sessionId,
|
|
25651
|
-
attemptedTuples.map((t3) => ({ ...t3, status: "success" }))
|
|
25652
|
-
);
|
|
25653
|
-
} catch (error) {
|
|
25654
|
-
success = false;
|
|
25655
|
-
const errorMessage = `Upload to Localazy failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
25656
|
-
strapi2.log.error(errorMessage);
|
|
25657
|
-
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
25658
|
-
success,
|
|
25659
|
-
message: errorMessage
|
|
25660
|
-
});
|
|
25661
|
-
await activityLogsService.addEntry(sessionId, errorMessage);
|
|
25662
|
-
await activityLogsService.recordAttemptedEntries(
|
|
25663
|
-
sessionId,
|
|
25664
|
-
attemptedTuples.map((t3) => ({ ...t3, status: "failed", errorMessage }))
|
|
25665
|
-
);
|
|
25666
|
-
await activityLogsService.finishSession(sessionId, "failed", errorMessage);
|
|
25667
|
-
console.timeEnd("upload");
|
|
25668
|
-
return;
|
|
25669
|
-
}
|
|
25670
|
-
strapi2.log.info("Upload finished in");
|
|
25671
|
-
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
25672
|
-
success,
|
|
25673
|
-
message: "Upload finished"
|
|
25674
|
-
});
|
|
25675
|
-
await activityLogsService.addEntry(sessionId, "Upload finished");
|
|
25676
|
-
await activityLogsService.finishSession(
|
|
25677
|
-
sessionId,
|
|
25678
|
-
success ? "completed" : "failed",
|
|
25679
|
-
success ? "Upload completed successfully" : "Upload finished with errors"
|
|
25680
|
-
);
|
|
25681
|
-
console.timeEnd("upload");
|
|
25682
|
-
}
|
|
25683
|
-
});
|
|
25684
25628
|
var symbolTag$2 = "[object Symbol]";
|
|
25685
25629
|
function isSymbol(value) {
|
|
25686
25630
|
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag$2;
|
|
@@ -25995,6 +25939,263 @@ function baseSet(object, path, value, customizer) {
|
|
|
25995
25939
|
function set(object, path, value) {
|
|
25996
25940
|
return object == null ? object : baseSet(object, path, value);
|
|
25997
25941
|
}
|
|
25942
|
+
const BLOCKS_ATTRIBUTE_TYPE = "blocks";
|
|
25943
|
+
const projectBlocksFields = (entry, model, getModel) => {
|
|
25944
|
+
const cloned = cloneDeep(entry);
|
|
25945
|
+
walkAndProject(cloned, model, getModel);
|
|
25946
|
+
return cloned;
|
|
25947
|
+
};
|
|
25948
|
+
const walkAndProject = (value, model, getModel) => {
|
|
25949
|
+
if (!value || !model?.attributes) {
|
|
25950
|
+
return;
|
|
25951
|
+
}
|
|
25952
|
+
for (const [attributeName, attribute] of Object.entries(model.attributes)) {
|
|
25953
|
+
const fieldValue = value[attributeName];
|
|
25954
|
+
if (fieldValue === void 0 || fieldValue === null) {
|
|
25955
|
+
continue;
|
|
25956
|
+
}
|
|
25957
|
+
if (attribute.type === BLOCKS_ATTRIBUTE_TYPE) {
|
|
25958
|
+
value[attributeName] = projectBlocksValue(fieldValue);
|
|
25959
|
+
} else if (attribute.type === "component") {
|
|
25960
|
+
const componentModel = getModel(attribute.component);
|
|
25961
|
+
if (attribute.repeatable && Array.isArray(fieldValue)) {
|
|
25962
|
+
fieldValue.forEach((item) => walkAndProject(item, componentModel, getModel));
|
|
25963
|
+
} else if (isPlainObject(fieldValue)) {
|
|
25964
|
+
walkAndProject(fieldValue, componentModel, getModel);
|
|
25965
|
+
}
|
|
25966
|
+
} else if (attribute.type === "dynamiczone" && Array.isArray(fieldValue)) {
|
|
25967
|
+
fieldValue.forEach((item) => {
|
|
25968
|
+
if (item?.__component) {
|
|
25969
|
+
walkAndProject(item, getModel(item.__component), getModel);
|
|
25970
|
+
}
|
|
25971
|
+
});
|
|
25972
|
+
}
|
|
25973
|
+
}
|
|
25974
|
+
};
|
|
25975
|
+
const projectBlocksValue = (nodes) => {
|
|
25976
|
+
if (!Array.isArray(nodes)) {
|
|
25977
|
+
return nodes;
|
|
25978
|
+
}
|
|
25979
|
+
return nodes.map(projectNode);
|
|
25980
|
+
};
|
|
25981
|
+
const projectNode = (node) => {
|
|
25982
|
+
if (!isPlainObject(node)) {
|
|
25983
|
+
return {};
|
|
25984
|
+
}
|
|
25985
|
+
const projected = {};
|
|
25986
|
+
if (typeof node.text === "string") {
|
|
25987
|
+
projected.text = node.text;
|
|
25988
|
+
}
|
|
25989
|
+
if (Array.isArray(node.children)) {
|
|
25990
|
+
projected.children = node.children.map(projectNode);
|
|
25991
|
+
}
|
|
25992
|
+
return projected;
|
|
25993
|
+
};
|
|
25994
|
+
const overlayBlocksTranslation = (sourceAst, translated) => {
|
|
25995
|
+
if (!Array.isArray(sourceAst)) {
|
|
25996
|
+
return void 0;
|
|
25997
|
+
}
|
|
25998
|
+
return sourceAst.map((node, index2) => overlayNode(node, get(translated, [String(index2)])));
|
|
25999
|
+
};
|
|
26000
|
+
const overlayNode = (node, translatedNode) => {
|
|
26001
|
+
if (!isPlainObject(node)) {
|
|
26002
|
+
return cloneDeep(node);
|
|
26003
|
+
}
|
|
26004
|
+
if (typeof node.text === "string") {
|
|
26005
|
+
const translatedText = isPlainObject(translatedNode) ? translatedNode.text : void 0;
|
|
26006
|
+
return typeof translatedText === "string" ? { ...node, text: translatedText } : cloneDeep(node);
|
|
26007
|
+
}
|
|
26008
|
+
if (Array.isArray(node.children)) {
|
|
26009
|
+
return {
|
|
26010
|
+
...node,
|
|
26011
|
+
children: node.children.map(
|
|
26012
|
+
(child, index2) => overlayNode(child, translatedNode ? get(translatedNode, ["children", String(index2)]) : void 0)
|
|
26013
|
+
)
|
|
26014
|
+
};
|
|
26015
|
+
}
|
|
26016
|
+
return cloneDeep(node);
|
|
26017
|
+
};
|
|
26018
|
+
const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
26019
|
+
async upload({ notificationService }) {
|
|
26020
|
+
console.time("upload");
|
|
26021
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26022
|
+
message: "Upload started"
|
|
26023
|
+
});
|
|
26024
|
+
const activityLogsService = getActivityLogsService();
|
|
26025
|
+
const sessionId = await activityLogsService.startSession("upload", "Strapi User");
|
|
26026
|
+
await activityLogsService.addEntry(sessionId, "Upload started");
|
|
26027
|
+
let success = true;
|
|
26028
|
+
const StrapiService2 = getStrapiService();
|
|
26029
|
+
const StrapiI18nService2 = getStrapiI18nService();
|
|
26030
|
+
const LocalazyUploadService2 = getLocalazyUploadService();
|
|
26031
|
+
const EntryExclusionService2 = getEntryExclusionService();
|
|
26032
|
+
const contentTransferSetup = await getPluginSettingsService().getContentTransferSetup();
|
|
26033
|
+
if (!contentTransferSetup.has_setup) {
|
|
26034
|
+
const message = "Content transfer setup is not set up.";
|
|
26035
|
+
success = false;
|
|
26036
|
+
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
26037
|
+
success,
|
|
26038
|
+
message
|
|
26039
|
+
});
|
|
26040
|
+
await activityLogsService.addEntry(sessionId, message);
|
|
26041
|
+
await activityLogsService.finishSession(sessionId, "failed", message);
|
|
26042
|
+
strapi2.log.info(message);
|
|
26043
|
+
return;
|
|
26044
|
+
}
|
|
26045
|
+
const { setup: setup2 } = contentTransferSetup;
|
|
26046
|
+
const collectionsNames = getCollectionsNames(setup2);
|
|
26047
|
+
const models = await StrapiService2.getModels();
|
|
26048
|
+
const strapiDefaultLocaleCode = await StrapiI18nService2.getDefaultLocaleCode();
|
|
26049
|
+
const attemptedTuples = [];
|
|
26050
|
+
let pickedFlattenStrapiContent = {};
|
|
26051
|
+
for (const collectionName of collectionsNames) {
|
|
26052
|
+
const currentModel = models.find((model) => model.collectionName === collectionName);
|
|
26053
|
+
const modelUid = currentModel.uid;
|
|
26054
|
+
if (!currentModel) {
|
|
26055
|
+
strapi2.log.warn(`Model with uid ${modelUid} is not found.`);
|
|
26056
|
+
continue;
|
|
26057
|
+
}
|
|
26058
|
+
const transferSetupModel = findSetupModelByCollectionName(setup2, collectionName);
|
|
26059
|
+
if (!isCollectionTransferEnabled(setup2, collectionName)) {
|
|
26060
|
+
const message2 = `Collection ${collectionName} transfer is disabled.`;
|
|
26061
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26062
|
+
message: message2
|
|
26063
|
+
});
|
|
26064
|
+
await activityLogsService.addEntry(sessionId, message2);
|
|
26065
|
+
strapi2.log.info(message2);
|
|
26066
|
+
continue;
|
|
26067
|
+
}
|
|
26068
|
+
const currentTransferSetupModel = transferSetupModel[collectionName];
|
|
26069
|
+
const pickPaths = getPickPathsWithComponents(currentTransferSetupModel);
|
|
26070
|
+
if (!pickPaths.length) {
|
|
26071
|
+
const message2 = `No fields for collection ${collectionName} transfer are enabled.`;
|
|
26072
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26073
|
+
message: message2
|
|
26074
|
+
});
|
|
26075
|
+
await activityLogsService.addEntry(sessionId, message2);
|
|
26076
|
+
strapi2.log.warn(message2);
|
|
26077
|
+
continue;
|
|
26078
|
+
}
|
|
26079
|
+
const pickPathsWithUid = pickPaths.map((pickPath) => `${modelUid}.${pickPath}`);
|
|
26080
|
+
let entries = await strapi2.documents(modelUid).findMany({
|
|
26081
|
+
locUploadPLevel: 6,
|
|
26082
|
+
status: "draft"
|
|
26083
|
+
});
|
|
26084
|
+
if (!entries.length) {
|
|
26085
|
+
strapi2.log.info(`No entries found for model ${modelUid}`);
|
|
26086
|
+
continue;
|
|
26087
|
+
}
|
|
26088
|
+
const excludedEntries = await EntryExclusionService2.getContentTypeExclusions(modelUid);
|
|
26089
|
+
const filteredEntries = [];
|
|
26090
|
+
for (const entry of entries) {
|
|
26091
|
+
const isExcluded = excludedEntries.includes(entry.documentId);
|
|
26092
|
+
if (!isExcluded) {
|
|
26093
|
+
filteredEntries.push(entry);
|
|
26094
|
+
}
|
|
26095
|
+
}
|
|
26096
|
+
entries = filteredEntries;
|
|
26097
|
+
if (!entries.length) {
|
|
26098
|
+
const message2 = `All entries for model ${collectionName} are excluded from translation`;
|
|
26099
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26100
|
+
message: message2
|
|
26101
|
+
});
|
|
26102
|
+
await activityLogsService.addEntry(sessionId, message2);
|
|
26103
|
+
strapi2.log.info(message2);
|
|
26104
|
+
continue;
|
|
26105
|
+
}
|
|
26106
|
+
const message = `Excluding ${excludedEntries.length} entries for model ${collectionName} from upload. Entries to translate: ${entries.length}.`;
|
|
26107
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26108
|
+
message
|
|
26109
|
+
});
|
|
26110
|
+
await activityLogsService.addEntry(sessionId, message);
|
|
26111
|
+
strapi2.log.info(message);
|
|
26112
|
+
if (strapiDefaultLocaleCode) {
|
|
26113
|
+
for (const entry of entries) {
|
|
26114
|
+
attemptedTuples.push({
|
|
26115
|
+
uid: modelUid,
|
|
26116
|
+
documentId: entry.documentId,
|
|
26117
|
+
locale: strapiDefaultLocaleCode
|
|
26118
|
+
});
|
|
26119
|
+
}
|
|
26120
|
+
}
|
|
26121
|
+
entries = omitDeep(entries, ["locale", "createdAt", "updatedAt", "publishedAt"]);
|
|
26122
|
+
entries.forEach((entry) => {
|
|
26123
|
+
const projectedEntry = projectBlocksFields(
|
|
26124
|
+
entry,
|
|
26125
|
+
strapi2.getModel(modelUid),
|
|
26126
|
+
(uid) => strapi2.getModel(uid)
|
|
26127
|
+
);
|
|
26128
|
+
const flatten = flattenObject({
|
|
26129
|
+
[modelUid]: projectedEntry
|
|
26130
|
+
});
|
|
26131
|
+
const pickedFlatten = pickEntries(flatten, pickPathsWithUid);
|
|
26132
|
+
pickedFlattenStrapiContent = {
|
|
26133
|
+
...pickedFlattenStrapiContent,
|
|
26134
|
+
...pickedFlatten
|
|
26135
|
+
};
|
|
26136
|
+
});
|
|
26137
|
+
const characterLimitsMetadata = getCharacterLimitsMetadata(pickedFlattenStrapiContent, modelUid);
|
|
26138
|
+
pickedFlattenStrapiContent = {
|
|
26139
|
+
...pickedFlattenStrapiContent,
|
|
26140
|
+
...characterLimitsMetadata
|
|
26141
|
+
};
|
|
26142
|
+
}
|
|
26143
|
+
const localazyLocaleCode = strapiDefaultLocaleCode ? isoStrapiToLocalazy(strapiDefaultLocaleCode) : config.default.LOCALAZY_DEFAULT_LOCALE;
|
|
26144
|
+
const importFile = LocalazyUploadService2.createImportFileRepresentation(
|
|
26145
|
+
localazyLocaleCode,
|
|
26146
|
+
pickedFlattenStrapiContent
|
|
26147
|
+
);
|
|
26148
|
+
const uploadConfig = {
|
|
26149
|
+
contentOptions: {
|
|
26150
|
+
type: config.default.LOCALAZY_DEFAULT_FILE_EXTENSION
|
|
26151
|
+
},
|
|
26152
|
+
i18nOptions: { deprecate: "file" },
|
|
26153
|
+
fileOptions: {
|
|
26154
|
+
name: config.default.LOCALAZY_DEFAULT_FILE_NAME,
|
|
26155
|
+
path: config.default.LOCALAZY_DEFAULT_FILE_PATH
|
|
26156
|
+
}
|
|
26157
|
+
};
|
|
26158
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26159
|
+
message: "Uploading collections to Localazy..."
|
|
26160
|
+
});
|
|
26161
|
+
await activityLogsService.addEntry(sessionId, "Uploading collections to Localazy...");
|
|
26162
|
+
try {
|
|
26163
|
+
await LocalazyUploadService2.upload(importFile, uploadConfig);
|
|
26164
|
+
await activityLogsService.recordAttemptedEntries(
|
|
26165
|
+
sessionId,
|
|
26166
|
+
attemptedTuples.map((t3) => ({ ...t3, status: "success" }))
|
|
26167
|
+
);
|
|
26168
|
+
} catch (error) {
|
|
26169
|
+
success = false;
|
|
26170
|
+
const errorMessage = `Upload to Localazy failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
26171
|
+
strapi2.log.error(errorMessage);
|
|
26172
|
+
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
26173
|
+
success,
|
|
26174
|
+
message: errorMessage
|
|
26175
|
+
});
|
|
26176
|
+
await activityLogsService.addEntry(sessionId, errorMessage);
|
|
26177
|
+
await activityLogsService.recordAttemptedEntries(
|
|
26178
|
+
sessionId,
|
|
26179
|
+
attemptedTuples.map((t3) => ({ ...t3, status: "failed", errorMessage }))
|
|
26180
|
+
);
|
|
26181
|
+
await activityLogsService.finishSession(sessionId, "failed", errorMessage);
|
|
26182
|
+
console.timeEnd("upload");
|
|
26183
|
+
return;
|
|
26184
|
+
}
|
|
26185
|
+
strapi2.log.info("Upload finished in");
|
|
26186
|
+
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
26187
|
+
success,
|
|
26188
|
+
message: "Upload finished"
|
|
26189
|
+
});
|
|
26190
|
+
await activityLogsService.addEntry(sessionId, "Upload finished");
|
|
26191
|
+
await activityLogsService.finishSession(
|
|
26192
|
+
sessionId,
|
|
26193
|
+
success ? "completed" : "failed",
|
|
26194
|
+
success ? "Upload completed successfully" : "Upload finished with errors"
|
|
26195
|
+
);
|
|
26196
|
+
console.timeEnd("upload");
|
|
26197
|
+
}
|
|
26198
|
+
});
|
|
25998
26199
|
const hasDynamicZoneKeySegment = (parsedKey) => {
|
|
25999
26200
|
return parsedKey.some((segment) => segment.includes(";"));
|
|
26000
26201
|
};
|
|
@@ -26067,7 +26268,7 @@ const shouldSetDownloadedProperty = (modelContentTransferSetup, parsedKeyRest) =
|
|
|
26067
26268
|
return "no";
|
|
26068
26269
|
}
|
|
26069
26270
|
};
|
|
26070
|
-
const getFilteredLanguagesCodesForDownload = async (languagesCodes) => {
|
|
26271
|
+
const getFilteredLanguagesCodesForDownload = async (languagesCodes, requestedUiLanguages) => {
|
|
26071
26272
|
const pluginSettingsServiceHelper = new PluginSettingsServiceHelper();
|
|
26072
26273
|
const requestInitiatorHelper = new RequestInitiatorHelper(strapi);
|
|
26073
26274
|
await pluginSettingsServiceHelper.setup();
|
|
@@ -26075,7 +26276,7 @@ const getFilteredLanguagesCodesForDownload = async (languagesCodes) => {
|
|
|
26075
26276
|
if (requestInitiatorHelper.isInitiatedByLocalazyWebhook()) {
|
|
26076
26277
|
localLanguagesCodes = pluginSettingsServiceHelper.getWebhookLanguagesCodes();
|
|
26077
26278
|
} else if (requestInitiatorHelper.isInitiatedByLocalazyPluginUI()) {
|
|
26078
|
-
localLanguagesCodes = pluginSettingsServiceHelper.getUiLanguagesCodes();
|
|
26279
|
+
localLanguagesCodes = requestedUiLanguages ?? pluginSettingsServiceHelper.getUiLanguagesCodes();
|
|
26079
26280
|
} else {
|
|
26080
26281
|
strapi.log.warn("Called by an unknown initiator.");
|
|
26081
26282
|
return languagesCodes;
|
|
@@ -26088,7 +26289,8 @@ const getFilteredLanguagesCodesForDownload = async (languagesCodes) => {
|
|
|
26088
26289
|
const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
26089
26290
|
async download({
|
|
26090
26291
|
notificationService,
|
|
26091
|
-
fullSync = false
|
|
26292
|
+
fullSync = false,
|
|
26293
|
+
requestedUiLanguages
|
|
26092
26294
|
}) {
|
|
26093
26295
|
console.time("download");
|
|
26094
26296
|
const syncMode = fullSync ? "Full sync" : "Incremental sync";
|
|
@@ -26168,7 +26370,7 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
26168
26370
|
return;
|
|
26169
26371
|
}
|
|
26170
26372
|
let languagesCodes = projectLanguagesWithoutSourceLanguage.map((language3) => language3.code);
|
|
26171
|
-
languagesCodes = await getFilteredLanguagesCodesForDownload(languagesCodes);
|
|
26373
|
+
languagesCodes = await getFilteredLanguagesCodesForDownload(languagesCodes, requestedUiLanguages);
|
|
26172
26374
|
const strapiUnsupportedLanguages = [];
|
|
26173
26375
|
const strapiLocales = await StrapiI18nService2.getLocales();
|
|
26174
26376
|
for (const isoLocalazy of languagesCodes) {
|
|
@@ -26681,6 +26883,9 @@ const isRepeatable = (attributeObj) => {
|
|
|
26681
26883
|
const isRelation = (attributeObj) => {
|
|
26682
26884
|
return attributeObj.type === "relation" && attributeObj.target !== "plugin::upload.file";
|
|
26683
26885
|
};
|
|
26886
|
+
const isBlocks = (attributeObj) => {
|
|
26887
|
+
return attributeObj.type === BLOCKS_ATTRIBUTE_TYPE;
|
|
26888
|
+
};
|
|
26684
26889
|
const findModel = (models, uid) => {
|
|
26685
26890
|
const model = models.find((model2) => model2.uid === uid);
|
|
26686
26891
|
return model;
|
|
@@ -26824,7 +27029,11 @@ const parsedLocalazyEntryToCreateEntry = (models, parsedLocalazyEntry, baseEntry
|
|
|
26824
27029
|
newPrefixBase = `${dzParamKey}.${baseEntryDZIndex}`;
|
|
26825
27030
|
newPrefix = `${newPrefixBase}.${objectKey}`;
|
|
26826
27031
|
}
|
|
26827
|
-
|
|
27032
|
+
const valueToSet = isBlocks(attribute) ? overlayBlocksTranslation(get(baseEntry, newPrefix), value) : value;
|
|
27033
|
+
if (valueToSet === void 0) {
|
|
27034
|
+
return;
|
|
27035
|
+
}
|
|
27036
|
+
set(createEntry, newPrefix, valueToSet);
|
|
26828
27037
|
if (component) {
|
|
26829
27038
|
const componentKeyToSet = `${newPrefixBase}.__component`;
|
|
26830
27039
|
set(createEntry, componentKeyToSet, component);
|