sb-mig 5.0.8-beta.2 → 5.0.8-beta.4

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.
@@ -239,7 +239,7 @@ export const migrateProvidedComponentsDataInStories = async ({ itemType, migrati
239
239
  // Get all stories to be migrated from storyblok space
240
240
  let itemsToMigrate = [];
241
241
  if (itemType === "story") {
242
- itemsToMigrate = await managementApi.stories.getAllStories({
242
+ itemsToMigrate = await managementApi.stories.getAllStories({}, {
243
243
  ...config,
244
244
  spaceId: from,
245
245
  });
@@ -60,6 +60,7 @@ export declare const managementApi: {
60
60
  updateStories: import("./stories/stories.types.js").UpdateStories;
61
61
  getAllStories: import("./stories/stories.types.js").GetAllStories;
62
62
  removeAllStories: import("./stories/stories.types.js").RemoveAllStories;
63
+ upsertStory: import("./stories/stories.types.js").UpsertStory;
63
64
  backupStories: import("./stories/stories.types.js").BackupStories;
64
65
  };
65
66
  spaces: {
@@ -207,7 +207,7 @@ export const syncContent = async ({ type, transmission, syncDirection, filename
207
207
  }, config);
208
208
  }
209
209
  if (syncDirection === "fromSpaceToSpace") {
210
- const stories = await getAllStories({
210
+ const stories = await getAllStories({}, {
211
211
  ...config,
212
212
  spaceId: transmission.from,
213
213
  sbApi: config.sbApi,
@@ -14,10 +14,10 @@ export interface Space {
14
14
  created_at: string;
15
15
  }
16
16
  export type GetSpace = (args: {
17
- spaceId: number;
17
+ spaceId: string;
18
18
  }, config: RequestBaseConfig) => Promise<any>;
19
19
  export type GetAllSpaces = (config: RequestBaseConfig) => Promise<Space[]>;
20
20
  export type UpdateSpace = (args: {
21
- spaceId: number;
21
+ spaceId: string;
22
22
  params: any;
23
23
  }, config: RequestBaseConfig) => Promise<any>;
@@ -3,7 +3,7 @@ import Logger from "../../utils/logger.js";
3
3
  import { getAllStories } from "./stories.js";
4
4
  export const backupStories = async ({ suffix, spaceId, filename }, config) => {
5
5
  Logger.log(`Making backup of your stories.`);
6
- await getAllStories({ ...config, spaceId })
6
+ await getAllStories({}, { ...config, spaceId })
7
7
  .then(async (res) => {
8
8
  await createAndSaveToFile({
9
9
  ext: "json",
@@ -1,2 +1,2 @@
1
- export { createStory, updateStory, getStoryById, removeStory, getStoryBySlug, updateStories, getAllStories, removeAllStories, } from "./stories.js";
1
+ export { createStory, updateStory, getStoryById, removeStory, getStoryBySlug, updateStories, getAllStories, removeAllStories, upsertStory, } from "./stories.js";
2
2
  export { backupStories } from "./backup.js";
@@ -1,2 +1,2 @@
1
- export { createStory, updateStory, getStoryById, removeStory, getStoryBySlug, updateStories, getAllStories, removeAllStories, } from "./stories.js";
1
+ export { createStory, updateStory, getStoryById, removeStory, getStoryBySlug, updateStories, getAllStories, removeAllStories, upsertStory, } from "./stories.js";
2
2
  export { backupStories } from "./backup.js";
@@ -1,5 +1,4 @@
1
- import type { GetAllStories, GetStoryById, RemoveStory, CreateStory, UpdateStory, UpdateStories, RemoveAllStories } from "./stories.types.js";
2
- import type { GetStoryBySlug } from "./stories.types.js";
1
+ import type { GetAllStories, GetStoryById, RemoveStory, CreateStory, UpdateStory, UpdateStories, RemoveAllStories, UpsertStory, DeepUpsertStory, GetStoryBySlug } from "./stories.types.js";
3
2
  export declare const removeStory: RemoveStory;
4
3
  export declare const removeAllStories: RemoveAllStories;
5
4
  export declare const getAllStories: GetAllStories;
@@ -8,3 +7,5 @@ export declare const getStoryBySlug: GetStoryBySlug;
8
7
  export declare const createStory: CreateStory;
9
8
  export declare const updateStory: UpdateStory;
10
9
  export declare const updateStories: UpdateStories;
10
+ export declare const upsertStory: UpsertStory;
11
+ export declare const deepUpsertStory: DeepUpsertStory;
@@ -1,6 +1,15 @@
1
1
  import chalk from "chalk";
2
2
  import Logger from "../../utils/logger.js";
3
+ import { managementApi } from "../managementApi.js";
3
4
  import { getAllItemsWithPagination } from "../utils/request.js";
5
+ const notNullish = (params) => {
6
+ return Object.keys(params).reduce((acc, key) => {
7
+ if (params[key] !== null && params[key] !== undefined) {
8
+ acc[key] = params[key];
9
+ }
10
+ return acc;
11
+ }, {});
12
+ };
4
13
  export const removeStory = (args, config) => {
5
14
  const { storyId } = args;
6
15
  const { spaceId, sbApi } = config;
@@ -18,7 +27,7 @@ export const removeStory = (args, config) => {
18
27
  export const removeAllStories = async (config) => {
19
28
  const { spaceId } = config;
20
29
  Logger.warning(`Trying to remove all stories from space with spaceId: ${spaceId}`);
21
- const stories = await getAllStories(config);
30
+ const stories = await getAllStories({}, config);
22
31
  const onlyRootStories = (story) => story.story.parent_id === 0 || story.story.parent_id === null;
23
32
  const allResponses = Promise.all(stories
24
33
  .filter(onlyRootStories)
@@ -26,11 +35,20 @@ export const removeAllStories = async (config) => {
26
35
  return allResponses;
27
36
  };
28
37
  // GET
29
- export const getAllStories = async (config) => {
38
+ export const getAllStories = async (args, config) => {
39
+ const { options } = args;
30
40
  const { spaceId, sbApi } = config;
31
41
  Logger.log(`Trying to get all Stories from: ${spaceId}`);
42
+ const params = notNullish({
43
+ with_slug: options?.with_slug,
44
+ starts_with: options?.starts_with,
45
+ language: options?.language,
46
+ });
47
+ console.log("These are params i will use: ");
48
+ console.log(params);
32
49
  const allStoriesWithoutContent = await getAllItemsWithPagination({
33
50
  apiFn: ({ per_page, page }) => sbApi.get(`spaces/${spaceId}/stories/`, {
51
+ ...params,
34
52
  per_page,
35
53
  page,
36
54
  }),
@@ -98,10 +116,13 @@ export const updateStory = (content, storyId, options, config) => {
98
116
  const { spaceId, sbApi } = config;
99
117
  Logger.warning("Trying to update Story...");
100
118
  Logger.log(`Updating story with name: ${content.name} in space: ${spaceId}`);
119
+ console.log("THis is content to update: ");
120
+ console.log(JSON.stringify(content, null, 2));
101
121
  return sbApi
102
122
  .put(`spaces/${spaceId}/stories/${storyId}`, {
103
123
  story: content,
104
124
  publish: options.publish ? 1 : 0,
125
+ force_update: options.force_update ? 1 : 0,
105
126
  })
106
127
  .then((res) => {
107
128
  console.log(`${chalk.green(res.data.story.full_slug)} updated.`);
@@ -117,3 +138,69 @@ export const updateStories = (args, config) => {
117
138
  return updateStory(stories.story, stories.story.id, { publish: options.publish }, { ...config, spaceId });
118
139
  }));
119
140
  };
141
+ export const upsertStory = async (args, config) => {
142
+ console.log("Modifying story... in space with id:");
143
+ console.log(config.spaceId);
144
+ const { storyId, storySlug, content } = args;
145
+ console.log("This are args passed: ");
146
+ console.log(args);
147
+ if (storyId) {
148
+ // if this exist than we update story with this id
149
+ console.log("You've selected storyid!");
150
+ }
151
+ else if (storySlug) {
152
+ // if this exist than we update story with this slug (probably when we try to add story from one space to another,
153
+ console.log("You've selected slug!");
154
+ const foundStory = await managementApi.stories.getStoryBySlug(storySlug, config);
155
+ console.log("This is story");
156
+ console.log(foundStory);
157
+ if (foundStory) {
158
+ // then update the story
159
+ }
160
+ else {
161
+ const { story: { parent_id, id, parent, ...rest }, } = content;
162
+ console.log("We are going to create story");
163
+ const response = await managementApi.stories.createStory(rest, config);
164
+ console.log("This is response");
165
+ console.log(response);
166
+ }
167
+ }
168
+ else {
169
+ // if this exist than we create new story
170
+ console.log("Nothing passed, creating story...");
171
+ }
172
+ };
173
+ export const deepUpsertStory = async (args, config) => {
174
+ console.log("Modifying story... in space with id:");
175
+ console.log(config.spaceId);
176
+ const { storyId, storySlug, content } = args;
177
+ console.log("This are args passed: ");
178
+ console.log(args);
179
+ if (storyId) {
180
+ // if this exist than we update story with this id
181
+ console.log("You've selected storyid!");
182
+ }
183
+ else if (storySlug) {
184
+ // if this exist than we update story with this slug (probably when we try to add story from one space to another,
185
+ console.log("You've selected slug!");
186
+ const slugs = storySlug.split("/");
187
+ console.log("Slugs for which we need to check for existence of stories");
188
+ console.log(slugs);
189
+ // const foundStory = await managementApi.stories.getStoryBySlug(storySlug, config)
190
+ // console.log("This is story")
191
+ // console.log(foundStory)
192
+ // if(foundStory) {
193
+ // // then update the story
194
+ // } else {
195
+ // const {story: {parent_id, id, parent,...rest}} = content
196
+ // console.log("We are going to create story")
197
+ // const response = await managementApi.stories.createStory(rest, config)
198
+ // console.log("This is response")
199
+ // console.log(response)
200
+ // }
201
+ }
202
+ else {
203
+ // if this exist than we create new story
204
+ console.log("Nothing passed, creating story...");
205
+ }
206
+ };
@@ -1,24 +1,41 @@
1
1
  import type { RequestBaseConfig } from "../utils/request.js";
2
+ import type { ISbStoriesParams } from "storyblok-js-client";
3
+ export interface ExtendedISbStoriesParams extends ISbStoriesParams {
4
+ with_slug?: string;
5
+ }
6
+ interface ModifyStoryOptions {
7
+ publish?: boolean;
8
+ force_update?: boolean;
9
+ }
2
10
  export type RemoveStory = (args: {
3
11
  storyId: string;
4
12
  }, config: RequestBaseConfig) => Promise<any>;
5
13
  export type RemoveAllStories = (config: RequestBaseConfig) => Promise<any>;
6
14
  export type GetStoryById = (storyId: string, config: RequestBaseConfig) => Promise<any>;
7
15
  export type GetStoryBySlug = (slug: string, config: RequestBaseConfig) => Promise<any>;
8
- export type GetAllStories = (config: RequestBaseConfig) => Promise<any>;
9
- export type CreateStory = (content: any, config: RequestBaseConfig) => Promise<any>;
10
- export type UpdateStory = (content: any, storyId: string, options: {
11
- publish?: boolean;
16
+ export type GetAllStories = (args: {
17
+ options?: ExtendedISbStoriesParams;
12
18
  }, config: RequestBaseConfig) => Promise<any>;
19
+ export type CreateStory = (content: any, config: RequestBaseConfig) => Promise<any>;
20
+ export type UpdateStory = (content: any, storyId: string, options: ModifyStoryOptions, config: RequestBaseConfig) => Promise<any>;
13
21
  export type UpdateStories = (args: {
14
22
  stories: any;
15
- options: {
16
- publish?: boolean;
17
- };
23
+ options: ModifyStoryOptions;
18
24
  spaceId: string;
19
25
  }, config: RequestBaseConfig) => Promise<any>;
26
+ export type UpsertStory = (args: {
27
+ content: any;
28
+ storyId?: string;
29
+ storySlug?: string;
30
+ }, config: RequestBaseConfig) => void;
31
+ export type DeepUpsertStory = (args: {
32
+ content: any;
33
+ storyId?: string;
34
+ storySlug?: string;
35
+ }, config: RequestBaseConfig) => void;
20
36
  export type BackupStories = (args: {
21
37
  filename: string;
22
38
  spaceId: string;
23
39
  suffix?: string;
24
40
  }, config: RequestBaseConfig) => void;
41
+ export {};
@@ -1,3 +1,3 @@
1
1
  import type { TraverseAndCreate, TreeNode } from "./tree.types.js";
2
- export declare const createTree: (stories: any[]) => TreeNode[];
2
+ export declare const createTree: (stories: any[], storiesToUpdate?: string[]) => TreeNode[];
3
3
  export declare const traverseAndCreate: TraverseAndCreate;
@@ -1,12 +1,17 @@
1
1
  import Logger from "../../utils/logger.js";
2
- import { createStory } from "./stories.js";
3
- export const createTree = (stories) => buildTree(stories, null);
4
- const buildTree = (nodes, parentId = null) => {
2
+ import { createStory, updateStory } from "./stories.js";
3
+ export const createTree = (stories, storiesToUpdate = []) => {
4
+ return buildTree(stories, null, storiesToUpdate);
5
+ };
6
+ const buildTree = (nodes, parentId = null, storiesToUpdate = []) => {
5
7
  const tree = [];
6
8
  nodes.forEach((node) => {
7
9
  if (node.parent_id === parentId) {
8
- const children = buildTree(nodes, node.id);
10
+ const children = buildTree(nodes, node.id, storiesToUpdate);
9
11
  tree.push({
12
+ action: storiesToUpdate.includes(node?.full_slug)
13
+ ? "update"
14
+ : "create",
10
15
  id: node.id,
11
16
  parent_id: node.parent_id,
12
17
  story: node,
@@ -20,9 +25,17 @@ export const traverseAndCreate = (input, config) => {
20
25
  const { tree, realParentId, spaceId } = input;
21
26
  tree.forEach(async (node) => {
22
27
  try {
23
- const { parent, ...content } = node.story;
24
- const result = await createStory({ ...content, parent_id: realParentId }, { ...config, spaceId });
25
- const storyId = result.story.id;
28
+ const { action, story } = node;
29
+ const { parent, ...content } = story;
30
+ let storyId = story.id;
31
+ if (action === "create") {
32
+ const result = await createStory({ ...content, parent_id: realParentId }, { ...config, spaceId });
33
+ storyId = result.story.id;
34
+ }
35
+ else if (action === "update") {
36
+ const result = await updateStory({ ...content, parent_id: realParentId }, `${storyId}`, { force_update: true }, { ...config, spaceId });
37
+ storyId = result.story.id;
38
+ }
26
39
  if (node.children) {
27
40
  traverseAndCreate({
28
41
  tree: node.children,
@@ -1,5 +1,6 @@
1
1
  import type { RequestBaseConfig } from "../utils/request.js";
2
2
  export interface TreeNode {
3
+ action: "update" | "create";
3
4
  id: number;
4
5
  parent_id: number | null;
5
6
  children?: TreeNode[];
@@ -60,6 +60,7 @@ export declare const testApi: {
60
60
  updateStories: import("./stories/stories.types.js").UpdateStories;
61
61
  getAllStories: import("./stories/stories.types.js").GetAllStories;
62
62
  removeAllStories: import("./stories/stories.types.js").RemoveAllStories;
63
+ upsertStory: import("./stories/stories.types.js").UpsertStory;
63
64
  backupStories: import("./stories/stories.types.js").BackupStories;
64
65
  };
65
66
  spaces: {
@@ -23,7 +23,9 @@ export const init = async (props) => {
23
23
  gtmToken,
24
24
  });
25
25
  const localSbApi = new StoryblokClient({ oauthToken }, storyblokApiUrl);
26
- const spaceData = await managementApi.spaces.getSpace(spaceId, apiConfig);
26
+ console.log("This is api config: ");
27
+ console.log({ ...apiConfig, oauthToken });
28
+ const spaceData = await managementApi.spaces.getSpace({ spaceId }, { ...apiConfig, sbApi: localSbApi });
27
29
  const STORYBLOK_SPACE_ID = spaceId;
28
30
  const STORYBLOK_OAUTH_TOKEN = oauthToken;
29
31
  const NEXT_PUBLIC_GTM_ID = gtmToken ?? "put-your-gtm-token-here";
@@ -51,7 +53,7 @@ export const init = async (props) => {
51
53
  params: {
52
54
  domain: `https://localhost:3000/api/preview/preview?secret=${STORYBLOK_PREVIEW_SECRET}&slug=`,
53
55
  },
54
- }, apiConfig);
56
+ }, { ...apiConfig, sbApi: localSbApi });
55
57
  Logger.success("Successfully updated space domain");
56
58
  }
57
59
  catch (e) {
@@ -0,0 +1,2 @@
1
+ import type { CLIOptions } from "../../utils/interfaces.js";
2
+ export declare const testCommand: (props: CLIOptions) => Promise<void>;
@@ -0,0 +1,26 @@
1
+ import { managementApi } from "../../api/managementApi.js";
2
+ import Logger from "../../utils/logger.js";
3
+ import { apiConfig } from "../api-config.js";
4
+ const INIT_COMMANDS = {
5
+ stories: "stories",
6
+ };
7
+ export const testCommand = async (props) => {
8
+ const { input, flags } = props;
9
+ const command = input[1];
10
+ switch (command) {
11
+ case INIT_COMMANDS.stories:
12
+ Logger.warning(`test sb-mig... with command: ${command}`);
13
+ console.log("This is api config");
14
+ console.log(apiConfig);
15
+ const allStories = await managementApi.stories.getAllStories({
16
+ options: {
17
+ language: "de-de",
18
+ },
19
+ }, apiConfig);
20
+ console.log("these are all stories");
21
+ console.log(JSON.stringify(allStories[0].story.content.body, null, 2));
22
+ break;
23
+ default:
24
+ console.log(`no command like that: ${command}`);
25
+ }
26
+ };
package/dist/cli/index.js CHANGED
@@ -11,6 +11,7 @@ import { migrations } from "./commands/migrations.js";
11
11
  import { remove } from "./commands/remove.js";
12
12
  import { revert } from "./commands/revert.js";
13
13
  import { sync } from "./commands/sync.js";
14
+ import { testCommand } from "./commands/test.js";
14
15
  const app = () => ({
15
16
  cli: meow(mainDescription, {
16
17
  importMeta: import.meta,
@@ -112,6 +113,15 @@ app.init = () => ({
112
113
  init(cli);
113
114
  },
114
115
  });
116
+ app.test = () => ({
117
+ cli: meow("nothing", {
118
+ importMeta: import.meta,
119
+ booleanDefault: undefined,
120
+ }),
121
+ action: (cli) => {
122
+ testCommand(cli);
123
+ },
124
+ });
115
125
  const getSubcommand = (cliObject, level) => pipe(prop("input"), prop(level), (name) => prop(name)(cliObject))(prop("cli")(cliObject()));
116
126
  const cli = (cliObject, level = 0) => {
117
127
  const { cli: nextCli, action } = cliObject();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sb-mig",
3
- "version": "5.0.8-beta.2",
3
+ "version": "5.0.8-beta.4",
4
4
  "description": "CLI to rule the world. (and handle stuff related to Storyblok CMS)",
5
5
  "author": "Marcin Krawczyk <marckraw@icloud.com>",
6
6
  "license": "MIT",