sb-mig 5.6.0-beta.1 → 5.6.0-beta.3

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 (173) hide show
  1. package/README.md +20 -19
  2. package/dist/api/assets/assets.js +2 -15
  3. package/dist/api/auth/auth.types.d.ts +1 -1
  4. package/dist/api/components/components.js +2 -1
  5. package/dist/api/components/components.sync.d.ts +8 -0
  6. package/dist/api/components/components.sync.js +193 -0
  7. package/dist/api/data-migration/component-data-migration.js +2 -2
  8. package/dist/api/datasources/datasource-entries.js +4 -5
  9. package/dist/api/datasources/datasources.d.ts +5 -2
  10. package/dist/api/datasources/datasources.js +42 -35
  11. package/dist/api/datasources/datasources.sync.d.ts +2 -0
  12. package/dist/api/datasources/datasources.sync.js +11 -0
  13. package/dist/api/datasources/datasources.types.d.ts +1 -1
  14. package/dist/api/datasources/index.d.ts +2 -1
  15. package/dist/api/datasources/index.js +2 -1
  16. package/dist/api/managementApi.d.ts +2 -2
  17. package/dist/api/migrate.d.ts +1 -1
  18. package/dist/api/migrate.js +3 -48
  19. package/dist/api/plugins/index.d.ts +2 -1
  20. package/dist/api/plugins/index.js +2 -1
  21. package/dist/api/plugins/plugins.d.ts +7 -2
  22. package/dist/api/plugins/plugins.js +28 -15
  23. package/dist/api/plugins/plugins.sync.d.ts +2 -0
  24. package/dist/api/plugins/plugins.sync.js +11 -0
  25. package/dist/api/roles/index.d.ts +2 -1
  26. package/dist/api/roles/index.js +2 -1
  27. package/dist/api/roles/roles.d.ts +5 -2
  28. package/dist/api/roles/roles.js +34 -11
  29. package/dist/api/roles/roles.sync.d.ts +2 -0
  30. package/dist/api/roles/roles.sync.js +6 -0
  31. package/dist/api/roles/roles.types.d.ts +1 -1
  32. package/dist/api/stories/stories.js +3 -11
  33. package/dist/api/sync/sync.types.d.ts +30 -0
  34. package/dist/api/sync/sync.types.js +1 -0
  35. package/dist/api/testApi.d.ts +2 -2
  36. package/dist/api/utils/helper-functions.d.ts +5 -1
  37. package/dist/api/utils/helper-functions.js +6 -1
  38. package/dist/api/utils/request.d.ts +1 -1
  39. package/dist/api/utils/request.js +11 -2
  40. package/dist/api/utils/resolverTransformations.js +2 -57
  41. package/dist/api-v2/assets/index.d.ts +13 -0
  42. package/dist/api-v2/assets/index.js +25 -0
  43. package/dist/api-v2/auth/index.d.ts +3 -0
  44. package/dist/api-v2/auth/index.js +8 -0
  45. package/dist/api-v2/client.d.ts +13 -0
  46. package/dist/api-v2/client.js +17 -0
  47. package/dist/api-v2/components/index.d.ts +10 -0
  48. package/dist/api-v2/components/index.js +29 -0
  49. package/dist/api-v2/datasources/index.d.ts +8 -0
  50. package/dist/api-v2/datasources/index.js +58 -0
  51. package/dist/api-v2/discover/discover.d.ts +47 -0
  52. package/dist/api-v2/discover/discover.js +328 -0
  53. package/dist/api-v2/discover/index.d.ts +2 -0
  54. package/dist/api-v2/discover/index.js +1 -0
  55. package/dist/api-v2/index.d.ts +19 -0
  56. package/dist/api-v2/index.js +21 -0
  57. package/dist/api-v2/plugins/index.d.ts +9 -0
  58. package/dist/api-v2/plugins/index.js +42 -0
  59. package/dist/api-v2/precompile/index.d.ts +2 -0
  60. package/dist/api-v2/precompile/index.js +1 -0
  61. package/dist/api-v2/precompile/precompile.d.ts +65 -0
  62. package/dist/api-v2/precompile/precompile.js +127 -0
  63. package/dist/api-v2/presets/index.d.ts +13 -0
  64. package/dist/api-v2/presets/index.js +25 -0
  65. package/dist/api-v2/requestConfig.d.ts +5 -0
  66. package/dist/api-v2/requestConfig.js +34 -0
  67. package/dist/api-v2/roles/index.d.ts +5 -0
  68. package/dist/api-v2/roles/index.js +35 -0
  69. package/dist/api-v2/spaces/index.d.ts +7 -0
  70. package/dist/api-v2/spaces/index.js +11 -0
  71. package/dist/api-v2/stories/index.d.ts +34 -0
  72. package/dist/api-v2/stories/index.js +172 -0
  73. package/dist/api-v2/stories/types.d.ts +28 -0
  74. package/dist/api-v2/stories/types.js +1 -0
  75. package/dist/api-v2/sync/index.d.ts +24 -0
  76. package/dist/api-v2/sync/index.js +109 -0
  77. package/dist/api-v2/sync/types.d.ts +1 -0
  78. package/dist/api-v2/sync/types.js +1 -0
  79. package/dist/api-v2/test.d.ts +15 -0
  80. package/dist/api-v2/test.js +21 -0
  81. package/dist/cli/commands/backup.js +7 -3
  82. package/dist/cli/commands/copy.js +2 -2
  83. package/dist/cli/commands/migrate.js +1 -2
  84. package/dist/cli/commands/migrations.js +2 -2
  85. package/dist/cli/commands/remove.js +1 -1
  86. package/dist/cli/commands/revert.js +2 -2
  87. package/dist/cli/commands/sync.js +1 -2
  88. package/dist/cli/index.js +1 -1
  89. package/dist/cli/utils/cli-utils.d.ts +69 -0
  90. package/dist/cli/utils/cli-utils.js +100 -0
  91. package/dist/cli/utils/discover.d.ts +3 -22
  92. package/dist/cli/utils/discover.js +53 -100
  93. package/dist/config/config.d.ts +2 -39
  94. package/dist/config/config.types.d.ts +40 -0
  95. package/dist/config/config.types.js +1 -0
  96. package/dist/config/defaultConfig.d.ts +1 -1
  97. package/dist/config/defaultConfig.js +2 -2
  98. package/dist/utils/array-utils.d.ts +20 -0
  99. package/dist/utils/array-utils.js +20 -0
  100. package/dist/utils/async-utils.d.ts +13 -0
  101. package/dist/utils/async-utils.js +13 -0
  102. package/dist/utils/date-utils.d.ts +14 -0
  103. package/dist/utils/date-utils.js +21 -0
  104. package/dist/utils/files.d.ts +35 -0
  105. package/dist/utils/files.js +57 -2
  106. package/dist/utils/main.d.ts +8 -18
  107. package/dist/utils/main.js +12 -104
  108. package/dist/utils/migrations.d.ts +9 -3
  109. package/dist/utils/object-utils.d.ts +46 -0
  110. package/dist/utils/object-utils.js +71 -0
  111. package/dist/utils/others.d.ts +6 -9
  112. package/dist/utils/others.js +8 -15
  113. package/dist/utils/path-utils.d.ts +89 -0
  114. package/dist/utils/path-utils.js +106 -0
  115. package/dist/utils/pkg.d.ts +16 -2
  116. package/dist/utils/pkg.js +16 -3
  117. package/dist/utils/string-utils.d.ts +33 -0
  118. package/dist/utils/string-utils.js +45 -0
  119. package/dist/utils/transform-utils.d.ts +62 -0
  120. package/dist/utils/transform-utils.js +113 -0
  121. package/dist-cjs/api/auth/auth.js +28 -0
  122. package/dist-cjs/api/auth/auth.types.js +2 -0
  123. package/dist-cjs/api/components/components.js +202 -0
  124. package/dist-cjs/api/components/components.sync.js +199 -0
  125. package/dist-cjs/api/components/components.types.js +2 -0
  126. package/dist-cjs/api/datasources/datasource-entries.js +166 -0
  127. package/dist-cjs/api/datasources/datasources.js +166 -0
  128. package/dist-cjs/api/datasources/datasources.types.js +2 -0
  129. package/dist-cjs/api/plugins/plugins.js +132 -0
  130. package/dist-cjs/api/plugins/plugins.types.js +2 -0
  131. package/dist-cjs/api/presets/componentPresets.js +25 -0
  132. package/dist-cjs/api/presets/presets.js +92 -0
  133. package/dist-cjs/api/presets/presets.types.js +2 -0
  134. package/dist-cjs/api/presets/resolvePresets.js +49 -0
  135. package/dist-cjs/api/roles/roles.js +131 -0
  136. package/dist-cjs/api/roles/roles.types.js +2 -0
  137. package/dist-cjs/api/spaces/spaces.js +34 -0
  138. package/dist-cjs/api/spaces/spaces.types.js +2 -0
  139. package/dist-cjs/api/stories/stories.js +214 -0
  140. package/dist-cjs/api/stories/stories.types.js +2 -0
  141. package/dist-cjs/api/sync/sync.types.js +2 -0
  142. package/dist-cjs/api/utils/request.js +48 -0
  143. package/dist-cjs/api/utils/resolvers.types.js +2 -0
  144. package/dist-cjs/api-v2/assets/index.js +30 -0
  145. package/dist-cjs/api-v2/auth/index.js +12 -0
  146. package/dist-cjs/api-v2/client.js +23 -0
  147. package/dist-cjs/api-v2/components/index.js +40 -0
  148. package/dist-cjs/api-v2/datasources/index.js +64 -0
  149. package/dist-cjs/api-v2/discover/discover.js +368 -0
  150. package/dist-cjs/api-v2/discover/index.js +9 -0
  151. package/dist-cjs/api-v2/index.js +60 -0
  152. package/dist-cjs/api-v2/plugins/index.js +49 -0
  153. package/dist-cjs/api-v2/precompile/index.js +7 -0
  154. package/dist-cjs/api-v2/precompile/precompile.js +136 -0
  155. package/dist-cjs/api-v2/presets/index.js +33 -0
  156. package/dist-cjs/api-v2/requestConfig.js +37 -0
  157. package/dist-cjs/api-v2/roles/index.js +41 -0
  158. package/dist-cjs/api-v2/spaces/index.js +16 -0
  159. package/dist-cjs/api-v2/stories/index.js +180 -0
  160. package/dist-cjs/api-v2/stories/types.js +2 -0
  161. package/dist-cjs/api-v2/sync/index.js +115 -0
  162. package/dist-cjs/api-v2/sync/types.js +2 -0
  163. package/dist-cjs/api-v2/test.js +25 -0
  164. package/dist-cjs/config/config.types.js +2 -0
  165. package/dist-cjs/config/constants.js +29 -0
  166. package/dist-cjs/package.json +3 -0
  167. package/dist-cjs/utils/array-utils.js +24 -0
  168. package/dist-cjs/utils/logger.js +32 -0
  169. package/dist-cjs/utils/object-utils.js +77 -0
  170. package/dist-cjs/utils/path-utils.js +115 -0
  171. package/package.json +43 -27
  172. package/dist/utils/pkg-require.d.ts +0 -2
  173. package/dist/utils/pkg-require.js +0 -4
