@localazy/strapi-plugin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/.babelrc +7 -0
  2. package/.eslintrc +7 -0
  3. package/.github/workflows/.build.yml +39 -0
  4. package/.nvmrc +1 -0
  5. package/LICENSE +21 -0
  6. package/README.md +40 -0
  7. package/admin/src/.eslintrc +3 -0
  8. package/admin/src/components/Initializer/index.js +26 -0
  9. package/admin/src/components/PluginIcon/index.js +14 -0
  10. package/admin/src/i18n.js +37 -0
  11. package/admin/src/index.js +106 -0
  12. package/admin/src/modules/@common/components/Icons/Localazy/index.js +12 -0
  13. package/admin/src/modules/@common/components/SideNav/index.js +46 -0
  14. package/admin/src/modules/@common/components/TransferReport/index.js +54 -0
  15. package/admin/src/modules/@common/locale/en.js +13 -0
  16. package/admin/src/modules/@common/services/i18n-service.js +15 -0
  17. package/admin/src/modules/@common/services/project-service.js +15 -0
  18. package/admin/src/modules/@common/services/user-service.js +38 -0
  19. package/admin/src/modules/@common/utils/are-locales-compatible.js +42 -0
  20. package/admin/src/modules/@common/utils/functions/flatten-deep.js +23 -0
  21. package/admin/src/modules/@common/utils/get-default-locale.js +32 -0
  22. package/admin/src/modules/@common/utils/get-header-subtitle.js +21 -0
  23. package/admin/src/modules/@common/utils/get-header-title.js +24 -0
  24. package/admin/src/modules/@common/utils/get-nav.js +35 -0
  25. package/admin/src/modules/@common/utils/history.js +6 -0
  26. package/admin/src/modules/@common/utils/is-plugin-route.js +15 -0
  27. package/admin/src/modules/@common/utils/iso-locales-utils.js +15 -0
  28. package/admin/src/modules/@common/utils/redirect-to-plugin-route.js +22 -0
  29. package/admin/src/modules/@common/utils/sort-by-model-name.js +10 -0
  30. package/admin/src/modules/localazy-download/locale/en.js +20 -0
  31. package/admin/src/modules/localazy-download/services/localazy-download-service.js +16 -0
  32. package/admin/src/modules/localazy-upload/components/ReadDocsButton.js +21 -0
  33. package/admin/src/modules/localazy-upload/locale/en.js +18 -0
  34. package/admin/src/modules/localazy-upload/services/localazy-upload-service.js +16 -0
  35. package/admin/src/modules/login/components/LoginButton/index.js +56 -0
  36. package/admin/src/modules/login/components/LogoutButton/index.js +50 -0
  37. package/admin/src/modules/login/locale/en.js +7 -0
  38. package/admin/src/modules/login/services/localazy-login-service.js +29 -0
  39. package/admin/src/modules/plugin-settings/components/ContentTransferSetup/index.js +292 -0
  40. package/admin/src/modules/plugin-settings/components/Tree/index.js +120 -0
  41. package/admin/src/modules/plugin-settings/components/TreeItem/index.js +48 -0
  42. package/admin/src/modules/plugin-settings/functions/build-content-transfer-setup-schema.js +71 -0
  43. package/admin/src/modules/plugin-settings/functions/has-model-changed.js +85 -0
  44. package/admin/src/modules/plugin-settings/locale/en.js +19 -0
  45. package/admin/src/modules/plugin-settings/services/plugin-settings-service.js +32 -0
  46. package/admin/src/modules/plugin-settings/services/strapi-model-service.js +26 -0
  47. package/admin/src/modules/plugin-settings/utils/__tests__/get-models-tree.test.js +135 -0
  48. package/admin/src/modules/plugin-settings/utils/array-of-models-to-object.js +6 -0
  49. package/admin/src/modules/plugin-settings/utils/find-model-value-by-key.js +8 -0
  50. package/admin/src/modules/plugin-settings/utils/get-filtered-models-schemas.js +34 -0
  51. package/admin/src/modules/plugin-settings/utils/get-models-tree.js +73 -0
  52. package/admin/src/modules/settings/components/OverviewItem/index.js +44 -0
  53. package/admin/src/modules/settings/components/OverviewItemLink/index.js +34 -0
  54. package/admin/src/modules/settings/components/PrerequisitiesInfo/index.js +30 -0
  55. package/admin/src/modules/settings/locale/en.js +13 -0
  56. package/admin/src/modules/user/model/localazy-identity.js +14 -0
  57. package/admin/src/modules/user/services/localazy-user-service.js +38 -0
  58. package/admin/src/pages/App/index.js +152 -0
  59. package/admin/src/pages/Download/index.js +179 -0
  60. package/admin/src/pages/Index/index.js +8 -0
  61. package/admin/src/pages/Login/index.js +94 -0
  62. package/admin/src/pages/PluginSettings/index.js +42 -0
  63. package/admin/src/pages/Settings/index.js +120 -0
  64. package/admin/src/pages/Upload/index.js +187 -0
  65. package/admin/src/pluginId.js +5 -0
  66. package/admin/src/plugins/apolloClient.js +33 -0
  67. package/admin/src/state/localazy-identity.js +29 -0
  68. package/admin/src/tests/fixtures/all-models.js +877 -0
  69. package/admin/src/tests/fixtures/restaurant-model.js +230 -0
  70. package/admin/src/translations/en.json +4 -0
  71. package/admin/src/translations/fr.json +1 -0
  72. package/admin/src/utils/createAxiosInstance.js +52 -0
  73. package/admin/src/utils/getTrad.js +5 -0
  74. package/jest.config.js +0 -0
  75. package/package.json +60 -0
  76. package/server/bootstrap.js +5 -0
  77. package/server/config/development/index.js +15 -0
  78. package/server/config/example/index.js +15 -0
  79. package/server/config/index.js +15 -0
  80. package/server/config/production/index.js +16 -0
  81. package/server/config/schema.graphql.js +21 -0
  82. package/server/content-types/index.js +3 -0
  83. package/server/controllers/index.js +19 -0
  84. package/server/controllers/localazy-auth-controller.js +46 -0
  85. package/server/controllers/localazy-project-controller.js +21 -0
  86. package/server/controllers/localazy-transfer-controller.js +469 -0
  87. package/server/controllers/localazy-user-controller.js +24 -0
  88. package/server/controllers/my-controller.js +10 -0
  89. package/server/controllers/plugin-settings-controller.js +17 -0
  90. package/server/controllers/strapi-controller.js +16 -0
  91. package/server/db/model/content-transfer-setup.js +13 -0
  92. package/server/db/model/localazy-user.js +23 -0
  93. package/server/db/model/utils/get-strapi-store.js +9 -0
  94. package/server/destroy.js +5 -0
  95. package/server/index.js +25 -0
  96. package/server/middlewares/index.js +3 -0
  97. package/server/policies/index.js +3 -0
  98. package/server/register.js +5 -0
  99. package/server/routes/index.js +26 -0
  100. package/server/routes/localazy-auth.js +22 -0
  101. package/server/routes/localazy-project.js +14 -0
  102. package/server/routes/localazy-transfer.js +22 -0
  103. package/server/routes/localazy-user.js +30 -0
  104. package/server/routes/plugin-settings.js +22 -0
  105. package/server/routes/strapi.js +22 -0
  106. package/server/services/index.js +21 -0
  107. package/server/services/localazy-auth-service.js +38 -0
  108. package/server/services/localazy-download-service.js +54 -0
  109. package/server/services/localazy-pubapi-service.js +47 -0
  110. package/server/services/localazy-upload-service.js +95 -0
  111. package/server/services/localazy-user-service.js +29 -0
  112. package/server/services/plugin-settings-service.js +30 -0
  113. package/server/services/strapi-i18n-service.js +132 -0
  114. package/server/services/strapi-service.js +23 -0
  115. package/server/tests/fixtures/all-models-with-multimedia.js +1064 -0
  116. package/server/tests/fixtures/all-models.js +869 -0
  117. package/server/tests/fixtures/collection-flattened.js +76 -0
  118. package/server/tests/fixtures/restaurant-flattened.js +46 -0
  119. package/server/tests/fixtures/restaurant-model.js +230 -0
  120. package/server/tests/fixtures/restaurants-entries.js +152 -0
  121. package/server/tests/fixtures/restaurants-pick-paths.js +15 -0
  122. package/server/tests/fixtures/strapi-book-with-multimedia-components-cs.js +31 -0
  123. package/server/tests/fixtures/stringified-book-cs.js +3 -0
  124. package/server/tests/fixtures/stringified-book-with-multimedia-components-cs.js +3 -0
  125. package/server/tests/fixtures/stringified-restaurant-cs.js +3 -0
  126. package/server/tests/fixtures/stringified-restaurant-de.js +5 -0
  127. package/server/utils/__tests__/build-populate.test.js +85 -0
  128. package/server/utils/__tests__/flatten-object.test.js +171 -0
  129. package/server/utils/__tests__/get-models-tree.test.js +170 -0
  130. package/server/utils/__tests__/parsed-localazy-entry-to-create-entry.test.js +153 -0
  131. package/server/utils/__tests__/parsed-localazy-entry-to-update-entry.test.js +172 -0
  132. package/server/utils/__tests__/pick-entries.test.js +83 -0
  133. package/server/utils/build-populate.js +43 -0
  134. package/server/utils/delay.js +6 -0
  135. package/server/utils/flatten-object.js +52 -0
  136. package/server/utils/get-localazy-api.js +22 -0
  137. package/server/utils/get-main-keys-of-nested-array-objects.js +5 -0
  138. package/server/utils/get-models-tree.js +43 -0
  139. package/server/utils/intl-display-name.js +7 -0
  140. package/server/utils/is-generally-applicable-content-type.js +33 -0
  141. package/server/utils/is-localazy-applicable-content-type.js +36 -0
  142. package/server/utils/iso-locales-utils.js +22 -0
  143. package/server/utils/objectivise-entry.js +41 -0
  144. package/server/utils/omit-deep.js +17 -0
  145. package/server/utils/parsed-localazy-entry-to-create-entry.js +115 -0
  146. package/server/utils/parsed-localazy-entry-to-update-entry.js +31 -0
  147. package/server/utils/pick-entries.js +14 -0
  148. package/server/utils/transfer-setup-utils.js +39 -0
  149. package/strapi-admin.js +14 -0
  150. package/strapi-server.js +5 -0
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ const pickEntries = require("../pick-entries");
4
+ const restaurantFlattened = require("../../tests/fixtures/restaurant-flattened");
5
+ const collectionFlattened = require("../../tests/fixtures/collection-flattened");
6
+ const restaurantsPickPaths = require("../../tests/fixtures/restaurants-pick-paths");
7
+
8
+ describe("pick entries test suite", () => {
9
+ it("should return picked entries from 1 restaurant", () => {
10
+ // SETUP
11
+ const entry = restaurantFlattened;
12
+ const pickPaths = [
13
+ "api::restaurant.restaurant.title",
14
+ "api::restaurant.restaurant.description",
15
+ "api::restaurant.restaurant.street",
16
+ "api::restaurant.restaurant.city",
17
+ "api::restaurant.restaurant.country",
18
+ "api::restaurant.restaurant.id",
19
+ ];
20
+
21
+ // EXECUTE
22
+ const result = pickEntries(entry, pickPaths);
23
+
24
+ // VERIFY
25
+ const expected = {
26
+ "api::restaurant.restaurant[3].city": "Testow",
27
+ "api::restaurant.restaurant[3].country": "Test Rep.",
28
+ "api::restaurant.restaurant[3].description":
29
+ "With some great description",
30
+ "api::restaurant.restaurant[3].street": "Testowa",
31
+ "api::restaurant.restaurant[3].title": "Full Restaurant",
32
+ };
33
+ expect(result).toEqual(expected);
34
+ });
35
+
36
+ it("should return picked entries from collection", () => {
37
+ // SETUP
38
+ const entry = collectionFlattened;
39
+ const pickPaths = restaurantsPickPaths("api::restaurant.restaurant");
40
+
41
+ // EXECUTE
42
+ const result = pickEntries(entry, pickPaths);
43
+
44
+ // VERIFY
45
+ const expected = {
46
+ "api::restaurant.restaurant[1].description": "Restaurant 1 description",
47
+ "api::restaurant.restaurant[1].descs[1].rich_description":
48
+ "restaurant 1 rich_desc",
49
+ "api::restaurant.restaurant[1].title": "Restaurant 1",
50
+ "api::restaurant.restaurant[2].description": "Restaurant 2 description",
51
+ "api::restaurant.restaurant[2].title": "Restaurant 2",
52
+ "api::restaurant.restaurant[3].city": "Testow",
53
+ "api::restaurant.restaurant[3].country": "Test Rep.",
54
+ "api::restaurant.restaurant[3].description":
55
+ "With some great description",
56
+ "api::restaurant.restaurant[3].descs[3].excerpt": "Est. 2022",
57
+ "api::restaurant.restaurant[3].descs[3].history":
58
+ "Est. 2022, based in NY, NY",
59
+ "api::restaurant.restaurant[3].descs[3].rich_description":
60
+ "Another restaurant desc",
61
+ "api::restaurant.restaurant[3].descs[3].test_variants[5].name":
62
+ "no such thing...",
63
+ "api::restaurant.restaurant[3].recipes[2].ingredients[4].name": "Beef",
64
+ "api::restaurant.restaurant[3].recipes[2].ingredients[5].name": "Water",
65
+ "api::restaurant.restaurant[3].recipes[2].name": "Beef Broth",
66
+ "api::restaurant.restaurant[3].recipes[3].ingredients[2].name": "Tomato",
67
+ "api::restaurant.restaurant[3].recipes[3].ingredients[3].name": "Soup",
68
+ "api::restaurant.restaurant[3].recipes[3].name": "Tomato Soup",
69
+ "api::restaurant.restaurant[3].recipes[3].variants[4].name":
70
+ "Red, yellow, green",
71
+ "api::restaurant.restaurant[3].recipes[4].ingredients[6].name":
72
+ "Beef meat",
73
+ "api::restaurant.restaurant[3].recipes[4].ingredients[7].name": "Pepper",
74
+ "api::restaurant.restaurant[3].recipes[4].ingredients[8].name":
75
+ "Pepper spices",
76
+ "api::restaurant.restaurant[3].recipes[4].ingredients[9].name": "Water",
77
+ "api::restaurant.restaurant[3].recipes[4].name": "Goulash",
78
+ "api::restaurant.restaurant[3].street": "Testowa",
79
+ "api::restaurant.restaurant[3].title": "Full Restaurant",
80
+ };
81
+ expect(result).toEqual(expected);
82
+ });
83
+ });
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ const set = require("lodash/set");
4
+
5
+ const getPopulateObject = (keys) => {
6
+ const populate = {};
7
+ for (const key of keys) {
8
+ set(populate, key, "*");
9
+ }
10
+
11
+ return populate;
12
+ };
13
+
14
+ const buildPopulate = (models, modelUid) => {
15
+ const buildPopulateStep = (models, modelUid, prefix = "") => {
16
+ const model = models.find((model) => model.uid === modelUid);
17
+
18
+ if (!model || !model.attributes) {
19
+ return getPopulateObject(keys);
20
+ }
21
+
22
+ for (const [attributeName, attribute] of Object.entries(model.attributes)) {
23
+ if (attribute.type === "component") {
24
+ const key = prefix
25
+ ? `${prefix}.${attributeName}.populate`
26
+ : `${attributeName}.populate`;
27
+ keys.push(key);
28
+ const newPrefix = prefix
29
+ ? `${prefix}.${attributeName}`
30
+ : `${attributeName}`;
31
+ const innerModelUid = attribute.component;
32
+ buildPopulateStep(models, innerModelUid, newPrefix);
33
+ }
34
+ }
35
+
36
+ return getPopulateObject(keys);
37
+ };
38
+ const keys = ["populate"];
39
+
40
+ return buildPopulateStep(models, modelUid);
41
+ };
42
+
43
+ module.exports = buildPopulate;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ // eslint-disable-next-line no-promise-executor-return
4
+ const delay = (ms = 150) => new Promise((resolve) => setTimeout(resolve, ms));
5
+
6
+ module.exports = delay;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ const flattenObject = (object, prefix = "") => {
4
+ const result = {};
5
+
6
+ for (const objectKey in object) {
7
+ if (objectKey === "id") {
8
+ continue;
9
+ }
10
+
11
+ if (typeof object[objectKey] !== "object") {
12
+ const key = prefix ? `${prefix}.${objectKey}` : objectKey;
13
+ // Simple leaf (e.g. string or number)
14
+ result[key] = object[objectKey];
15
+ } else {
16
+ // Recursive call down to flattened object
17
+ let flatObject;
18
+
19
+ // If it is an array then turn it into an object with the correct keys
20
+ if (Array.isArray(object[objectKey])) {
21
+ // Reduce each item into the right key
22
+ const flattenedArray = object[objectKey].reduce(
23
+ (accumulator, item, index) => {
24
+ // No id should use the index of the array item
25
+ accumulator[`${objectKey}[${item.id || index}]`] =
26
+ flattenObject(item);
27
+ return accumulator;
28
+ },
29
+ {}
30
+ );
31
+
32
+ // Then flatten it
33
+ flatObject = flattenObject(flattenedArray);
34
+ } else {
35
+ // Otherwise it is a complex object so you want to flatten that
36
+ // but with the prefix of this current object key
37
+ const suffix = object[objectKey]?.id
38
+ ? `${objectKey}[${object[objectKey].id}]`
39
+ : objectKey;
40
+ flatObject = flattenObject(object[objectKey], suffix);
41
+ }
42
+
43
+ for (const flatObjectKey in flatObject) {
44
+ const key = prefix ? `${prefix}.${flatObjectKey}` : flatObjectKey;
45
+ result[`${key}`] = flatObject[flatObjectKey];
46
+ }
47
+ }
48
+ }
49
+ return result;
50
+ };
51
+
52
+ module.exports = flattenObject;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ const LocalazyApi = require("@localazy/ts-api").default;
4
+ const { LOCALAZY_PUBLIC_API_URL } = require("../config").default;
5
+
6
+ module.exports = async () => {
7
+ const user = await strapi
8
+ .plugin("localazy")
9
+ .service("localazyUserService")
10
+ .getUser();
11
+
12
+ const { accessToken } = user;
13
+ if (!accessToken) {
14
+ throw new Error("Localazy user is not logged in.");
15
+ }
16
+
17
+ const api = LocalazyApi({
18
+ projectToken: accessToken,
19
+ baseUrl: LOCALAZY_PUBLIC_API_URL,
20
+ });
21
+ return api;
22
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ module.exports = (array) => {
4
+ return array.map((item) => Object.keys(item)[0]);
5
+ };
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ const getModelTree = (attributes, models) => {
4
+ const currentModelTree = {};
5
+ for (const attribute in attributes) {
6
+ if (attributes[attribute].type === "component") {
7
+ const nestedModel = models.find(
8
+ (model) => model.uid === attributes[attribute].component
9
+ );
10
+
11
+ currentModelTree[attribute] = {
12
+ ...getModelTree(nestedModel.__schema__.attributes, models),
13
+ };
14
+ } else if (
15
+ ["string", "text", "richtext"].includes(attributes[attribute].type)
16
+ ) {
17
+ currentModelTree[attribute] = false;
18
+ } else {
19
+ currentModelTree[attribute] = null;
20
+ }
21
+ }
22
+
23
+ return currentModelTree;
24
+ };
25
+
26
+ /**
27
+ * Kinds of models ["collectionType", "singleType"] are expected by the function.
28
+ */
29
+ const getModelsTree = (models) => {
30
+ const modelsTree = [];
31
+ for (const model of models) {
32
+ const modelTree = {
33
+ [model.__schema__.collectionName]: {
34
+ __model__: true,
35
+ ...getModelTree(model.__schema__.attributes, models),
36
+ },
37
+ };
38
+ modelsTree.push(modelTree);
39
+ }
40
+ return modelsTree;
41
+ };
42
+
43
+ module.exports = getModelsTree;
@@ -0,0 +1,7 @@
1
+ const { isoStrapiToLocalazy } = require("./iso-locales-utils.js");
2
+
3
+ module.exports = (isoCode) => {
4
+ const isoDashed = isoStrapiToLocalazy(isoCode);
5
+ let languageNames = new Intl.DisplayNames(["en"], { type: "language" });
6
+ return languageNames.of(isoDashed);
7
+ };
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ const SUPPORTED_MODEL_TYPES = ["contentType", "component"];
4
+ const UNSUPPORTED_UID_PREFIXES = [
5
+ "strapi::core",
6
+ "plugin::users-permissions.user",
7
+ ];
8
+
9
+ module.exports = (model) => {
10
+ for (const prefix of UNSUPPORTED_UID_PREFIXES) {
11
+ if (model.uid.includes(prefix)) {
12
+ return false;
13
+ }
14
+ }
15
+
16
+ if (!SUPPORTED_MODEL_TYPES.includes(model.modelType)) {
17
+ return false;
18
+ }
19
+
20
+ // is not applicable
21
+ // eslint-disable-next-line no-underscore-dangle
22
+ if (!model.__schema__) {
23
+ return false;
24
+ }
25
+
26
+ if (model.pluginOptions) {
27
+ if (model.pluginOptions["content-type-builder"]) {
28
+ return model.pluginOptions["content-type-builder"].visible;
29
+ }
30
+ }
31
+
32
+ return true;
33
+ };
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ const isGenerallyApplicableContentType = require("./is-generally-applicable-content-type");
4
+
5
+ module.exports = (model) => {
6
+ const isGenerallyApplicable = isGenerallyApplicableContentType(model);
7
+ if (!isGenerallyApplicable) {
8
+ return false;
9
+ }
10
+
11
+ // cannot be translatable
12
+ if (!model.pluginOptions) {
13
+ return false;
14
+ }
15
+
16
+ // cannot be translatable
17
+ if (!model.pluginOptions) {
18
+ return false;
19
+ }
20
+
21
+ if (model.pluginOptions) {
22
+ // cannot be translatable
23
+ if (!model.pluginOptions["i18n"]) {
24
+ return false;
25
+ }
26
+
27
+ // decide whether it is translatable
28
+ if (model.pluginOptions["i18n"]) {
29
+ return model.pluginOptions["i18n"].localized
30
+ ? model.pluginOptions["i18n"].localized
31
+ : false;
32
+ }
33
+ }
34
+
35
+ return true;
36
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ const isoStrapiToLocalazy = (isoStrapi) => {
4
+ if (!isoStrapi) {
5
+ return null;
6
+ }
7
+
8
+ return isoStrapi.replace("_", "-");
9
+ };
10
+
11
+ const isoLocalazyToStrapi = (isoLocalazy) => {
12
+ if (!isoLocalazy) {
13
+ return null;
14
+ }
15
+
16
+ return isoLocalazy.replace("-", "_");
17
+ };
18
+
19
+ module.exports = {
20
+ isoStrapiToLocalazy,
21
+ isoLocalazyToStrapi,
22
+ };
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ const set = require("lodash/set");
4
+
5
+ const arrayToObject = (array, keyField) =>
6
+ array.reduce((obj, item) => {
7
+ obj[item[keyField]] = item;
8
+ return obj;
9
+ }, {});
10
+
11
+ const objectiviseEntry = (entry) => {
12
+ const objectivized = {};
13
+
14
+ const objectiviseEntryStep = (entryStep, prefix = "") => {
15
+ if (entryStep === null || typeof entryStep !== "object") {
16
+ set(objectivized, prefix, entryStep);
17
+ } else {
18
+ if (Array.isArray(entryStep)) {
19
+ const arrayedEntry = arrayToObject(entryStep, "id");
20
+ Object.keys(arrayedEntry).forEach((key) => {
21
+ objectiviseEntryStep(
22
+ arrayedEntry[key],
23
+ prefix ? `${prefix}.${key}` : key
24
+ );
25
+ });
26
+ } else {
27
+ Object.keys(entryStep).forEach((key) => {
28
+ objectiviseEntryStep(
29
+ entryStep[key],
30
+ prefix ? `${prefix}.${key}` : key
31
+ );
32
+ });
33
+ }
34
+ }
35
+ };
36
+ objectiviseEntryStep(entry);
37
+
38
+ return objectivized;
39
+ };
40
+
41
+ module.exports = objectiviseEntry;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ const cloneDeepWith = require("lodash/cloneDeepWith");
4
+
5
+ function omitDeep(collection, excludeKeys) {
6
+ function omitFn(value) {
7
+ if (value && typeof value === "object") {
8
+ excludeKeys.forEach((key) => {
9
+ delete value[key];
10
+ });
11
+ }
12
+ }
13
+
14
+ return cloneDeepWith(collection, omitFn);
15
+ }
16
+
17
+ module.exports = omitDeep;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ const set = require("lodash/set");
4
+
5
+ const getAttribute = (model, attribute) => {
6
+ const attributeObj = model.attributes[attribute];
7
+ return attributeObj;
8
+ };
9
+
10
+ const isComponent = (attributeObj) => {
11
+ return attributeObj.type === "component";
12
+ };
13
+
14
+ const isRepeatable = (attributeObj) => {
15
+ return isComponent(attributeObj) && !!attributeObj.repeatable;
16
+ };
17
+
18
+ const findModel = (models, uid) => {
19
+ const model = models.find((model) => model.uid === uid);
20
+ return model;
21
+ };
22
+
23
+ const parsedLocalazyEntryToCreateEntry = (
24
+ models,
25
+ parsedLocalazyEntry,
26
+ uid,
27
+ locale = ""
28
+ ) => {
29
+ const createEntry = {};
30
+
31
+ const toCreateEntry = (
32
+ entry,
33
+ model,
34
+ // eslint-disable-next-line no-unused-vars
35
+ key = "",
36
+ prefix = "",
37
+ component = "",
38
+ isRepeatableComponent = false
39
+ ) => {
40
+ if (Array.isArray(entry)) {
41
+ // is array
42
+ let i = 0;
43
+ Object.entries(entry).forEach(([, value]) => {
44
+ if (value !== null) {
45
+ if (component && isRepeatableComponent) {
46
+ toCreateEntry(value, model, i, `${prefix}.${i}`, component);
47
+ i += 1;
48
+ }
49
+
50
+ if (component && !isRepeatableComponent) {
51
+ toCreateEntry(value, model, `${prefix}`, `${prefix}`);
52
+ }
53
+ }
54
+ });
55
+ } else {
56
+ // is object
57
+ Object.entries(entry).forEach(([objectKey, value]) => {
58
+ const attribute = getAttribute(model, objectKey);
59
+ if (attribute === undefined) {
60
+ // logicaly don't anything, skip...
61
+ } else if (isComponent(attribute)) {
62
+ // is component
63
+ const component = attribute.component;
64
+ const componentModel = findModel(models, component);
65
+ if (isRepeatable(attribute)) {
66
+ // is repeatable - array
67
+ const newPrefix = prefix
68
+ ? `${prefix}.${objectKey}`
69
+ : `${objectKey}`;
70
+ toCreateEntry(
71
+ value,
72
+ componentModel,
73
+ objectKey,
74
+ newPrefix,
75
+ component,
76
+ true
77
+ );
78
+ } else {
79
+ // is no repeatable - object
80
+ const newPrefix = prefix
81
+ ? `${prefix}.${objectKey}`
82
+ : `${objectKey}`;
83
+ set(createEntry, `${newPrefix}.__component`, component);
84
+ toCreateEntry(
85
+ value,
86
+ componentModel,
87
+ objectKey,
88
+ newPrefix,
89
+ component,
90
+ false
91
+ );
92
+ }
93
+ } else {
94
+ const newPrefix = prefix ? `${prefix}.${objectKey}` : `${objectKey}`;
95
+ set(createEntry, newPrefix, value);
96
+
97
+ if (component) {
98
+ set(createEntry, `${prefix}.__component`, component);
99
+ }
100
+ // is not component
101
+ }
102
+ });
103
+ }
104
+ };
105
+
106
+ const model = findModel(models, uid);
107
+ toCreateEntry(parsedLocalazyEntry, model);
108
+ if (locale) {
109
+ createEntry.locale = locale;
110
+ }
111
+
112
+ return createEntry;
113
+ };
114
+
115
+ module.exports = parsedLocalazyEntryToCreateEntry;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ const merge = require("lodash/merge");
4
+ const parsedLocalazyEntryToCreateEntry = require("./parsed-localazy-entry-to-create-entry");
5
+ const omitDeep = require("./omit-deep");
6
+
7
+ const parsedLocalazyEntryToUpdateEntry = (
8
+ allModels,
9
+ localazyEntry,
10
+ currentEntry,
11
+ uid
12
+ ) => {
13
+ const createEntry = parsedLocalazyEntryToCreateEntry(
14
+ allModels,
15
+ localazyEntry,
16
+ uid
17
+ );
18
+ let updateEntry = merge(currentEntry, createEntry);
19
+ updateEntry = omitDeep(updateEntry, [
20
+ "__component",
21
+ "locale",
22
+ "localizations",
23
+ "createdAt",
24
+ "updatedAt",
25
+ "publishedAt",
26
+ ]);
27
+
28
+ return updateEntry;
29
+ };
30
+
31
+ module.exports = parsedLocalazyEntryToUpdateEntry;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ const pickEntries = (flatten, pickPaths) => {
4
+ const pickedEntries = {};
5
+ Object.keys(flatten).forEach((key) => {
6
+ const filteredKey = key.replace(/\d|[[\]]+/g, "");
7
+ if (pickPaths.includes(filteredKey)) {
8
+ pickedEntries[key] = flatten[key];
9
+ }
10
+ });
11
+ return pickedEntries;
12
+ };
13
+
14
+ module.exports = pickEntries;
@@ -0,0 +1,39 @@
1
+ const getMainKeysOfNestedArrayObjects = require("./get-main-keys-of-nested-array-objects");
2
+ const flattenObject = require("./flatten-object");
3
+
4
+ const findSetupModelByCollectionName = (models, collectionName) => {
5
+ return models.find((model) => Object.keys(model)[0] === collectionName);
6
+ };
7
+
8
+ const getCollectionsNames = (setup) => {
9
+ return getMainKeysOfNestedArrayObjects(setup);
10
+ };
11
+
12
+ const isCollectionTransferEnabled = (models, collectionName) => {
13
+ const model = findSetupModelByCollectionName(models, collectionName);
14
+
15
+ if (!model || !model[collectionName]) {
16
+ return false;
17
+ }
18
+
19
+ return !!model[collectionName].__model__;
20
+ };
21
+
22
+ const getPickPaths = (transferSetupModelProps) => {
23
+ const flattenedObject = flattenObject(transferSetupModelProps);
24
+ const pickPaths = Object.keys(flattenedObject).filter(
25
+ (key) => flattenedObject[key] === true && key.indexOf("__model__") === -1
26
+ );
27
+
28
+ // id needs to be always included
29
+ pickPaths.push("id");
30
+
31
+ return pickPaths;
32
+ };
33
+
34
+ module.exports = {
35
+ findSetupModelByCollectionName,
36
+ getCollectionsNames,
37
+ isCollectionTransferEnabled,
38
+ getPickPaths,
39
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ // TODO: resolve if possible
4
+ // https://medium.com/the-javascript-dojo/improving-code-readability-with-path-aliases-1a41143d7632
5
+ // const moduleAlias = require("module-alias");
6
+
7
+ // moduleAlias.addAliases({
8
+ // // eslint-disable-next-line node/no-path-concat
9
+ // "@admin": `${__dirname}/admin`,
10
+ // // eslint-disable-next-line node/no-path-concat
11
+ // "@src": `${__dirname}/admin/src`,
12
+ // });
13
+
14
+ module.exports = require("./admin/src").default;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ require("isomorphic-fetch");
4
+
5
+ module.exports = require("./server");