@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.mjs
CHANGED
|
@@ -20520,7 +20520,7 @@ var distExports = dist$1.exports;
|
|
|
20520
20520
|
const io = /* @__PURE__ */ getDefaultExportFromCjs(distExports);
|
|
20521
20521
|
const { Server: Server2, Namespace, Socket: Socket3 } = io;
|
|
20522
20522
|
const name = "@localazy/strapi-plugin";
|
|
20523
|
-
const version = "1.
|
|
20523
|
+
const version = "1.7.0";
|
|
20524
20524
|
const description = "The official Strapi Plugin by Localazy.";
|
|
20525
20525
|
const keywords = [
|
|
20526
20526
|
"strapi",
|
|
@@ -20704,7 +20704,60 @@ const _package$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
20704
20704
|
version
|
|
20705
20705
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
20706
20706
|
const PLUGIN_NAME = strapi$1.name;
|
|
20707
|
-
const
|
|
20707
|
+
const PERMISSION_UIDS = {
|
|
20708
|
+
READ: `plugin::${PLUGIN_NAME}.read`,
|
|
20709
|
+
TRANSFER: `plugin::${PLUGIN_NAME}.transfer`,
|
|
20710
|
+
SETTINGS_UPDATE: `plugin::${PLUGIN_NAME}.settings.update`
|
|
20711
|
+
};
|
|
20712
|
+
const LOCALAZY_RBAC_ACTIONS = [
|
|
20713
|
+
{
|
|
20714
|
+
section: "plugins",
|
|
20715
|
+
subCategory: "General",
|
|
20716
|
+
pluginName: PLUGIN_NAME,
|
|
20717
|
+
displayName: "Read",
|
|
20718
|
+
uid: "read"
|
|
20719
|
+
},
|
|
20720
|
+
{
|
|
20721
|
+
section: "plugins",
|
|
20722
|
+
subCategory: "General",
|
|
20723
|
+
pluginName: PLUGIN_NAME,
|
|
20724
|
+
displayName: "Transfer",
|
|
20725
|
+
uid: "transfer"
|
|
20726
|
+
},
|
|
20727
|
+
{
|
|
20728
|
+
section: "plugins",
|
|
20729
|
+
subCategory: "Settings",
|
|
20730
|
+
pluginName: PLUGIN_NAME,
|
|
20731
|
+
displayName: "Read settings",
|
|
20732
|
+
uid: "settings.read"
|
|
20733
|
+
},
|
|
20734
|
+
{
|
|
20735
|
+
section: "plugins",
|
|
20736
|
+
subCategory: "Settings",
|
|
20737
|
+
pluginName: PLUGIN_NAME,
|
|
20738
|
+
displayName: "Update settings",
|
|
20739
|
+
uid: "settings.update"
|
|
20740
|
+
}
|
|
20741
|
+
];
|
|
20742
|
+
const registerRbacActions = async (strapi2) => {
|
|
20743
|
+
try {
|
|
20744
|
+
const permissionService = strapi2.service("admin::permission");
|
|
20745
|
+
const actionProvider = permissionService?.actionProvider;
|
|
20746
|
+
if (!actionProvider?.registerMany) {
|
|
20747
|
+
strapi2.log.warn(
|
|
20748
|
+
`[${PLUGIN_NAME}] admin::permission.actionProvider unavailable — skipping RBAC action registration`
|
|
20749
|
+
);
|
|
20750
|
+
return;
|
|
20751
|
+
}
|
|
20752
|
+
await actionProvider.registerMany(LOCALAZY_RBAC_ACTIONS);
|
|
20753
|
+
} catch (error) {
|
|
20754
|
+
strapi2.log.error(
|
|
20755
|
+
`[${PLUGIN_NAME}] Failed to register RBAC actions — plugin permissions will not appear in role editor: ${error instanceof Error ? error.message : String(error)}`
|
|
20756
|
+
);
|
|
20757
|
+
}
|
|
20758
|
+
};
|
|
20759
|
+
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
20760
|
+
await registerRbacActions(strapi2);
|
|
20708
20761
|
if (strapi2.plugin(PLUGIN_NAME)?.config("enableSocketIO", true)) {
|
|
20709
20762
|
process.nextTick(async () => {
|
|
20710
20763
|
const io2 = new Server2(strapi2.server.httpServer, {
|
|
@@ -24287,6 +24340,9 @@ const PluginSettingsController = ({ strapi: _strapi }) => ({
|
|
|
24287
24340
|
async updatePluginSettings(ctx) {
|
|
24288
24341
|
ctx.body = await getPluginSettingsService().updatePluginSettings(ctx.request.body);
|
|
24289
24342
|
},
|
|
24343
|
+
async updatePluginSettingsUiPrefs(ctx) {
|
|
24344
|
+
ctx.body = await getPluginSettingsService().updatePluginSettingsUiPrefs(ctx.request.body);
|
|
24345
|
+
},
|
|
24290
24346
|
async getSyncCursor(ctx) {
|
|
24291
24347
|
ctx.body = await getPluginSettingsService().getSyncCursor();
|
|
24292
24348
|
}
|
|
@@ -24386,6 +24442,8 @@ const LocalazyTransferController = ({ strapi: strapi2 }) => ({
|
|
|
24386
24442
|
try {
|
|
24387
24443
|
const LocalazyTransferDownloadService2 = getLocalazyTransferDownloadService();
|
|
24388
24444
|
let fullSync = ctx.request.body?.fullSync === true;
|
|
24445
|
+
const rawUiLanguages = ctx.request.body?.uiLanguages;
|
|
24446
|
+
const requestedUiLanguages = Array.isArray(rawUiLanguages) && rawUiLanguages.every((code) => typeof code === "string") ? rawUiLanguages : void 0;
|
|
24389
24447
|
const requestInitiatorHelper = new RequestInitiatorHelper(strapi2);
|
|
24390
24448
|
if (requestInitiatorHelper.isInitiatedByLocalazyWebhook()) {
|
|
24391
24449
|
const pluginSettingsServiceHelper = new PluginSettingsServiceHelper();
|
|
@@ -24395,7 +24453,8 @@ const LocalazyTransferController = ({ strapi: strapi2 }) => ({
|
|
|
24395
24453
|
setTimeout(
|
|
24396
24454
|
() => LocalazyTransferDownloadService2.download({
|
|
24397
24455
|
notificationService: JobNotificationService$1,
|
|
24398
|
-
fullSync
|
|
24456
|
+
fullSync,
|
|
24457
|
+
requestedUiLanguages
|
|
24399
24458
|
}),
|
|
24400
24459
|
1e3
|
|
24401
24460
|
);
|
|
@@ -24964,13 +25023,17 @@ const middlewares = {
|
|
|
24964
25023
|
};
|
|
24965
25024
|
const policies = {};
|
|
24966
25025
|
const ROUTE_PREFIX$8 = "/user";
|
|
25026
|
+
const readPolicy$6 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25027
|
+
const settingsUpdatePolicy$4 = [
|
|
25028
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25029
|
+
];
|
|
24967
25030
|
const LocalazyUserRoutes = [
|
|
24968
25031
|
{
|
|
24969
25032
|
method: "GET",
|
|
24970
25033
|
path: `${ROUTE_PREFIX$8}`,
|
|
24971
25034
|
handler: "LocalazyUserController.getUser",
|
|
24972
25035
|
config: {
|
|
24973
|
-
policies:
|
|
25036
|
+
policies: readPolicy$6
|
|
24974
25037
|
}
|
|
24975
25038
|
},
|
|
24976
25039
|
{
|
|
@@ -24978,7 +25041,7 @@ const LocalazyUserRoutes = [
|
|
|
24978
25041
|
path: `${ROUTE_PREFIX$8}`,
|
|
24979
25042
|
handler: "LocalazyUserController.updateUser",
|
|
24980
25043
|
config: {
|
|
24981
|
-
policies:
|
|
25044
|
+
policies: settingsUpdatePolicy$4
|
|
24982
25045
|
}
|
|
24983
25046
|
},
|
|
24984
25047
|
{
|
|
@@ -24986,18 +25049,21 @@ const LocalazyUserRoutes = [
|
|
|
24986
25049
|
path: `${ROUTE_PREFIX$8}`,
|
|
24987
25050
|
handler: "LocalazyUserController.deleteUser",
|
|
24988
25051
|
config: {
|
|
24989
|
-
policies:
|
|
25052
|
+
policies: settingsUpdatePolicy$4
|
|
24990
25053
|
}
|
|
24991
25054
|
}
|
|
24992
25055
|
];
|
|
24993
25056
|
const ROUTE_PREFIX$7 = "/auth";
|
|
25057
|
+
const settingsUpdatePolicy$3 = [
|
|
25058
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25059
|
+
];
|
|
24994
25060
|
const LocalazyAuthRoutes = [
|
|
24995
25061
|
{
|
|
24996
25062
|
method: "GET",
|
|
24997
25063
|
path: `${ROUTE_PREFIX$7}/generate-keys`,
|
|
24998
25064
|
handler: "LocalazyAuthController.generateKeys",
|
|
24999
25065
|
config: {
|
|
25000
|
-
policies:
|
|
25066
|
+
policies: settingsUpdatePolicy$3
|
|
25001
25067
|
}
|
|
25002
25068
|
},
|
|
25003
25069
|
{
|
|
@@ -25005,18 +25071,26 @@ const LocalazyAuthRoutes = [
|
|
|
25005
25071
|
path: `${ROUTE_PREFIX$7}/continuous-poll`,
|
|
25006
25072
|
handler: "LocalazyAuthController.continuousPoll",
|
|
25007
25073
|
config: {
|
|
25008
|
-
policies:
|
|
25074
|
+
policies: settingsUpdatePolicy$3
|
|
25009
25075
|
}
|
|
25010
25076
|
}
|
|
25011
25077
|
];
|
|
25012
25078
|
const ROUTE_PREFIX$6 = "/plugin-settings";
|
|
25079
|
+
const readPolicy$5 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25080
|
+
const settingsUpdatePolicy$2 = [
|
|
25081
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25082
|
+
];
|
|
25013
25083
|
const PluginSettingsRoutes = [
|
|
25014
25084
|
{
|
|
25015
25085
|
method: "GET",
|
|
25016
25086
|
path: `${ROUTE_PREFIX$6}/content-transfer-setup`,
|
|
25017
25087
|
handler: "PluginSettingsController.getContentTransferSetup",
|
|
25018
25088
|
config: {
|
|
25019
|
-
|
|
25089
|
+
// Upload/Download pages call this to detect "model changed" before
|
|
25090
|
+
// transferring. Gating on `settings.read` would lock transfer-only
|
|
25091
|
+
// roles out of the transfer pages, so the read is open to any plugin
|
|
25092
|
+
// user. The destructive PUT below stays on `settings.update`.
|
|
25093
|
+
policies: readPolicy$5
|
|
25020
25094
|
}
|
|
25021
25095
|
},
|
|
25022
25096
|
{
|
|
@@ -25024,7 +25098,7 @@ const PluginSettingsRoutes = [
|
|
|
25024
25098
|
path: `${ROUTE_PREFIX$6}/content-transfer-setup`,
|
|
25025
25099
|
handler: "PluginSettingsController.updateContentTransferSetup",
|
|
25026
25100
|
config: {
|
|
25027
|
-
policies:
|
|
25101
|
+
policies: settingsUpdatePolicy$2
|
|
25028
25102
|
}
|
|
25029
25103
|
},
|
|
25030
25104
|
{
|
|
@@ -25032,7 +25106,7 @@ const PluginSettingsRoutes = [
|
|
|
25032
25106
|
path: `${ROUTE_PREFIX$6}/plugin-settings`,
|
|
25033
25107
|
handler: "PluginSettingsController.getPluginSettings",
|
|
25034
25108
|
config: {
|
|
25035
|
-
policies:
|
|
25109
|
+
policies: readPolicy$5
|
|
25036
25110
|
}
|
|
25037
25111
|
},
|
|
25038
25112
|
{
|
|
@@ -25040,7 +25114,20 @@ const PluginSettingsRoutes = [
|
|
|
25040
25114
|
path: `${ROUTE_PREFIX$6}/plugin-settings`,
|
|
25041
25115
|
handler: "PluginSettingsController.updatePluginSettings",
|
|
25042
25116
|
config: {
|
|
25043
|
-
|
|
25117
|
+
// Persists destructive Global Settings (webhookConfig, download.*, upload.*).
|
|
25118
|
+
// UI-pref-only writes use `PUT /plugin-settings/ui-prefs` (read-gated) below.
|
|
25119
|
+
policies: settingsUpdatePolicy$2
|
|
25120
|
+
}
|
|
25121
|
+
},
|
|
25122
|
+
{
|
|
25123
|
+
method: "PUT",
|
|
25124
|
+
path: `${ROUTE_PREFIX$6}/ui-prefs`,
|
|
25125
|
+
handler: "PluginSettingsController.updatePluginSettingsUiPrefs",
|
|
25126
|
+
config: {
|
|
25127
|
+
// Per-user UI state (last visited route, sort prefs). Service-side filters
|
|
25128
|
+
// the body to a fixed allowlist so a `read`-only caller cannot reach the
|
|
25129
|
+
// destructive fields that share the same plugin-settings store.
|
|
25130
|
+
policies: readPolicy$5
|
|
25044
25131
|
}
|
|
25045
25132
|
},
|
|
25046
25133
|
{
|
|
@@ -25048,18 +25135,22 @@ const PluginSettingsRoutes = [
|
|
|
25048
25135
|
path: `${ROUTE_PREFIX$6}/sync-cursor`,
|
|
25049
25136
|
handler: "PluginSettingsController.getSyncCursor",
|
|
25050
25137
|
config: {
|
|
25051
|
-
policies:
|
|
25138
|
+
policies: readPolicy$5
|
|
25052
25139
|
}
|
|
25053
25140
|
}
|
|
25054
25141
|
];
|
|
25055
25142
|
const ROUTE_PREFIX$5 = "/strapi";
|
|
25143
|
+
const readPolicy$4 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25144
|
+
const settingsUpdatePolicy$1 = [
|
|
25145
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25146
|
+
];
|
|
25056
25147
|
const StrapiRoutes = [
|
|
25057
25148
|
{
|
|
25058
25149
|
method: "GET",
|
|
25059
25150
|
path: `${ROUTE_PREFIX$5}/models`,
|
|
25060
25151
|
handler: "StrapiController.getModels",
|
|
25061
25152
|
config: {
|
|
25062
|
-
policies:
|
|
25153
|
+
policies: readPolicy$4
|
|
25063
25154
|
}
|
|
25064
25155
|
},
|
|
25065
25156
|
{
|
|
@@ -25067,7 +25158,7 @@ const StrapiRoutes = [
|
|
|
25067
25158
|
path: `${ROUTE_PREFIX$5}/localizable-models`,
|
|
25068
25159
|
handler: "StrapiController.getLocalizableModels",
|
|
25069
25160
|
config: {
|
|
25070
|
-
policies:
|
|
25161
|
+
policies: readPolicy$4
|
|
25071
25162
|
}
|
|
25072
25163
|
},
|
|
25073
25164
|
{
|
|
@@ -25075,7 +25166,7 @@ const StrapiRoutes = [
|
|
|
25075
25166
|
path: `${ROUTE_PREFIX$5}/lifecycle/localazy-webhooks`,
|
|
25076
25167
|
handler: "StrapiController.postLifecycleLocalazyWebhooks",
|
|
25077
25168
|
config: {
|
|
25078
|
-
policies:
|
|
25169
|
+
policies: settingsUpdatePolicy$1
|
|
25079
25170
|
}
|
|
25080
25171
|
},
|
|
25081
25172
|
{
|
|
@@ -25083,18 +25174,19 @@ const StrapiRoutes = [
|
|
|
25083
25174
|
path: `${ROUTE_PREFIX$5}/version`,
|
|
25084
25175
|
handler: "StrapiController.getPluginVersion",
|
|
25085
25176
|
config: {
|
|
25086
|
-
policies:
|
|
25177
|
+
policies: readPolicy$4
|
|
25087
25178
|
}
|
|
25088
25179
|
}
|
|
25089
25180
|
];
|
|
25090
25181
|
const ROUTE_PREFIX$4 = "/transfer";
|
|
25182
|
+
const transferPolicy$2 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.TRANSFER] } }];
|
|
25091
25183
|
const LocalazyTransferRoutes = [
|
|
25092
25184
|
{
|
|
25093
25185
|
method: "POST",
|
|
25094
25186
|
path: `${ROUTE_PREFIX$4}/upload`,
|
|
25095
25187
|
handler: "LocalazyTransferController.upload",
|
|
25096
25188
|
config: {
|
|
25097
|
-
policies:
|
|
25189
|
+
policies: transferPolicy$2
|
|
25098
25190
|
}
|
|
25099
25191
|
},
|
|
25100
25192
|
{
|
|
@@ -25102,18 +25194,22 @@ const LocalazyTransferRoutes = [
|
|
|
25102
25194
|
path: `${ROUTE_PREFIX$4}/download`,
|
|
25103
25195
|
handler: "LocalazyTransferController.download",
|
|
25104
25196
|
config: {
|
|
25105
|
-
policies:
|
|
25197
|
+
policies: transferPolicy$2
|
|
25106
25198
|
}
|
|
25107
25199
|
}
|
|
25108
25200
|
];
|
|
25109
25201
|
const ROUTE_PREFIX$3 = "/project";
|
|
25202
|
+
const readPolicy$3 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25203
|
+
const settingsUpdatePolicy = [
|
|
25204
|
+
{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.SETTINGS_UPDATE] } }
|
|
25205
|
+
];
|
|
25110
25206
|
const LocalazyProjectRoutes = [
|
|
25111
25207
|
{
|
|
25112
25208
|
method: "GET",
|
|
25113
25209
|
path: `${ROUTE_PREFIX$3}`,
|
|
25114
25210
|
handler: "LocalazyProjectController.getConnectedProject",
|
|
25115
25211
|
config: {
|
|
25116
|
-
policies:
|
|
25212
|
+
policies: readPolicy$3
|
|
25117
25213
|
}
|
|
25118
25214
|
},
|
|
25119
25215
|
{
|
|
@@ -25121,7 +25217,7 @@ const LocalazyProjectRoutes = [
|
|
|
25121
25217
|
path: `${ROUTE_PREFIX$3}/webhooks`,
|
|
25122
25218
|
handler: "LocalazyProjectController.getWebhookStatus",
|
|
25123
25219
|
config: {
|
|
25124
|
-
policies:
|
|
25220
|
+
policies: readPolicy$3
|
|
25125
25221
|
}
|
|
25126
25222
|
},
|
|
25127
25223
|
{
|
|
@@ -25129,7 +25225,7 @@ const LocalazyProjectRoutes = [
|
|
|
25129
25225
|
path: `${ROUTE_PREFIX$3}/webhooks/setup`,
|
|
25130
25226
|
handler: "LocalazyProjectController.setupWebhook",
|
|
25131
25227
|
config: {
|
|
25132
|
-
policies:
|
|
25228
|
+
policies: settingsUpdatePolicy
|
|
25133
25229
|
}
|
|
25134
25230
|
},
|
|
25135
25231
|
{
|
|
@@ -25137,7 +25233,7 @@ const LocalazyProjectRoutes = [
|
|
|
25137
25233
|
path: `${ROUTE_PREFIX$3}/strapi-url`,
|
|
25138
25234
|
handler: "LocalazyProjectController.getStrapiUrl",
|
|
25139
25235
|
config: {
|
|
25140
|
-
policies:
|
|
25236
|
+
policies: readPolicy$3
|
|
25141
25237
|
}
|
|
25142
25238
|
}
|
|
25143
25239
|
];
|
|
@@ -25156,13 +25252,15 @@ const LocalazyPublicTransferRoutes = [
|
|
|
25156
25252
|
}
|
|
25157
25253
|
];
|
|
25158
25254
|
const ROUTE_PREFIX$1 = "/entry-exclusion";
|
|
25255
|
+
const readPolicy$2 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25256
|
+
const transferPolicy$1 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.TRANSFER] } }];
|
|
25159
25257
|
const EntryExclusionRoutes = [
|
|
25160
25258
|
{
|
|
25161
25259
|
method: "GET",
|
|
25162
25260
|
path: `${ROUTE_PREFIX$1}/:contentType/:documentId`,
|
|
25163
25261
|
handler: "EntryExclusionController.getEntryExclusion",
|
|
25164
25262
|
config: {
|
|
25165
|
-
policies:
|
|
25263
|
+
policies: readPolicy$2
|
|
25166
25264
|
}
|
|
25167
25265
|
},
|
|
25168
25266
|
{
|
|
@@ -25170,7 +25268,7 @@ const EntryExclusionRoutes = [
|
|
|
25170
25268
|
path: `${ROUTE_PREFIX$1}/:contentType/:documentId`,
|
|
25171
25269
|
handler: "EntryExclusionController.setEntryExclusion",
|
|
25172
25270
|
config: {
|
|
25173
|
-
policies:
|
|
25271
|
+
policies: transferPolicy$1
|
|
25174
25272
|
}
|
|
25175
25273
|
},
|
|
25176
25274
|
{
|
|
@@ -25178,18 +25276,20 @@ const EntryExclusionRoutes = [
|
|
|
25178
25276
|
path: `${ROUTE_PREFIX$1}/:contentType`,
|
|
25179
25277
|
handler: "EntryExclusionController.getContentTypeExclusions",
|
|
25180
25278
|
config: {
|
|
25181
|
-
policies:
|
|
25279
|
+
policies: readPolicy$2
|
|
25182
25280
|
}
|
|
25183
25281
|
}
|
|
25184
25282
|
];
|
|
25185
25283
|
const ROUTE_PREFIX = "/activity-logs";
|
|
25284
|
+
const readPolicy$1 = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25285
|
+
const transferPolicy = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.TRANSFER] } }];
|
|
25186
25286
|
const ActivityLogsRoutes = [
|
|
25187
25287
|
{
|
|
25188
25288
|
method: "GET",
|
|
25189
25289
|
path: `${ROUTE_PREFIX}`,
|
|
25190
25290
|
handler: "ActivityLogsController.getSessions",
|
|
25191
25291
|
config: {
|
|
25192
|
-
policies:
|
|
25292
|
+
policies: readPolicy$1
|
|
25193
25293
|
}
|
|
25194
25294
|
},
|
|
25195
25295
|
{
|
|
@@ -25197,7 +25297,7 @@ const ActivityLogsRoutes = [
|
|
|
25197
25297
|
path: `${ROUTE_PREFIX}/export`,
|
|
25198
25298
|
handler: "ActivityLogsController.exportSessions",
|
|
25199
25299
|
config: {
|
|
25200
|
-
policies:
|
|
25300
|
+
policies: readPolicy$1
|
|
25201
25301
|
}
|
|
25202
25302
|
},
|
|
25203
25303
|
{
|
|
@@ -25205,7 +25305,7 @@ const ActivityLogsRoutes = [
|
|
|
25205
25305
|
path: `${ROUTE_PREFIX}/:sessionId`,
|
|
25206
25306
|
handler: "ActivityLogsController.getSession",
|
|
25207
25307
|
config: {
|
|
25208
|
-
policies:
|
|
25308
|
+
policies: readPolicy$1
|
|
25209
25309
|
}
|
|
25210
25310
|
},
|
|
25211
25311
|
{
|
|
@@ -25213,23 +25313,28 @@ const ActivityLogsRoutes = [
|
|
|
25213
25313
|
path: `${ROUTE_PREFIX}`,
|
|
25214
25314
|
handler: "ActivityLogsController.clearSessions",
|
|
25215
25315
|
config: {
|
|
25216
|
-
policies:
|
|
25316
|
+
policies: transferPolicy
|
|
25217
25317
|
}
|
|
25218
25318
|
}
|
|
25219
25319
|
];
|
|
25320
|
+
const readPolicy = [{ name: "admin::hasPermissions", config: { actions: [PERMISSION_UIDS.READ] } }];
|
|
25220
25321
|
const DebugBundleRoutes = [
|
|
25221
25322
|
{
|
|
25222
25323
|
method: "GET",
|
|
25223
25324
|
path: "/activity-logs/:sessionId/bundle",
|
|
25224
25325
|
handler: "DebugBundleController.getBundle",
|
|
25225
25326
|
config: {
|
|
25226
|
-
policies:
|
|
25327
|
+
policies: readPolicy
|
|
25227
25328
|
}
|
|
25228
25329
|
}
|
|
25229
25330
|
];
|
|
25331
|
+
const withoutAdminPolicies = (routes2) => routes2.map((route) => ({
|
|
25332
|
+
...route,
|
|
25333
|
+
config: { ...route.config, policies: [] }
|
|
25334
|
+
}));
|
|
25230
25335
|
const routes = {
|
|
25231
25336
|
"content-api": {
|
|
25232
|
-
routes:
|
|
25337
|
+
routes: withoutAdminPolicies(StrapiRoutes)
|
|
25233
25338
|
},
|
|
25234
25339
|
admin: {
|
|
25235
25340
|
type: "admin",
|
|
@@ -25441,6 +25546,7 @@ const KEY$1 = "sync-cursor";
|
|
|
25441
25546
|
const emptySyncCursor = {
|
|
25442
25547
|
processedKeys: {}
|
|
25443
25548
|
};
|
|
25549
|
+
const UI_PREF_FIELDS = ["defaultRoute", "activityLogsSort"];
|
|
25444
25550
|
const PluginSettingsService = ({ strapi: strapi2 }) => ({
|
|
25445
25551
|
async getContentTransferSetup() {
|
|
25446
25552
|
const pluginStore = getStrapiStore(strapi2);
|
|
@@ -25477,6 +25583,20 @@ const PluginSettingsService = ({ strapi: strapi2 }) => ({
|
|
|
25477
25583
|
});
|
|
25478
25584
|
return newSettings;
|
|
25479
25585
|
},
|
|
25586
|
+
// Counterpart to `updatePluginSettings` for the `read`-gated UI-prefs route.
|
|
25587
|
+
// Drops any field outside `UI_PREF_FIELDS` server-side so a `read`-only caller
|
|
25588
|
+
// cannot reach `webhookConfig` / `download.*` / `upload.*` via the merge.
|
|
25589
|
+
async updatePluginSettingsUiPrefs(prefs) {
|
|
25590
|
+
const sanitized = {};
|
|
25591
|
+
if (prefs && typeof prefs === "object") {
|
|
25592
|
+
for (const field of UI_PREF_FIELDS) {
|
|
25593
|
+
if (field in prefs) {
|
|
25594
|
+
sanitized[field] = prefs[field];
|
|
25595
|
+
}
|
|
25596
|
+
}
|
|
25597
|
+
}
|
|
25598
|
+
return this.updatePluginSettings(sanitized);
|
|
25599
|
+
},
|
|
25480
25600
|
async getSyncCursor() {
|
|
25481
25601
|
const pluginStore = getStrapiStore(strapi2);
|
|
25482
25602
|
const cursor = await pluginStore.get({ key: KEY$1 });
|
|
@@ -25491,182 +25611,6 @@ const PluginSettingsService = ({ strapi: strapi2 }) => ({
|
|
|
25491
25611
|
return cursor;
|
|
25492
25612
|
}
|
|
25493
25613
|
});
|
|
25494
|
-
const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
25495
|
-
async upload({ notificationService }) {
|
|
25496
|
-
console.time("upload");
|
|
25497
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25498
|
-
message: "Upload started"
|
|
25499
|
-
});
|
|
25500
|
-
const activityLogsService = getActivityLogsService();
|
|
25501
|
-
const sessionId = await activityLogsService.startSession("upload", "Strapi User");
|
|
25502
|
-
await activityLogsService.addEntry(sessionId, "Upload started");
|
|
25503
|
-
let success = true;
|
|
25504
|
-
const StrapiService2 = getStrapiService();
|
|
25505
|
-
const StrapiI18nService2 = getStrapiI18nService();
|
|
25506
|
-
const LocalazyUploadService2 = getLocalazyUploadService();
|
|
25507
|
-
const EntryExclusionService2 = getEntryExclusionService();
|
|
25508
|
-
const contentTransferSetup = await getPluginSettingsService().getContentTransferSetup();
|
|
25509
|
-
if (!contentTransferSetup.has_setup) {
|
|
25510
|
-
const message = "Content transfer setup is not set up.";
|
|
25511
|
-
success = false;
|
|
25512
|
-
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
25513
|
-
success,
|
|
25514
|
-
message
|
|
25515
|
-
});
|
|
25516
|
-
await activityLogsService.addEntry(sessionId, message);
|
|
25517
|
-
await activityLogsService.finishSession(sessionId, "failed", message);
|
|
25518
|
-
strapi2.log.info(message);
|
|
25519
|
-
return;
|
|
25520
|
-
}
|
|
25521
|
-
const { setup: setup2 } = contentTransferSetup;
|
|
25522
|
-
const collectionsNames = getCollectionsNames(setup2);
|
|
25523
|
-
const models = await StrapiService2.getModels();
|
|
25524
|
-
const strapiDefaultLocaleCode = await StrapiI18nService2.getDefaultLocaleCode();
|
|
25525
|
-
const attemptedTuples = [];
|
|
25526
|
-
let pickedFlattenStrapiContent = {};
|
|
25527
|
-
for (const collectionName of collectionsNames) {
|
|
25528
|
-
const currentModel = models.find((model) => model.collectionName === collectionName);
|
|
25529
|
-
const modelUid = currentModel.uid;
|
|
25530
|
-
if (!currentModel) {
|
|
25531
|
-
strapi2.log.warn(`Model with uid ${modelUid} is not found.`);
|
|
25532
|
-
continue;
|
|
25533
|
-
}
|
|
25534
|
-
const transferSetupModel = findSetupModelByCollectionName(setup2, collectionName);
|
|
25535
|
-
if (!isCollectionTransferEnabled(setup2, collectionName)) {
|
|
25536
|
-
const message2 = `Collection ${collectionName} transfer is disabled.`;
|
|
25537
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25538
|
-
message: message2
|
|
25539
|
-
});
|
|
25540
|
-
await activityLogsService.addEntry(sessionId, message2);
|
|
25541
|
-
strapi2.log.info(message2);
|
|
25542
|
-
continue;
|
|
25543
|
-
}
|
|
25544
|
-
const currentTransferSetupModel = transferSetupModel[collectionName];
|
|
25545
|
-
const pickPaths = getPickPathsWithComponents(currentTransferSetupModel);
|
|
25546
|
-
if (!pickPaths.length) {
|
|
25547
|
-
const message2 = `No fields for collection ${collectionName} transfer are enabled.`;
|
|
25548
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25549
|
-
message: message2
|
|
25550
|
-
});
|
|
25551
|
-
await activityLogsService.addEntry(sessionId, message2);
|
|
25552
|
-
strapi2.log.warn(message2);
|
|
25553
|
-
continue;
|
|
25554
|
-
}
|
|
25555
|
-
const pickPathsWithUid = pickPaths.map((pickPath) => `${modelUid}.${pickPath}`);
|
|
25556
|
-
let entries = await strapi2.documents(modelUid).findMany({
|
|
25557
|
-
locUploadPLevel: 6,
|
|
25558
|
-
status: "draft"
|
|
25559
|
-
});
|
|
25560
|
-
if (!entries.length) {
|
|
25561
|
-
strapi2.log.info(`No entries found for model ${modelUid}`);
|
|
25562
|
-
continue;
|
|
25563
|
-
}
|
|
25564
|
-
const excludedEntries = await EntryExclusionService2.getContentTypeExclusions(modelUid);
|
|
25565
|
-
const filteredEntries = [];
|
|
25566
|
-
for (const entry of entries) {
|
|
25567
|
-
const isExcluded = excludedEntries.includes(entry.documentId);
|
|
25568
|
-
if (!isExcluded) {
|
|
25569
|
-
filteredEntries.push(entry);
|
|
25570
|
-
}
|
|
25571
|
-
}
|
|
25572
|
-
entries = filteredEntries;
|
|
25573
|
-
if (!entries.length) {
|
|
25574
|
-
const message2 = `All entries for model ${collectionName} are excluded from translation`;
|
|
25575
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25576
|
-
message: message2
|
|
25577
|
-
});
|
|
25578
|
-
await activityLogsService.addEntry(sessionId, message2);
|
|
25579
|
-
strapi2.log.info(message2);
|
|
25580
|
-
continue;
|
|
25581
|
-
}
|
|
25582
|
-
const message = `Excluding ${excludedEntries.length} entries for model ${collectionName} from upload. Entries to translate: ${entries.length}.`;
|
|
25583
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25584
|
-
message
|
|
25585
|
-
});
|
|
25586
|
-
await activityLogsService.addEntry(sessionId, message);
|
|
25587
|
-
strapi2.log.info(message);
|
|
25588
|
-
if (strapiDefaultLocaleCode) {
|
|
25589
|
-
for (const entry of entries) {
|
|
25590
|
-
attemptedTuples.push({
|
|
25591
|
-
uid: modelUid,
|
|
25592
|
-
documentId: entry.documentId,
|
|
25593
|
-
locale: strapiDefaultLocaleCode
|
|
25594
|
-
});
|
|
25595
|
-
}
|
|
25596
|
-
}
|
|
25597
|
-
entries = omitDeep(entries, ["locale", "createdAt", "updatedAt", "publishedAt"]);
|
|
25598
|
-
entries.forEach((entry) => {
|
|
25599
|
-
const flatten = flattenObject({
|
|
25600
|
-
[modelUid]: entry
|
|
25601
|
-
});
|
|
25602
|
-
const pickedFlatten = pickEntries(flatten, pickPathsWithUid);
|
|
25603
|
-
pickedFlattenStrapiContent = {
|
|
25604
|
-
...pickedFlattenStrapiContent,
|
|
25605
|
-
...pickedFlatten
|
|
25606
|
-
};
|
|
25607
|
-
});
|
|
25608
|
-
const characterLimitsMetadata = getCharacterLimitsMetadata(pickedFlattenStrapiContent, modelUid);
|
|
25609
|
-
pickedFlattenStrapiContent = {
|
|
25610
|
-
...pickedFlattenStrapiContent,
|
|
25611
|
-
...characterLimitsMetadata
|
|
25612
|
-
};
|
|
25613
|
-
}
|
|
25614
|
-
const localazyLocaleCode = strapiDefaultLocaleCode ? isoStrapiToLocalazy(strapiDefaultLocaleCode) : config.default.LOCALAZY_DEFAULT_LOCALE;
|
|
25615
|
-
const importFile = LocalazyUploadService2.createImportFileRepresentation(
|
|
25616
|
-
localazyLocaleCode,
|
|
25617
|
-
pickedFlattenStrapiContent
|
|
25618
|
-
);
|
|
25619
|
-
const uploadConfig = {
|
|
25620
|
-
contentOptions: {
|
|
25621
|
-
type: config.default.LOCALAZY_DEFAULT_FILE_EXTENSION
|
|
25622
|
-
},
|
|
25623
|
-
i18nOptions: { deprecate: "file" },
|
|
25624
|
-
fileOptions: {
|
|
25625
|
-
name: config.default.LOCALAZY_DEFAULT_FILE_NAME,
|
|
25626
|
-
path: config.default.LOCALAZY_DEFAULT_FILE_PATH
|
|
25627
|
-
}
|
|
25628
|
-
};
|
|
25629
|
-
await notificationService.emit(EventType.UPLOAD, {
|
|
25630
|
-
message: "Uploading collections to Localazy..."
|
|
25631
|
-
});
|
|
25632
|
-
await activityLogsService.addEntry(sessionId, "Uploading collections to Localazy...");
|
|
25633
|
-
try {
|
|
25634
|
-
await LocalazyUploadService2.upload(importFile, uploadConfig);
|
|
25635
|
-
await activityLogsService.recordAttemptedEntries(
|
|
25636
|
-
sessionId,
|
|
25637
|
-
attemptedTuples.map((t3) => ({ ...t3, status: "success" }))
|
|
25638
|
-
);
|
|
25639
|
-
} catch (error) {
|
|
25640
|
-
success = false;
|
|
25641
|
-
const errorMessage = `Upload to Localazy failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
25642
|
-
strapi2.log.error(errorMessage);
|
|
25643
|
-
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
25644
|
-
success,
|
|
25645
|
-
message: errorMessage
|
|
25646
|
-
});
|
|
25647
|
-
await activityLogsService.addEntry(sessionId, errorMessage);
|
|
25648
|
-
await activityLogsService.recordAttemptedEntries(
|
|
25649
|
-
sessionId,
|
|
25650
|
-
attemptedTuples.map((t3) => ({ ...t3, status: "failed", errorMessage }))
|
|
25651
|
-
);
|
|
25652
|
-
await activityLogsService.finishSession(sessionId, "failed", errorMessage);
|
|
25653
|
-
console.timeEnd("upload");
|
|
25654
|
-
return;
|
|
25655
|
-
}
|
|
25656
|
-
strapi2.log.info("Upload finished in");
|
|
25657
|
-
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
25658
|
-
success,
|
|
25659
|
-
message: "Upload finished"
|
|
25660
|
-
});
|
|
25661
|
-
await activityLogsService.addEntry(sessionId, "Upload finished");
|
|
25662
|
-
await activityLogsService.finishSession(
|
|
25663
|
-
sessionId,
|
|
25664
|
-
success ? "completed" : "failed",
|
|
25665
|
-
success ? "Upload completed successfully" : "Upload finished with errors"
|
|
25666
|
-
);
|
|
25667
|
-
console.timeEnd("upload");
|
|
25668
|
-
}
|
|
25669
|
-
});
|
|
25670
25614
|
var symbolTag$2 = "[object Symbol]";
|
|
25671
25615
|
function isSymbol(value) {
|
|
25672
25616
|
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag$2;
|
|
@@ -25981,6 +25925,263 @@ function baseSet(object, path, value, customizer) {
|
|
|
25981
25925
|
function set(object, path, value) {
|
|
25982
25926
|
return object == null ? object : baseSet(object, path, value);
|
|
25983
25927
|
}
|
|
25928
|
+
const BLOCKS_ATTRIBUTE_TYPE = "blocks";
|
|
25929
|
+
const projectBlocksFields = (entry, model, getModel) => {
|
|
25930
|
+
const cloned = cloneDeep(entry);
|
|
25931
|
+
walkAndProject(cloned, model, getModel);
|
|
25932
|
+
return cloned;
|
|
25933
|
+
};
|
|
25934
|
+
const walkAndProject = (value, model, getModel) => {
|
|
25935
|
+
if (!value || !model?.attributes) {
|
|
25936
|
+
return;
|
|
25937
|
+
}
|
|
25938
|
+
for (const [attributeName, attribute] of Object.entries(model.attributes)) {
|
|
25939
|
+
const fieldValue = value[attributeName];
|
|
25940
|
+
if (fieldValue === void 0 || fieldValue === null) {
|
|
25941
|
+
continue;
|
|
25942
|
+
}
|
|
25943
|
+
if (attribute.type === BLOCKS_ATTRIBUTE_TYPE) {
|
|
25944
|
+
value[attributeName] = projectBlocksValue(fieldValue);
|
|
25945
|
+
} else if (attribute.type === "component") {
|
|
25946
|
+
const componentModel = getModel(attribute.component);
|
|
25947
|
+
if (attribute.repeatable && Array.isArray(fieldValue)) {
|
|
25948
|
+
fieldValue.forEach((item) => walkAndProject(item, componentModel, getModel));
|
|
25949
|
+
} else if (isPlainObject(fieldValue)) {
|
|
25950
|
+
walkAndProject(fieldValue, componentModel, getModel);
|
|
25951
|
+
}
|
|
25952
|
+
} else if (attribute.type === "dynamiczone" && Array.isArray(fieldValue)) {
|
|
25953
|
+
fieldValue.forEach((item) => {
|
|
25954
|
+
if (item?.__component) {
|
|
25955
|
+
walkAndProject(item, getModel(item.__component), getModel);
|
|
25956
|
+
}
|
|
25957
|
+
});
|
|
25958
|
+
}
|
|
25959
|
+
}
|
|
25960
|
+
};
|
|
25961
|
+
const projectBlocksValue = (nodes) => {
|
|
25962
|
+
if (!Array.isArray(nodes)) {
|
|
25963
|
+
return nodes;
|
|
25964
|
+
}
|
|
25965
|
+
return nodes.map(projectNode);
|
|
25966
|
+
};
|
|
25967
|
+
const projectNode = (node) => {
|
|
25968
|
+
if (!isPlainObject(node)) {
|
|
25969
|
+
return {};
|
|
25970
|
+
}
|
|
25971
|
+
const projected = {};
|
|
25972
|
+
if (typeof node.text === "string") {
|
|
25973
|
+
projected.text = node.text;
|
|
25974
|
+
}
|
|
25975
|
+
if (Array.isArray(node.children)) {
|
|
25976
|
+
projected.children = node.children.map(projectNode);
|
|
25977
|
+
}
|
|
25978
|
+
return projected;
|
|
25979
|
+
};
|
|
25980
|
+
const overlayBlocksTranslation = (sourceAst, translated) => {
|
|
25981
|
+
if (!Array.isArray(sourceAst)) {
|
|
25982
|
+
return void 0;
|
|
25983
|
+
}
|
|
25984
|
+
return sourceAst.map((node, index2) => overlayNode(node, get(translated, [String(index2)])));
|
|
25985
|
+
};
|
|
25986
|
+
const overlayNode = (node, translatedNode) => {
|
|
25987
|
+
if (!isPlainObject(node)) {
|
|
25988
|
+
return cloneDeep(node);
|
|
25989
|
+
}
|
|
25990
|
+
if (typeof node.text === "string") {
|
|
25991
|
+
const translatedText = isPlainObject(translatedNode) ? translatedNode.text : void 0;
|
|
25992
|
+
return typeof translatedText === "string" ? { ...node, text: translatedText } : cloneDeep(node);
|
|
25993
|
+
}
|
|
25994
|
+
if (Array.isArray(node.children)) {
|
|
25995
|
+
return {
|
|
25996
|
+
...node,
|
|
25997
|
+
children: node.children.map(
|
|
25998
|
+
(child, index2) => overlayNode(child, translatedNode ? get(translatedNode, ["children", String(index2)]) : void 0)
|
|
25999
|
+
)
|
|
26000
|
+
};
|
|
26001
|
+
}
|
|
26002
|
+
return cloneDeep(node);
|
|
26003
|
+
};
|
|
26004
|
+
const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
26005
|
+
async upload({ notificationService }) {
|
|
26006
|
+
console.time("upload");
|
|
26007
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26008
|
+
message: "Upload started"
|
|
26009
|
+
});
|
|
26010
|
+
const activityLogsService = getActivityLogsService();
|
|
26011
|
+
const sessionId = await activityLogsService.startSession("upload", "Strapi User");
|
|
26012
|
+
await activityLogsService.addEntry(sessionId, "Upload started");
|
|
26013
|
+
let success = true;
|
|
26014
|
+
const StrapiService2 = getStrapiService();
|
|
26015
|
+
const StrapiI18nService2 = getStrapiI18nService();
|
|
26016
|
+
const LocalazyUploadService2 = getLocalazyUploadService();
|
|
26017
|
+
const EntryExclusionService2 = getEntryExclusionService();
|
|
26018
|
+
const contentTransferSetup = await getPluginSettingsService().getContentTransferSetup();
|
|
26019
|
+
if (!contentTransferSetup.has_setup) {
|
|
26020
|
+
const message = "Content transfer setup is not set up.";
|
|
26021
|
+
success = false;
|
|
26022
|
+
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
26023
|
+
success,
|
|
26024
|
+
message
|
|
26025
|
+
});
|
|
26026
|
+
await activityLogsService.addEntry(sessionId, message);
|
|
26027
|
+
await activityLogsService.finishSession(sessionId, "failed", message);
|
|
26028
|
+
strapi2.log.info(message);
|
|
26029
|
+
return;
|
|
26030
|
+
}
|
|
26031
|
+
const { setup: setup2 } = contentTransferSetup;
|
|
26032
|
+
const collectionsNames = getCollectionsNames(setup2);
|
|
26033
|
+
const models = await StrapiService2.getModels();
|
|
26034
|
+
const strapiDefaultLocaleCode = await StrapiI18nService2.getDefaultLocaleCode();
|
|
26035
|
+
const attemptedTuples = [];
|
|
26036
|
+
let pickedFlattenStrapiContent = {};
|
|
26037
|
+
for (const collectionName of collectionsNames) {
|
|
26038
|
+
const currentModel = models.find((model) => model.collectionName === collectionName);
|
|
26039
|
+
const modelUid = currentModel.uid;
|
|
26040
|
+
if (!currentModel) {
|
|
26041
|
+
strapi2.log.warn(`Model with uid ${modelUid} is not found.`);
|
|
26042
|
+
continue;
|
|
26043
|
+
}
|
|
26044
|
+
const transferSetupModel = findSetupModelByCollectionName(setup2, collectionName);
|
|
26045
|
+
if (!isCollectionTransferEnabled(setup2, collectionName)) {
|
|
26046
|
+
const message2 = `Collection ${collectionName} transfer is disabled.`;
|
|
26047
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26048
|
+
message: message2
|
|
26049
|
+
});
|
|
26050
|
+
await activityLogsService.addEntry(sessionId, message2);
|
|
26051
|
+
strapi2.log.info(message2);
|
|
26052
|
+
continue;
|
|
26053
|
+
}
|
|
26054
|
+
const currentTransferSetupModel = transferSetupModel[collectionName];
|
|
26055
|
+
const pickPaths = getPickPathsWithComponents(currentTransferSetupModel);
|
|
26056
|
+
if (!pickPaths.length) {
|
|
26057
|
+
const message2 = `No fields for collection ${collectionName} transfer are enabled.`;
|
|
26058
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26059
|
+
message: message2
|
|
26060
|
+
});
|
|
26061
|
+
await activityLogsService.addEntry(sessionId, message2);
|
|
26062
|
+
strapi2.log.warn(message2);
|
|
26063
|
+
continue;
|
|
26064
|
+
}
|
|
26065
|
+
const pickPathsWithUid = pickPaths.map((pickPath) => `${modelUid}.${pickPath}`);
|
|
26066
|
+
let entries = await strapi2.documents(modelUid).findMany({
|
|
26067
|
+
locUploadPLevel: 6,
|
|
26068
|
+
status: "draft"
|
|
26069
|
+
});
|
|
26070
|
+
if (!entries.length) {
|
|
26071
|
+
strapi2.log.info(`No entries found for model ${modelUid}`);
|
|
26072
|
+
continue;
|
|
26073
|
+
}
|
|
26074
|
+
const excludedEntries = await EntryExclusionService2.getContentTypeExclusions(modelUid);
|
|
26075
|
+
const filteredEntries = [];
|
|
26076
|
+
for (const entry of entries) {
|
|
26077
|
+
const isExcluded = excludedEntries.includes(entry.documentId);
|
|
26078
|
+
if (!isExcluded) {
|
|
26079
|
+
filteredEntries.push(entry);
|
|
26080
|
+
}
|
|
26081
|
+
}
|
|
26082
|
+
entries = filteredEntries;
|
|
26083
|
+
if (!entries.length) {
|
|
26084
|
+
const message2 = `All entries for model ${collectionName} are excluded from translation`;
|
|
26085
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26086
|
+
message: message2
|
|
26087
|
+
});
|
|
26088
|
+
await activityLogsService.addEntry(sessionId, message2);
|
|
26089
|
+
strapi2.log.info(message2);
|
|
26090
|
+
continue;
|
|
26091
|
+
}
|
|
26092
|
+
const message = `Excluding ${excludedEntries.length} entries for model ${collectionName} from upload. Entries to translate: ${entries.length}.`;
|
|
26093
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26094
|
+
message
|
|
26095
|
+
});
|
|
26096
|
+
await activityLogsService.addEntry(sessionId, message);
|
|
26097
|
+
strapi2.log.info(message);
|
|
26098
|
+
if (strapiDefaultLocaleCode) {
|
|
26099
|
+
for (const entry of entries) {
|
|
26100
|
+
attemptedTuples.push({
|
|
26101
|
+
uid: modelUid,
|
|
26102
|
+
documentId: entry.documentId,
|
|
26103
|
+
locale: strapiDefaultLocaleCode
|
|
26104
|
+
});
|
|
26105
|
+
}
|
|
26106
|
+
}
|
|
26107
|
+
entries = omitDeep(entries, ["locale", "createdAt", "updatedAt", "publishedAt"]);
|
|
26108
|
+
entries.forEach((entry) => {
|
|
26109
|
+
const projectedEntry = projectBlocksFields(
|
|
26110
|
+
entry,
|
|
26111
|
+
strapi2.getModel(modelUid),
|
|
26112
|
+
(uid) => strapi2.getModel(uid)
|
|
26113
|
+
);
|
|
26114
|
+
const flatten = flattenObject({
|
|
26115
|
+
[modelUid]: projectedEntry
|
|
26116
|
+
});
|
|
26117
|
+
const pickedFlatten = pickEntries(flatten, pickPathsWithUid);
|
|
26118
|
+
pickedFlattenStrapiContent = {
|
|
26119
|
+
...pickedFlattenStrapiContent,
|
|
26120
|
+
...pickedFlatten
|
|
26121
|
+
};
|
|
26122
|
+
});
|
|
26123
|
+
const characterLimitsMetadata = getCharacterLimitsMetadata(pickedFlattenStrapiContent, modelUid);
|
|
26124
|
+
pickedFlattenStrapiContent = {
|
|
26125
|
+
...pickedFlattenStrapiContent,
|
|
26126
|
+
...characterLimitsMetadata
|
|
26127
|
+
};
|
|
26128
|
+
}
|
|
26129
|
+
const localazyLocaleCode = strapiDefaultLocaleCode ? isoStrapiToLocalazy(strapiDefaultLocaleCode) : config.default.LOCALAZY_DEFAULT_LOCALE;
|
|
26130
|
+
const importFile = LocalazyUploadService2.createImportFileRepresentation(
|
|
26131
|
+
localazyLocaleCode,
|
|
26132
|
+
pickedFlattenStrapiContent
|
|
26133
|
+
);
|
|
26134
|
+
const uploadConfig = {
|
|
26135
|
+
contentOptions: {
|
|
26136
|
+
type: config.default.LOCALAZY_DEFAULT_FILE_EXTENSION
|
|
26137
|
+
},
|
|
26138
|
+
i18nOptions: { deprecate: "file" },
|
|
26139
|
+
fileOptions: {
|
|
26140
|
+
name: config.default.LOCALAZY_DEFAULT_FILE_NAME,
|
|
26141
|
+
path: config.default.LOCALAZY_DEFAULT_FILE_PATH
|
|
26142
|
+
}
|
|
26143
|
+
};
|
|
26144
|
+
await notificationService.emit(EventType.UPLOAD, {
|
|
26145
|
+
message: "Uploading collections to Localazy..."
|
|
26146
|
+
});
|
|
26147
|
+
await activityLogsService.addEntry(sessionId, "Uploading collections to Localazy...");
|
|
26148
|
+
try {
|
|
26149
|
+
await LocalazyUploadService2.upload(importFile, uploadConfig);
|
|
26150
|
+
await activityLogsService.recordAttemptedEntries(
|
|
26151
|
+
sessionId,
|
|
26152
|
+
attemptedTuples.map((t3) => ({ ...t3, status: "success" }))
|
|
26153
|
+
);
|
|
26154
|
+
} catch (error) {
|
|
26155
|
+
success = false;
|
|
26156
|
+
const errorMessage = `Upload to Localazy failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
26157
|
+
strapi2.log.error(errorMessage);
|
|
26158
|
+
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
26159
|
+
success,
|
|
26160
|
+
message: errorMessage
|
|
26161
|
+
});
|
|
26162
|
+
await activityLogsService.addEntry(sessionId, errorMessage);
|
|
26163
|
+
await activityLogsService.recordAttemptedEntries(
|
|
26164
|
+
sessionId,
|
|
26165
|
+
attemptedTuples.map((t3) => ({ ...t3, status: "failed", errorMessage }))
|
|
26166
|
+
);
|
|
26167
|
+
await activityLogsService.finishSession(sessionId, "failed", errorMessage);
|
|
26168
|
+
console.timeEnd("upload");
|
|
26169
|
+
return;
|
|
26170
|
+
}
|
|
26171
|
+
strapi2.log.info("Upload finished in");
|
|
26172
|
+
await notificationService.emit(EventType.UPLOAD_FINISHED, {
|
|
26173
|
+
success,
|
|
26174
|
+
message: "Upload finished"
|
|
26175
|
+
});
|
|
26176
|
+
await activityLogsService.addEntry(sessionId, "Upload finished");
|
|
26177
|
+
await activityLogsService.finishSession(
|
|
26178
|
+
sessionId,
|
|
26179
|
+
success ? "completed" : "failed",
|
|
26180
|
+
success ? "Upload completed successfully" : "Upload finished with errors"
|
|
26181
|
+
);
|
|
26182
|
+
console.timeEnd("upload");
|
|
26183
|
+
}
|
|
26184
|
+
});
|
|
25984
26185
|
const hasDynamicZoneKeySegment = (parsedKey) => {
|
|
25985
26186
|
return parsedKey.some((segment) => segment.includes(";"));
|
|
25986
26187
|
};
|
|
@@ -26053,7 +26254,7 @@ const shouldSetDownloadedProperty = (modelContentTransferSetup, parsedKeyRest) =
|
|
|
26053
26254
|
return "no";
|
|
26054
26255
|
}
|
|
26055
26256
|
};
|
|
26056
|
-
const getFilteredLanguagesCodesForDownload = async (languagesCodes) => {
|
|
26257
|
+
const getFilteredLanguagesCodesForDownload = async (languagesCodes, requestedUiLanguages) => {
|
|
26057
26258
|
const pluginSettingsServiceHelper = new PluginSettingsServiceHelper();
|
|
26058
26259
|
const requestInitiatorHelper = new RequestInitiatorHelper(strapi);
|
|
26059
26260
|
await pluginSettingsServiceHelper.setup();
|
|
@@ -26061,7 +26262,7 @@ const getFilteredLanguagesCodesForDownload = async (languagesCodes) => {
|
|
|
26061
26262
|
if (requestInitiatorHelper.isInitiatedByLocalazyWebhook()) {
|
|
26062
26263
|
localLanguagesCodes = pluginSettingsServiceHelper.getWebhookLanguagesCodes();
|
|
26063
26264
|
} else if (requestInitiatorHelper.isInitiatedByLocalazyPluginUI()) {
|
|
26064
|
-
localLanguagesCodes = pluginSettingsServiceHelper.getUiLanguagesCodes();
|
|
26265
|
+
localLanguagesCodes = requestedUiLanguages ?? pluginSettingsServiceHelper.getUiLanguagesCodes();
|
|
26065
26266
|
} else {
|
|
26066
26267
|
strapi.log.warn("Called by an unknown initiator.");
|
|
26067
26268
|
return languagesCodes;
|
|
@@ -26074,7 +26275,8 @@ const getFilteredLanguagesCodesForDownload = async (languagesCodes) => {
|
|
|
26074
26275
|
const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
26075
26276
|
async download({
|
|
26076
26277
|
notificationService,
|
|
26077
|
-
fullSync = false
|
|
26278
|
+
fullSync = false,
|
|
26279
|
+
requestedUiLanguages
|
|
26078
26280
|
}) {
|
|
26079
26281
|
console.time("download");
|
|
26080
26282
|
const syncMode = fullSync ? "Full sync" : "Incremental sync";
|
|
@@ -26154,7 +26356,7 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
26154
26356
|
return;
|
|
26155
26357
|
}
|
|
26156
26358
|
let languagesCodes = projectLanguagesWithoutSourceLanguage.map((language3) => language3.code);
|
|
26157
|
-
languagesCodes = await getFilteredLanguagesCodesForDownload(languagesCodes);
|
|
26359
|
+
languagesCodes = await getFilteredLanguagesCodesForDownload(languagesCodes, requestedUiLanguages);
|
|
26158
26360
|
const strapiUnsupportedLanguages = [];
|
|
26159
26361
|
const strapiLocales = await StrapiI18nService2.getLocales();
|
|
26160
26362
|
for (const isoLocalazy of languagesCodes) {
|
|
@@ -26667,6 +26869,9 @@ const isRepeatable = (attributeObj) => {
|
|
|
26667
26869
|
const isRelation = (attributeObj) => {
|
|
26668
26870
|
return attributeObj.type === "relation" && attributeObj.target !== "plugin::upload.file";
|
|
26669
26871
|
};
|
|
26872
|
+
const isBlocks = (attributeObj) => {
|
|
26873
|
+
return attributeObj.type === BLOCKS_ATTRIBUTE_TYPE;
|
|
26874
|
+
};
|
|
26670
26875
|
const findModel = (models, uid) => {
|
|
26671
26876
|
const model = models.find((model2) => model2.uid === uid);
|
|
26672
26877
|
return model;
|
|
@@ -26810,7 +27015,11 @@ const parsedLocalazyEntryToCreateEntry = (models, parsedLocalazyEntry, baseEntry
|
|
|
26810
27015
|
newPrefixBase = `${dzParamKey}.${baseEntryDZIndex}`;
|
|
26811
27016
|
newPrefix = `${newPrefixBase}.${objectKey}`;
|
|
26812
27017
|
}
|
|
26813
|
-
|
|
27018
|
+
const valueToSet = isBlocks(attribute) ? overlayBlocksTranslation(get(baseEntry, newPrefix), value) : value;
|
|
27019
|
+
if (valueToSet === void 0) {
|
|
27020
|
+
return;
|
|
27021
|
+
}
|
|
27022
|
+
set(createEntry, newPrefix, valueToSet);
|
|
26814
27023
|
if (component) {
|
|
26815
27024
|
const componentKeyToSet = `${newPrefixBase}.__component`;
|
|
26816
27025
|
set(createEntry, componentKeyToSet, component);
|