package/README.md CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  <p align="center">
3
2
  <img width="250" height="250" src="./sb-mig-logo.png" alt="Logo" />
4
3
  </p>
@@ -10,17 +9,16 @@ If you've found an issue or you have feature request - <a href="https://github.c
10
9
  [![GitHub issues](https://img.shields.io/github/issues/sb-mig/sb-mig.svg?style=flat-square&v=1)](https://github.com/sb-mig/sb-mig/issues?q=is%3Aopen+is%3Aissue)
11
10
  ![npm](https://img.shields.io/npms-io/maintenance-score/sb-mig)
12
11
 
13
-
14
-
15
12
  # Requirements:
16
13
 
17
- | | |
18
- | ------------- | ------------- |
19
- | Node | LTS (18.x.x) |
14
+ | | |
15
+ | ---- | ------------ |
16
+ | Node | LTS (18.x.x) |
20
17
 
21
18
  # 5.x.x version released!
22
19
 
23
20
  ## Important Updates
21
+
24
22
  - Complete codebase overhaul to facilitate the utilization of features and requests to Storyblok. This development decreases the tight coupling with CLI, while improving folder and file structure.
25
23
  - New feature: Content synchronization (including stories and assets) in various directions, ranging from space to space, from space to file, and from file to space.
26
24
  - New feature: Introduced support for TypeScript Schema, with the added ability to precompile them on-the-fly before synchronization, improving usage with sb-mig.
@@ -33,12 +31,12 @@ If you've found an issue or you have feature request - <a href="https://github.c
33
31
  - Expanded test coverage (with more additions anticipated).
34
32
 
35
33
  ## Breaking changes
34
+
36
35
  - Please note that sb-mig no longer extends support for Node versions older than 18.x.x, as part of its adoption of native ESM support.
37
36
  - The sb-mig backup command has now been aligned with all other commands, causing minor changes in its execution (although functionalities have been preserved).
38
37
 
39
38
  Do not hesitate to get in touch if you encounter any issues or require further clarification on any points.
40
39
 
41
-
42
40
  # 4.x.x version released!
43
41
 
44
42
  - Whole deployment now, is handled by [semantic-release](https://github.com/semantic-release/semantic-release). And is just normal repository, instead of Lerna monorepo which is not needed anymore, and it was recently unmaintained (now it was passed to `nrwl` to maintain (https://github.com/lerna/lerna/issues/3121) will see what will happen in future with it :)
@@ -57,10 +55,10 @@ Do not hesitate to get in touch if you encounter any issues or require further c
57
55
 
58
56
  - [How to install and configure](#how-to-install-and-configure)
59
57
  - [Schema documentation:](#schema-documentation)
60
- - [Basics](#basics)
61
- - [Syncing components](#syncing-components)
62
- - [Syncing datasources](#syncing-datasources)
63
- - [Presets support](#presets-support)
58
+ - [Basics](#basics)
59
+ - [Syncing components](#syncing-components)
60
+ - [Syncing datasources](#syncing-datasources)
61
+ - [Presets support](#presets-support)
64
62
  - [Development](#development)
65
63
  - [Roadmap](#roadmap)
66
64
 
@@ -189,7 +187,6 @@ sb-mig sync components row column
189
187
 
190
188
  This command will look for `row.sb.js` and `column.sb.js` files inside a directories mentioned in `componentDirectories` field. (You can change directories name mapping by modifying `componentDirectories` inside `storyblok.config.js`). You can also change the extension searched by changing `schemaFileExt`. [How to install and configure](#how-to-install-and-configure))
191
189
 
192
-
193
190
  ## Syncing datasources
194
191
 
195
192
  You can also sync your `datasources`.
@@ -269,7 +266,6 @@ You can also sync all datasources, and that's the command we strongly recommend.
269
266
  sb-mig sync datasources --all
270
267
  ```
271
268
 
272
-
273
269
  ## Presets support
274
270
 
275
271
  Writing your own predefined data (presets) for components can be a pain, so with `sb-mig` you can create presets for your components in the storyblok gui, and then export them to a schema based `.sb.js` file to be picked up while syncing.
@@ -342,36 +338,41 @@ git clone git@github.com:sb-mig/sb-mig.git
342
338
  Install packages
343
339
 
344
340
  ```
345
- yarn
341
+ npm install
346
342
  ```
347
343
 
348
344
  Run development command
345
+
349
346
  ```bash
350
- yarn build:dev
347
+ npm run build:dev
351
348
  ```
352
349
 
353
350
  It will watch a file change, and on every change, will rebuild typescript and build the whole lib/cli.
354
351
 
355
- The you can use
352
+ The you can use
353
+
356
354
  ```
357
- node dist/index.js debug
355
+ node dist/index.js debug
358
356
  ```
357
+
359
358
  to access `sb-mig`
360
359
 
361
360
  For your conveniece, you can also, link it to proper `sb-mi` name:
361
+
362
362
  ```
363
- yarn link
363
+ npm link
364
364
  ```
365
365
 
366
366
  And then you can use it like that:
367
+
367
368
  ```
368
369
  sb-mig debug
369
370
  ```
370
371
 
371
-
372
372
  # Releasing
373
373
 
374
374
  ## Flow of branching out and merging
375
+
375
376
  - Before creating feature branch from beta, make sure you have newest beta. (by `git pull origin beta`).
376
377
  - Create feature branch from beta
377
378
  - Do your changes
@@ -4,6 +4,7 @@ import path from "path";
4
4
  import FormData from "form-data";
5
5
  import { createDir, isDirectoryExists } from "../../utils/files.js";
6
6
  import Logger from "../../utils/logger.js";
7
+ import { getFileName, getSizeFromURL } from "../../utils/string-utils.js";
7
8
  // GET
8
9
  export const getAllAssets = async (args, config) => {
9
10
  const { spaceId, search } = args;
@@ -37,7 +38,7 @@ export const getAssetByName = async ({ spaceId, fileName }, config) => {
37
38
  };
38
39
  const requestSignedUploadUrl = ({ spaceId, payload }, config) => {
39
40
  const { sbApi, debug } = config;
40
- const { filename: _1, asset_folder_id, ext_id, space_id, ...restPayload } = payload;
41
+ const { filename: _1, asset_folder_id, ext_id, space_id, deleted_at: _2, ...restPayload } = payload;
41
42
  const filename = getFileName(payload.filename);
42
43
  const size = getSizeFromURL(payload.filename);
43
44
  return sbApi
@@ -77,20 +78,6 @@ const uploadFile = ({ signedResponseObject, pathToFile }) => {
77
78
  }
78
79
  });
79
80
  };
80
- const getFileName = (fileUrl) => {
81
- const fileName = fileUrl.split("/").pop();
82
- if (fileName) {
83
- return fileName;
84
- }
85
- else {
86
- throw Error("File name couldn't be extracted from URL.");
87
- }
88
- };
89
- const getSizeFromURL = (fileUrl) => {
90
- const data = fileUrl.split("/");
91
- const sizePos = data.length - 3;
92
- return data[sizePos];
93
- };
94
81
  const downloadAsset = async (args, config) => {
95
82
  const { debug, sbmigWorkingDirectory } = config;
96
83
  const { payload } = args;
@@ -1,5 +1,5 @@
1
1
  import type { RequestBaseConfig } from "../utils/request.js";
2
- import type { ISbResult } from "storyblok-js-client/src/interfaces";
2
+ import type { ISbResult } from "storyblok-js-client";
3
3
  export interface Org {
4
4
  }
5
5
  export interface CurrentUserResult extends ISbResult {
@@ -55,7 +55,7 @@ export const createComponent = (component, presets, config) => {
55
55
  Logger.log(`Trying to create '${component.name}'`);
56
56
  const componentWithPresets = component;
57
57
  const { all_presets, ...componentWithoutPresets } = componentWithPresets;
58
- sbApi
58
+ return sbApi
59
59
  .post(`spaces/${spaceId}/components/`, {
60
60
  component: componentWithoutPresets,
61
61
  })
@@ -67,6 +67,7 @@ export const createComponent = (component, presets, config) => {
67
67
  })
68
68
  .catch((err) => {
69
69
  Logger.error(`${err.message} in migration of ${component.name} in createComponent function`);
70
+ throw err;
70
71
  });
71
72
  };
72
73
  /*
@@ -0,0 +1,8 @@
1
+ import type { SyncProgressCallback, SyncResult } from "../sync/sync.types.js";
2
+ import type { RequestBaseConfig } from "../utils/request.js";
3
+ export declare function syncComponentsData(args: {
4
+ components: any[];
5
+ presets: boolean;
6
+ ssot?: boolean;
7
+ onProgress?: SyncProgressCallback;
8
+ }, config: RequestBaseConfig): Promise<SyncResult>;
@@ -0,0 +1,193 @@
1
+ import { uniqueValuesFrom } from "../../utils/array-utils.js";
2
+ import Logger from "../../utils/logger.js";
3
+ import { isObjectEmpty } from "../../utils/object-utils.js";
4
+ /**
5
+ * Default progress callback that logs to console
6
+ */
7
+ const defaultProgress = (event) => {
8
+ if (event.type === "start") {
9
+ Logger.log(`Starting sync of ${event.total} components...`);
10
+ }
11
+ else if (event.type === "progress" && event.name) {
12
+ const status = event.action === "creating"
13
+ ? "Creating"
14
+ : event.action === "updating"
15
+ ? "Updating"
16
+ : event.action === "created"
17
+ ? "✓ Created"
18
+ : event.action === "updated"
19
+ ? "✓ Updated"
20
+ : event.action === "skipped"
21
+ ? "⏭ Skipped"
22
+ : "✘ Error";
23
+ Logger.log(`[${event.current}/${event.total}] ${status}: ${event.name}`);
24
+ }
25
+ else if (event.type === "complete") {
26
+ Logger.success(`Sync complete: ${event.message ?? "done"}`);
27
+ }
28
+ };
29
+ import { createComponent, createComponentsGroup, getAllComponents, getAllComponentsGroups, removeComponent, removeComponentGroup, updateComponent, } from "./components.js";
30
+ async function ensureComponentGroupsExist(groupNames, config) {
31
+ try {
32
+ const existing = await getAllComponentsGroups(config);
33
+ const existingNames = new Set((existing ?? []).map((g) => g.name));
34
+ for (const groupName of groupNames) {
35
+ if (!existingNames.has(groupName)) {
36
+ await createComponentsGroup(groupName, config);
37
+ }
38
+ }
39
+ }
40
+ catch (error) {
41
+ // Log but don't fail - component groups are optional
42
+ Logger.warning(`Could not fetch component groups: ${error instanceof Error ? error.message : String(error)}`);
43
+ }
44
+ }
45
+ function resolveGroupUuid(component, remoteGroups) {
46
+ if (!component.component_group_name) {
47
+ return { ...component, component_group_uuid: null };
48
+ }
49
+ const match = remoteGroups.find((g) => g.name === component.component_group_name);
50
+ if (!match)
51
+ return { ...component, component_group_uuid: null };
52
+ return { ...component, component_group_uuid: match.uuid };
53
+ }
54
+ export async function syncComponentsData(args, config) {
55
+ const { components, presets, ssot, onProgress } = args;
56
+ const progress = onProgress ?? defaultProgress;
57
+ const result = {
58
+ created: [],
59
+ updated: [],
60
+ skipped: [],
61
+ errors: [],
62
+ };
63
+ if (ssot) {
64
+ const existingComponents = await getAllComponents(config);
65
+ const existingGroups = await getAllComponentsGroups(config);
66
+ await Promise.allSettled([
67
+ ...(existingComponents ?? []).map((c) => removeComponent(c, config)),
68
+ ...(existingGroups ?? []).map((g) => removeComponentGroup(g, config)),
69
+ ]);
70
+ }
71
+ const nonEmptyComponents = components.filter((c) => !isObjectEmpty(c));
72
+ const groupsToCheck = uniqueValuesFrom(nonEmptyComponents
73
+ .filter((c) => c.component_group_name)
74
+ .map((c) => c.component_group_name));
75
+ await ensureComponentGroupsExist(groupsToCheck, config);
76
+ let remoteComponents = [];
77
+ let remoteGroups = [];
78
+ try {
79
+ remoteComponents = (await getAllComponents(config)) ?? [];
80
+ }
81
+ catch (error) {
82
+ Logger.warning(`Could not fetch remote components: ${error instanceof Error ? error.message : String(error)}`);
83
+ }
84
+ try {
85
+ remoteGroups = (await getAllComponentsGroups(config)) ?? [];
86
+ }
87
+ catch (error) {
88
+ Logger.warning(`Could not fetch remote groups: ${error instanceof Error ? error.message : String(error)}`);
89
+ }
90
+ const componentsToUpdate = [];
91
+ const componentsToCreate = [];
92
+ for (const component of nonEmptyComponents) {
93
+ if (!component?.name) {
94
+ result.skipped.push("unknown");
95
+ continue;
96
+ }
97
+ const remote = remoteComponents.find((rc) => rc.name === component.name);
98
+ if (remote) {
99
+ componentsToUpdate.push({ id: remote.id, ...component });
100
+ }
101
+ else {
102
+ componentsToCreate.push(component);
103
+ }
104
+ }
105
+ // Resolve group uuids after ensureComponentGroupsExist
106
+ const updatePayloads = componentsToUpdate.map((c) => resolveGroupUuid(c, remoteGroups));
107
+ const createPayloads = componentsToCreate.map((c) => resolveGroupUuid(c, remoteGroups));
108
+ const totalComponents = updatePayloads.length + createPayloads.length;
109
+ let currentIndex = 0;
110
+ // Report start
111
+ progress({ type: "start", total: totalComponents });
112
+ // Process updates sequentially for progress reporting
113
+ for (const component of updatePayloads) {
114
+ const name = String(component?.name ?? "unknown");
115
+ currentIndex++;
116
+ progress({
117
+ type: "progress",
118
+ current: currentIndex,
119
+ total: totalComponents,
120
+ name,
121
+ action: "updating",
122
+ });
123
+ try {
124
+ await updateComponent(component, presets, config);
125
+ result.updated.push(name);
126
+ progress({
127
+ type: "progress",
128
+ current: currentIndex,
129
+ total: totalComponents,
130
+ name,
131
+ action: "updated",
132
+ });
133
+ }
134
+ catch (error) {
135
+ result.errors.push({
136
+ name,
137
+ message: error instanceof Error ? error.message : String(error),
138
+ });
139
+ progress({
140
+ type: "progress",
141
+ current: currentIndex,
142
+ total: totalComponents,
143
+ name,
144
+ action: "error",
145
+ message: error instanceof Error ? error.message : String(error),
146
+ });
147
+ }
148
+ }
149
+ // Process creates sequentially for progress reporting
150
+ for (const component of createPayloads) {
151
+ const name = String(component?.name ?? "unknown");
152
+ currentIndex++;
153
+ progress({
154
+ type: "progress",
155
+ current: currentIndex,
156
+ total: totalComponents,
157
+ name,
158
+ action: "creating",
159
+ });
160
+ try {
161
+ await createComponent(component, presets, config);
162
+ result.created.push(name);
163
+ progress({
164
+ type: "progress",
165
+ current: currentIndex,
166
+ total: totalComponents,
167
+ name,
168
+ action: "created",
169
+ });
170
+ }
171
+ catch (error) {
172
+ result.errors.push({
173
+ name,
174
+ message: error instanceof Error ? error.message : String(error),
175
+ });
176
+ progress({
177
+ type: "progress",
178
+ current: currentIndex,
179
+ total: totalComponents,
180
+ name,
181
+ action: "error",
182
+ message: error instanceof Error ? error.message : String(error),
183
+ });
184
+ }
185
+ }
186
+ // Report completion
187
+ progress({
188
+ type: "complete",
189
+ total: totalComponents,
190
+ message: `${result.created.length} created, ${result.updated.length} updated, ${result.errors.length} errors`,
191
+ });
192
+ return result;
193
+ }
@@ -2,10 +2,10 @@ import path from "path";
2
2
  import chalk from "chalk";
3
3
  import { discoverMigrationConfig, discoverStories, LOOKUP_TYPE, SCOPE, } from "../../cli/utils/discover.js";
4
4
  import storyblokConfig from "../../config/config.js";
5
- import { createAndSaveToFile } from "../../utils/files.js";
5
+ import { createAndSaveToFile, getFilesContentWithRequire, } from "../../utils/files.js";
6
6
  import Logger from "../../utils/logger.js";
7
- import { getFilesContentWithRequire, isObjectEmpty } from "../../utils/main.js";
8
7
  import { modifyOrCreateAppliedMigrationsFile } from "../../utils/migrations.js";
8
+ import { isObjectEmpty } from "../../utils/object-utils.js";
9
9
  import { managementApi } from "../managementApi.js";
10
10
  function replaceComponentData({ parent, key, components, mapper, depth, maxDepth, sumOfReplacing, }) {
11
11
  let currentMaxDepth = depth;
@@ -1,7 +1,6 @@
1
1
  import chalk from "chalk";
2
- import storyblokConfig from "../../config/config.js";
3
2
  import Logger from "../../utils/logger.js";
4
- import { isObjectEmpty } from "../../utils/main.js";
3
+ import { isObjectEmpty } from "../../utils/object-utils.js";
5
4
  import { getDatasource } from "./datasources.js";
6
5
  const _decorateWithDimensions = async (args, config) => {
7
6
  const { currentDatasource, dimensionsData, _callback } = args;
@@ -67,7 +66,7 @@ export const createDatasourceEntries = (args, config) => {
67
66
  const _createDatasourceEntry = (args, config) => {
68
67
  const { currentDatasource, finalDatasource_entry } = args;
69
68
  const { spaceId, sbApi } = config;
70
- if (storyblokConfig.debug) {
69
+ if (config.debug) {
71
70
  console.log("############# Entity to Create: ");
72
71
  console.log(finalDatasource_entry);
73
72
  console.log("################################");
@@ -81,7 +80,7 @@ const _createDatasourceEntry = (args, config) => {
81
80
  return data;
82
81
  })
83
82
  .catch((err) => {
84
- if (storyblokConfig.debug) {
83
+ if (config.debug) {
85
84
  console.log("Full Create error: ");
86
85
  console.log(err);
87
86
  }
@@ -122,7 +121,7 @@ const _updateDatasourceEntry = (args, config) => {
122
121
  return true;
123
122
  })
124
123
  .catch((err) => {
125
- if (storyblokConfig.debug) {
124
+ if (config.debug) {
126
125
  console.log("Full update error: ");
127
126
  console.log(err);
128
127
  }
@@ -1,6 +1,9 @@
1
- import type { CreateDatasource, GetAllDatasources, GetDatasource, SyncDatasources, UpdateDatasource } from "./datasources.types.js";
1
+ import type { CreateDatasource, GetAllDatasources, GetDatasource, UpdateDatasource } from "./datasources.types.js";
2
+ import type { SyncResult } from "../sync/sync.types.js";
2
3
  export declare const getAllDatasources: GetAllDatasources;
3
4
  export declare const getDatasource: GetDatasource;
4
5
  export declare const createDatasource: CreateDatasource;
5
6
  export declare const updateDatasource: UpdateDatasource;
6
- export declare const syncDatasources: SyncDatasources;
7
+ export declare const syncDatasourcesData: ({ datasources }: {
8
+ datasources: any[];
9
+ }, config: any) => Promise<SyncResult>;
@@ -1,5 +1,4 @@
1
1
  import Logger from "../../utils/logger.js";
2
- import { getFileContentWithRequire, } from "../../utils/main.js";
3
2
  import { getAllItemsWithPagination } from "../utils/request.js";
4
3
  import { createDatasourceEntries, getDatasourceEntries, } from "./datasource-entries.js";
5
4
  // GET
@@ -110,39 +109,47 @@ export const updateDatasource = (args, config) => {
110
109
  })
111
110
  .catch((err) => Logger.error(err));
112
111
  };
113
- export const syncDatasources = async (args, config) => {
114
- const { providedDatasources } = args;
115
- Logger.log(`Trying to sync provided datasources: `);
116
- const providedDatasourcesContent = await Promise.all(providedDatasources.map((datasource) => {
117
- return getFileContentWithRequire({ file: datasource.p });
118
- }));
119
- const remoteDatasources = await getAllDatasources(config);
120
- Promise.all(providedDatasourcesContent.map((datasource) => {
121
- const datasourceToBeUpdated = remoteDatasources.find((remoteDatasource) => datasource.name === remoteDatasource.name);
122
- if (datasourceToBeUpdated) {
123
- return updateDatasource({ datasource: datasource, datasourceToBeUpdated }, config);
112
+ // File-based sync wrapper lives in `datasources.sync.ts` to keep this module CJS-safe.
113
+ export const syncDatasourcesData = async ({ datasources }, config) => {
114
+ const result = {
115
+ created: [],
116
+ updated: [],
117
+ skipped: [],
118
+ errors: [],
119
+ };
120
+ const remoteDatasourcesRaw = await getAllDatasources(config);
121
+ const remoteDatasources = Array.isArray(remoteDatasourcesRaw)
122
+ ? remoteDatasourcesRaw
123
+ : [];
124
+ for (const datasource of datasources) {
125
+ const name = String(datasource?.name ?? "unknown");
126
+ if (!datasource || typeof datasource !== "object" || !datasource.name) {
127
+ result.skipped.push(name);
128
+ continue;
124
129
  }
125
- return createDatasource({ datasource: datasource }, config);
126
- }))
127
- .then((res) => {
128
- // After create or after update datasource
129
- res.map(async ({ data, datasource_entries }) => {
130
- const remoteDatasourceEntries = await getDatasourceEntries({
131
- datasourceName: data.datasource.name,
132
- }, config);
133
- console.log(" ");
134
- Logger.warning(`Start async syncing of '${data.datasource.name}' datasource entries.`);
135
- createDatasourceEntries({
136
- data,
137
- datasource_entries,
138
- remoteDatasourceEntries,
139
- }, config);
140
- });
141
- return res;
142
- })
143
- .catch((err) => {
144
- console.log(err);
145
- Logger.warning("There is error inside promise.all from datasource");
146
- return false;
147
- });
130
+ try {
131
+ const datasourceToBeUpdated = remoteDatasources.find((remoteDatasource) => datasource.name === remoteDatasource.name);
132
+ const opResult = datasourceToBeUpdated
133
+ ? await updateDatasource({ datasource, datasourceToBeUpdated }, config)
134
+ : await createDatasource({ datasource }, config);
135
+ if (datasourceToBeUpdated)
136
+ result.updated.push(name);
137
+ else
138
+ result.created.push(name);
139
+ if (opResult?.data?.datasource && opResult?.datasource_entries) {
140
+ const remoteDatasourceEntries = await getDatasourceEntries({
141
+ datasourceName: opResult.data.datasource.name,
142
+ }, config);
143
+ await createDatasourceEntries({
144
+ data: opResult.data,
145
+ datasource_entries: opResult.datasource_entries,
146
+ remoteDatasourceEntries,
147
+ }, config);
148
+ }
149
+ }
150
+ catch (e) {
151
+ result.errors.push({ name, message: String(e) });
152
+ }
153
+ }
154
+ return result;
148
155
  };
@@ -0,0 +1,2 @@
1
+ import type { SyncDatasources } from "./datasources.types.js";
2
+ export declare const syncDatasources: SyncDatasources;
@@ -0,0 +1,11 @@
1
+ import { getFileContentWithRequire } from "../../utils/files.js";
2
+ import Logger from "../../utils/logger.js";
3
+ import { syncDatasourcesData } from "./datasources.js";
4
+ export const syncDatasources = async (args, config) => {
5
+ const { providedDatasources } = args;
6
+ Logger.log(`Trying to sync provided datasources: `);
7
+ const providedDatasourcesContent = await Promise.all(providedDatasources.map((datasource) => {
8
+ return getFileContentWithRequire({ file: datasource.p });
9
+ }));
10
+ await syncDatasourcesData({ datasources: providedDatasourcesContent }, config);
11
+ };
@@ -1,4 +1,4 @@
1
- import type { OneFileElement } from "../../cli/utils/discover.js";
1
+ import type { OneFileElement } from "../../utils/path-utils.js";
2
2
  import type { RequestBaseConfig } from "../utils/request.js";
3
3
  export type GetAllDatasources = (config: RequestBaseConfig) => Promise<any>;
4
4
  export type GetDatasource = (args: {
@@ -1 +1,2 @@
1
- export { createDatasource, getDatasource, getAllDatasources, syncDatasources, updateDatasource, } from "./datasources.js";
1
+ export { createDatasource, getDatasource, getAllDatasources, updateDatasource, } from "./datasources.js";
2
+ export { syncDatasources } from "./datasources.sync.js";
@@ -1 +1,2 @@
1
- export { createDatasource, getDatasource, getAllDatasources, syncDatasources, updateDatasource, } from "./datasources.js";
1
+ export { createDatasource, getDatasource, getAllDatasources, updateDatasource, } from "./datasources.js";
2
+ export { syncDatasources } from "./datasources.sync.js";
@@ -25,8 +25,8 @@ export declare const managementApi: {
25
25
  createDatasource: import("./datasources/datasources.types.js").CreateDatasource;
26
26
  getDatasource: import("./datasources/datasources.types.js").GetDatasource;
27
27
  getAllDatasources: import("./datasources/datasources.types.js").GetAllDatasources;
28
- syncDatasources: import("./datasources/datasources.types.js").SyncDatasources;
29
28
  updateDatasource: import("./datasources/datasources.types.js").UpdateDatasource;
29
+ syncDatasources: import("./datasources/datasources.types.js").SyncDatasources;
30
30
  };
31
31
  plugins: {
32
32
  getAllPlugins: import("./plugins/plugins.types.js").GetAllPlugins;
@@ -48,8 +48,8 @@ export declare const managementApi: {
48
48
  createRole: import("./roles/roles.types.js").CreateRole;
49
49
  getRole: import("./roles/roles.types.js").GetRole;
50
50
  getAllRoles: import("./roles/roles.types.js").GetAllRoles;
51
- syncRoles: import("./roles/roles.types.js").SyncRoles;
52
51
  updateRole: import("./roles/roles.types.js").UpdateRole;
52
+ syncRoles: import("./roles/roles.types.js").SyncRoles;
53
53
  };
54
54
  stories: {
55
55
  createStory: import("./stories/stories.types.js").CreateStory;
@@ -10,6 +10,6 @@ export declare const syncAssets: SyncAssets;
10
10
  export declare const syncContent: SyncContentFunction;
11
11
  export declare const setComponentDefaultPreset: ({ presets, componentsToSync, apiConfig, }: {
12
12
  presets: boolean;
13
- componentsToSync?: string[] | undefined;
13
+ componentsToSync?: string[];
14
14
  apiConfig: RequestBaseConfig;
15
15
  }) => Promise<false | any[]>;