@slicemachine/init 1.1.9 → 1.1.10-alpha.11

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.
@@ -1,26 +1,24 @@
1
1
  import * as inquirer from "inquirer";
2
2
  import Separator from "inquirer/lib/objects/separator";
3
- import { Utils, Models, CONSTS } from "@slicemachine/core";
4
- import * as Prismic from "@slicemachine/core/build/prismic";
3
+ import { Models } from "@slicemachine/core";
5
4
  import * as NodeUtils from "@slicemachine/core/build/node-utils";
6
5
  import { createRepository } from "../utils/create-repo";
7
- import { logs } from "../utils";
6
+ import { validateRepositoryName } from "../utils/validateRepositoryName";
7
+ import { InitClient, logs } from "../utils";
8
8
 
9
9
  export const CREATE_REPO = "$_CREATE_REPO"; // not a valid domain name
10
- const DEFAULT_BASE = CONSTS.DEFAULT_BASE;
11
10
 
12
- export function prettyRepoName(address: URL, value?: string): string {
13
- const repoName = value ? logs.cyan(value) : logs.dim.cyan("repo-name");
14
- return `${logs.cyan.dim(`${address.protocol}//`)}${repoName}${logs.cyan.dim(
15
- `.${address.hostname}`
16
- )}`;
11
+ export function prettyRepoName(address: URL, domain: string): string {
12
+ return `${logs.cyan.dim(`${address.protocol}//`)}${logs.cyan(
13
+ domain
14
+ )}${logs.cyan.dim(`.${address.hostname}`)}`;
17
15
  }
18
16
 
19
17
  export async function promptForRepoDomain(
20
- base: string,
18
+ client: InitClient,
21
19
  defaultValue?: string
22
20
  ): Promise<string> {
23
- const address = new URL(base);
21
+ const address = new URL(client.apisEndpoints.Wroom);
24
22
 
25
23
  logs.writeInfo(
26
24
  "The name acts as a domain/endpoint for your content repo and should be completely unique."
@@ -34,16 +32,9 @@ export async function promptForRepoDomain(
34
32
  type: "input",
35
33
  required: true,
36
34
  default: defaultValue,
37
- transformer: (value: string) =>
38
- prettyRepoName(address, value || defaultValue),
39
- async validate(name: string) {
40
- const result = await Prismic.Communication.validateRepositoryName(
41
- name,
42
- base,
43
- false
44
- );
45
- return result === name || result;
46
- },
35
+ transformer: (value: string | undefined) =>
36
+ prettyRepoName(address, value || defaultValue || "repository"),
37
+ validate: (name: string) => validateRepositoryName(client, name),
47
38
  },
48
39
  ])
49
40
  .then((res) => res.repoDomain);
@@ -122,47 +113,57 @@ export function sortReposForPrompt(
122
113
  }
123
114
 
124
115
  export async function chooseOrCreateARepository(
116
+ client: InitClient,
125
117
  cwd: string,
126
118
  framework: Models.Frameworks,
127
- cookies: string,
128
- base = DEFAULT_BASE,
129
- domain?: string
119
+ preSelectedRepository?: string
130
120
  ): Promise<string> {
131
- const token = Utils.Cookie.parsePrismicAuthToken(cookies);
132
- const repos = await Prismic.Communication.listRepositories(token, base);
133
-
134
- const hasRepo = domain && repos.find((d) => d.domain === domain);
135
- if (hasRepo) return domain;
136
-
137
- if (repos.length === 0) {
138
- const domainName = await promptForRepoDomain(base, domain);
139
- return await createRepository(domainName, framework, cookies, base);
121
+ const repositories: Models.Repository[] = await client.listRepositories();
122
+
123
+ const isPreSelectedValid =
124
+ preSelectedRepository &&
125
+ repositories.find(
126
+ (repository) => repository.domain === preSelectedRepository
127
+ );
128
+ if (isPreSelectedValid) return preSelectedRepository;
129
+
130
+ // No repository to display, ask for a new repository name to create it.
131
+ if (repositories.length === 0) {
132
+ const domainName = await promptForRepoDomain(client, preSelectedRepository);
133
+ await createRepository(client, domainName, framework);
134
+ return domainName;
140
135
  }
141
136
 
142
- const choices = sortReposForPrompt(repos, base, cwd);
143
-
137
+ // prepare the list of repositories to display
138
+ const choices = sortReposForPrompt(
139
+ repositories,
140
+ client.apisEndpoints.Wroom,
141
+ cwd
142
+ );
144
143
  const numberOfDisabledRepos = choices.filter((repo) => {
145
144
  if (repo instanceof Separator) return false;
146
145
  return repo.disabled;
147
146
  }).length;
148
147
 
149
- const res = await inquirer.prompt<{ chosenRepo: string }>([
148
+ // display the list of repositories and wait for the user to choose one.
149
+ const promptResult = await inquirer.prompt<{ chosenRepository: string }>([
150
150
  {
151
151
  type: "list",
152
- name: "chosenRepo",
152
+ name: "chosenRepository",
153
153
  default: 0,
154
154
  required: true,
155
155
  message: "Connect a Prismic Repository or create a new one",
156
156
  choices,
157
157
  pageSize: numberOfDisabledRepos + 2 <= 7 ? 7 : numberOfDisabledRepos + 2,
158
- // loop: false
159
158
  },
160
159
  ]);
161
160
 
162
- if (res.chosenRepo === CREATE_REPO) {
163
- const domainName = await promptForRepoDomain(base, domain);
164
- return await createRepository(domainName, framework, cookies, base);
161
+ // If the user has chosen to create a new repository.
162
+ if (promptResult.chosenRepository === CREATE_REPO) {
163
+ const domainName = await promptForRepoDomain(client, preSelectedRepository);
164
+ await createRepository(client, domainName, framework);
165
+ return domainName;
165
166
  }
166
167
 
167
- return res.chosenRepo;
168
+ return promptResult.chosenRepository;
168
169
  }
@@ -3,23 +3,22 @@ import type { Models } from "@slicemachine/core";
3
3
  import * as Prismic from "@slicemachine/core/build/prismic";
4
4
  import * as NodeUtils from "@slicemachine/core/build/node-utils";
5
5
  import { FrameworkResult } from "./detect-framework";
6
- import { logs } from "../utils";
6
+ import { InitClient, logs } from "../utils";
7
7
  import Tracker from "../utils/tracker";
8
8
 
9
- type Base = Prismic.Endpoints.Base;
10
-
11
9
  const defaultSliceMachineVersion = "0.0.41";
12
10
 
13
11
  export async function configureProject(
12
+ client: InitClient,
14
13
  cwd: string,
15
- base: Base,
16
14
  repositoryDomainName: string,
17
15
  framework: FrameworkResult,
18
16
  sliceLibPath: string[] = [],
19
17
  tracking = true
20
18
  ): Promise<void> {
19
+ const frameworkName = NodeUtils.Framework.fancyName(framework.value);
21
20
  const spinner = logs.spinner(
22
- `Configuring your ${framework.value} & Prismic project...`
21
+ `Configuring your ${frameworkName} and Prismic project...`
23
22
  );
24
23
  spinner.start();
25
24
 
@@ -32,15 +31,22 @@ export async function configureProject(
32
31
 
33
32
  const manifestAlreadyExistWithContent = manifest.exists && manifest.content;
34
33
 
34
+ const libs =
35
+ manifest.content &&
36
+ manifest.content.libraries &&
37
+ manifest.content.libraries.length > 0
38
+ ? manifest.content.libraries
39
+ : ["@/slices"];
40
+
35
41
  const manifestUpdated: Models.Manifest = {
36
42
  ...(manifestAlreadyExistWithContent
37
43
  ? manifest.content
38
44
  : { _latest: sliceMachineVersionInstalled }),
39
45
  apiEndpoint: Prismic.Endpoints.buildRepositoryEndpoint(
40
- base,
46
+ client.apisEndpoints.Wroom,
41
47
  repositoryDomainName
42
48
  ),
43
- libraries: ["@/slices", ...sliceLibPath],
49
+ libraries: [...libs, ...sliceLibPath], // odd case here for staters
44
50
  ...(framework.manuallyAdded ? { framework: framework.value } : {}),
45
51
  ...(!tracking ? { tracking } : {}),
46
52
  };
@@ -52,7 +58,10 @@ export async function configureProject(
52
58
  const pathToSlicesFolder = NodeUtils.CustomPaths(cwd)
53
59
  .library("slices")
54
60
  .value();
55
- if (!NodeUtils.Files.exists(pathToSlicesFolder)) {
61
+ if (
62
+ !NodeUtils.Files.exists(pathToSlicesFolder) &&
63
+ libs.includes("@/slices")
64
+ ) {
56
65
  NodeUtils.Files.mkdir(pathToSlicesFolder, { recursive: true });
57
66
  }
58
67
 
@@ -2,11 +2,30 @@ import { CONSTS } from "@slicemachine/core";
2
2
  import * as NodeUtils from "@slicemachine/core/build/node-utils";
3
3
  import { logs } from "../utils";
4
4
 
5
- export function displayFinalMessage(cwd: string): void {
5
+ export function displayFinalMessage(
6
+ cwd: string,
7
+ wasStarter: boolean,
8
+ reponame: string,
9
+ base: string
10
+ ): void {
6
11
  const yarnLock = NodeUtils.Files.exists(NodeUtils.YarnLockPath(cwd));
7
12
  const command = `${yarnLock ? "yarn" : "npm"} run ${CONSTS.SCRIPT_NAME}`;
13
+ console.log();
8
14
 
9
- console.log(
10
- `${logs.white("■")} Run ${logs.purple(command)} to now launch Slice Machine`
11
- );
15
+ if (wasStarter) {
16
+ const repoUrl = new URL(base);
17
+ repoUrl.hostname = `${reponame}.${repoUrl.hostname}`;
18
+ const urlAsString = repoUrl.toString();
19
+
20
+ const message = `${logs.white(
21
+ "■"
22
+ )} Start editing your content in Prismic ${logs.purple(urlAsString)}`;
23
+ console.log(message);
24
+ } else {
25
+ console.log(
26
+ `${logs.white("■")} Run ${logs.purple(
27
+ command
28
+ )} to launch Slice Machine and create your first Custom Type`
29
+ );
30
+ }
12
31
  }
@@ -6,3 +6,4 @@ export { loginOrBypass } from "./loginOrBypass";
6
6
  export { configureProject } from "./configure-project";
7
7
  export { displayFinalMessage } from "./display-final-message";
8
8
  export { installLib } from "./install-lib";
9
+ export { sendStarterData } from "./sendStarterData";
@@ -32,18 +32,14 @@ function depsForFramework(framework: Models.Frameworks): string {
32
32
  }
33
33
  }
34
34
 
35
- export async function installRequiredDependencies(
36
- cwd: string,
37
- framework: Models.Frameworks
38
- ): Promise<void> {
39
- const yarnLock = NodeUtils.Files.exists(NodeUtils.YarnLockPath(cwd));
40
- const installDevDependencyCommand = yarnLock
35
+ async function addAndInstallDeps(
36
+ framework: Models.Frameworks,
37
+ useYarn = false
38
+ ): Promise<string> {
39
+ const installDevDependencyCommand = useYarn
41
40
  ? "yarn add -D"
42
41
  : "npm install --save-dev";
43
- const installDependencyCommand = yarnLock ? "yarn add" : "npm install --save";
44
-
45
- const spinner = logs.spinner("Downloading Slice Machine");
46
- spinner.start();
42
+ const installDependencyCommand = useYarn ? "yarn add" : "npm install --save";
47
43
 
48
44
  const { stderr } = await execCommand(
49
45
  `${installDevDependencyCommand} ${SM_PACKAGE_NAME}`
@@ -52,6 +48,29 @@ export async function installRequiredDependencies(
52
48
  const deps = depsForFramework(framework);
53
49
  if (deps) await execCommand(`${installDependencyCommand} ${deps}`);
54
50
 
51
+ return stderr;
52
+ }
53
+
54
+ async function installDeps(useYarn = false): Promise<string> {
55
+ const installCommand = useYarn ? "yarn" : "npm install";
56
+ const { stderr } = await execCommand(installCommand);
57
+ return stderr;
58
+ }
59
+
60
+ export async function installRequiredDependencies(
61
+ cwd: string,
62
+ framework: Models.Frameworks,
63
+ skipDependencies: boolean
64
+ ): Promise<void> {
65
+ const yarnLock = NodeUtils.Files.exists(NodeUtils.YarnLockPath(cwd));
66
+
67
+ const spinner = logs.spinner("Installing Slice Machine");
68
+ spinner.start();
69
+
70
+ const stderr = await (skipDependencies
71
+ ? installDeps(yarnLock)
72
+ : addAndInstallDeps(framework, yarnLock));
73
+
55
74
  const pathToPkg = path.join(
56
75
  NodeUtils.PackagePaths(cwd).value(),
57
76
  SM_PACKAGE_NAME
@@ -1,21 +1,25 @@
1
1
  import { Models } from "@slicemachine/core";
2
- import { validateSessionAndGetProfile } from "../utils/communication";
3
- import { logs, Auth } from "../utils";
2
+ import { PrismicSharedConfigManager } from "@slicemachine/core/build/prismic";
3
+ import { logs, Auth, InitClient } from "../utils";
4
+
5
+ export async function loginOrBypass(
6
+ client: InitClient
7
+ ): Promise<Models.UserProfile> {
8
+ const user: Models.UserProfile | null = await client
9
+ .profile()
10
+ .catch(() => null);
4
11
 
5
- export async function loginOrBypass(base: string): Promise<{
6
- info: Models.UserInfo;
7
- profile: Models.UserProfile | null;
8
- } | null> {
9
- const user = await validateSessionAndGetProfile(base).catch((err) =>
10
- console.log(err)
11
- );
12
12
  if (user) {
13
- const email = user.info.email;
13
+ const email = user.email;
14
14
  logs.writeCheck(`Logged in as ${logs.bold(email)}`);
15
15
  return user;
16
- } else {
17
- await Auth.login(base);
18
- const user = await validateSessionAndGetProfile(base);
19
- return user;
20
16
  }
17
+
18
+ await Auth.login(client);
19
+
20
+ // update token used to make calls.
21
+ client.updateAuthenticationToken(PrismicSharedConfigManager.getAuth());
22
+
23
+ const userAfterLogin: Models.UserProfile = await client.profile();
24
+ return userAfterLogin;
21
25
  }
@@ -0,0 +1,31 @@
1
+ import { retrieveManifest, Files } from "@slicemachine/core/build/node-utils";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import { sendSlices } from "./starters/slices";
5
+ import { sendCustomTypes } from "./starters/custom-types";
6
+ import { sendDocuments } from "./starters/documents";
7
+ import { InitClient } from "../utils";
8
+
9
+ export async function sendStarterData(
10
+ client: InitClient,
11
+ cwd: string,
12
+ pushDocuments = true
13
+ ) {
14
+ const manifest = retrieveManifest(cwd);
15
+ const documentsPath = path.join(cwd, "documents");
16
+ const hasDocuments = Files.exists(documentsPath);
17
+
18
+ if (manifest.exists === false || hasDocuments === false)
19
+ return Promise.resolve(false);
20
+
21
+ if (manifest.content) await sendSlices(client, cwd, manifest.content);
22
+ await sendCustomTypes(client, cwd);
23
+
24
+ // If the user choose not to push documents, we still delete the documents folder.
25
+ if (!pushDocuments) {
26
+ fs.rmSync(documentsPath, { recursive: true, force: true });
27
+ return Promise.resolve(true);
28
+ }
29
+
30
+ return sendDocuments(client, cwd);
31
+ }
@@ -0,0 +1,81 @@
1
+ import { CustomType } from "@prismicio/types-internal/lib/customtypes";
2
+ import { Files, CustomTypesPaths } from "@slicemachine/core/build/node-utils";
3
+ import { isLeft } from "fp-ts/lib/Either";
4
+ import { promptToPushCustomTypes } from "./prompts";
5
+ import { InitClient, logs } from "../../utils";
6
+ import { ClientError } from "@slicemachine/client";
7
+
8
+ export function readLocalCustomTypes(cwd: string): Array<CustomType> {
9
+ const customTypePaths = CustomTypesPaths(cwd);
10
+ const dir = customTypePaths.value();
11
+
12
+ if (Files.isDirectory(dir) === false) return [];
13
+
14
+ const fileNames = Files.readDirectory(dir);
15
+
16
+ const files = fileNames.reduce<Array<CustomType>>((acc, fileName) => {
17
+ const filePath = customTypePaths.customType(fileName).model();
18
+ const json = Files.safeReadJson(filePath);
19
+
20
+ if (!json) return acc;
21
+
22
+ const file = CustomType.decode(json);
23
+
24
+ if (file instanceof Error) {
25
+ logs.writeError(`reading ${filePath}: ${file.message}`);
26
+ return acc;
27
+ }
28
+ if (isLeft(file)) {
29
+ logs.writeError(`validating ${filePath}: ${JSON.stringify(file.left)}`);
30
+ return acc;
31
+ }
32
+
33
+ return [...acc, file.right];
34
+ }, []);
35
+
36
+ return files;
37
+ }
38
+
39
+ export async function sendCustomTypes(client: InitClient, cwd: string) {
40
+ const localCustomTypes = readLocalCustomTypes(cwd);
41
+
42
+ // nothing to push
43
+ if (localCustomTypes.length === 0) return Promise.resolve(false);
44
+
45
+ const remoteCustomTypeIds = await client
46
+ .getCustomTypes()
47
+ .then((customTypes) => customTypes.map((customType) => customType.id));
48
+
49
+ if (remoteCustomTypeIds.length) {
50
+ const shouldPush = await promptToPushCustomTypes();
51
+ if (shouldPush === false) return Promise.resolve(false);
52
+ }
53
+
54
+ const spinner = logs.spinner(
55
+ "Pushing existing custom types to your repository"
56
+ );
57
+ spinner.start();
58
+
59
+ await Promise.all(
60
+ localCustomTypes.map(async (customType) => {
61
+ const promise = remoteCustomTypeIds.includes(customType.id)
62
+ ? client.updateCustomType(customType)
63
+ : client.insertCustomType(customType);
64
+
65
+ return promise.catch((error: ClientError) => {
66
+ logs.writeError(
67
+ `Sending custom type ${customType.id} - ${error.message}`
68
+ );
69
+
70
+ // throwing the error again to stop the Promise.all
71
+ throw error;
72
+ });
73
+ })
74
+ ).catch(() => {
75
+ // the error about the custom type that failed to be pushed should be in the terminal already.
76
+ process.exit(1);
77
+ });
78
+
79
+ spinner.succeed();
80
+ return Promise.resolve(true);
81
+ }
@@ -0,0 +1,89 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import type { AxiosError } from "axios";
4
+
5
+ import * as t from "io-ts";
6
+ import { getOrElseW } from "fp-ts/Either";
7
+ import { InitClient, logs, lsdir, lsfiles } from "../../utils";
8
+ import { PrismicSharedConfigManager } from "@slicemachine/core/build/prismic/SharedConfig";
9
+
10
+ const SignatureFileReader = t.type({
11
+ signature: t.string,
12
+ });
13
+
14
+ type SignatureFile = t.TypeOf<typeof SignatureFileReader>;
15
+
16
+ export async function readSignatureFile(cwd: string): Promise<SignatureFile> {
17
+ const pathToFile = path.join(cwd, "documents", "index.json");
18
+ return fs.promises.readFile(pathToFile, "utf-8").then((res) => {
19
+ const data = JSON.parse(res) as unknown;
20
+ return getOrElseW(() => {
21
+ throw new Error("Unable to read document signature file");
22
+ })(SignatureFileReader.decode(data));
23
+ });
24
+ }
25
+
26
+ export async function readDocuments(
27
+ cwd: string
28
+ ): Promise<Record<string, unknown>> {
29
+ const documentDir = path.join(cwd, "documents");
30
+ const dirs = await lsdir(documentDir);
31
+
32
+ const files = (await Promise.all(dirs.map((dir) => lsfiles(dir)))).flat();
33
+
34
+ const documentObj = files.reduce<Record<string, unknown>>((acc, file) => {
35
+ const filename: string = path.parse(file).name;
36
+ const fileContent: string = fs.readFileSync(file, "utf-8");
37
+ const json = JSON.parse(fileContent) as Record<string, unknown>;
38
+
39
+ return { ...acc, [filename]: json };
40
+ }, {});
41
+
42
+ return documentObj;
43
+ }
44
+
45
+ export async function sendDocuments(
46
+ client: InitClient,
47
+ cwd: string
48
+ ): Promise<boolean> {
49
+ const pathToDocuments = path.join(cwd, "documents");
50
+ const pathToSignatureFile = path.join(pathToDocuments, "index.json");
51
+
52
+ // Without the signature, we can't push documents to Prismic.
53
+ if (!fs.existsSync(pathToSignatureFile)) return Promise.resolve(false);
54
+
55
+ const signatureObj = await readSignatureFile(cwd);
56
+ const documents: Record<string, unknown> = await readDocuments(cwd);
57
+
58
+ // No documents to push
59
+ if (Object.keys(documents).length === 0) return Promise.resolve(false);
60
+
61
+ const spinner = logs.spinner("Pushing existing documents to your repository");
62
+ spinner.start();
63
+
64
+ return client
65
+ .pushDocuments(
66
+ signatureObj.signature,
67
+ documents,
68
+ PrismicSharedConfigManager.get().cookies
69
+ )
70
+ .then(() => {
71
+ spinner.succeed();
72
+ fs.rmSync(pathToDocuments, { recursive: true, force: true });
73
+ return true;
74
+ })
75
+ .catch((e: AxiosError) => {
76
+ spinner.fail();
77
+ if (e.response?.data === "Repository should not contain documents") {
78
+ logs.writeError(
79
+ "The selected repository is not empty, documents cannot be uploaded. Please choose an empty repository or delete the documents contained in your repository."
80
+ );
81
+ } else {
82
+ logs.writeError(
83
+ "Sending documents failed, please try again. If the problem persists, contact us."
84
+ );
85
+ logs.writeError(`Full error: ${e.code || 500} - ${e.message}`);
86
+ }
87
+ process.exit(1);
88
+ });
89
+ }
@@ -0,0 +1,29 @@
1
+ import inquirer from "inquirer";
2
+
3
+ export async function promptToPushSlices(): Promise<boolean> {
4
+ return inquirer
5
+ .prompt<{ pushSlices: boolean }>([
6
+ {
7
+ type: "confirm",
8
+ name: "pushSlices",
9
+ default: false,
10
+ message:
11
+ "Your repository already contains Slices. Do you want to continue pushing your local Slices?",
12
+ },
13
+ ])
14
+ .then((res) => res.pushSlices);
15
+ }
16
+
17
+ export async function promptToPushCustomTypes(): Promise<boolean> {
18
+ return inquirer
19
+ .prompt<{ pushCustomTypes: boolean }>([
20
+ {
21
+ type: "confirm",
22
+ name: "pushCustomTypes",
23
+ default: false,
24
+ message:
25
+ "Your repository already contains Custom Types. Do you want to continue pushing your local Custom Types?",
26
+ },
27
+ ])
28
+ .then((res) => res.pushCustomTypes);
29
+ }
@@ -0,0 +1,70 @@
1
+ import { InitClient } from "../../utils";
2
+ import {
3
+ Component,
4
+ ComponentInfo,
5
+ VariationSM,
6
+ SliceSM,
7
+ } from "@slicemachine/core/build/models";
8
+ import { Acl, ClientError } from "@slicemachine/client";
9
+ import { writeError } from "../../utils/logs";
10
+
11
+ async function updateVariationWithScreenshot(
12
+ client: InitClient,
13
+ acl: Acl,
14
+ screenshotPaths: ComponentInfo["screenshotPaths"],
15
+ sliceName: SliceSM["id"],
16
+ variation: VariationSM
17
+ ): Promise<VariationSM> {
18
+ const screenshot = screenshotPaths[variation.id];
19
+ if (!screenshot || !screenshot.path) return Promise.resolve(variation);
20
+
21
+ return client
22
+ .uploadScreenshot({
23
+ acl,
24
+ sliceName,
25
+ variationId: variation.id,
26
+ filePath: screenshot.path,
27
+ })
28
+ .then((screenshotUrl) => {
29
+ return {
30
+ ...variation,
31
+ imageUrl: screenshotUrl,
32
+ };
33
+ })
34
+ .catch((error: ClientError) => {
35
+ writeError(
36
+ `Couldn't upload screenshot slice: ${sliceName} - variation: ${variation.id}`
37
+ );
38
+ writeError(error.message, "Full error:");
39
+ return variation;
40
+ });
41
+ }
42
+
43
+ export async function updateSlicesWithScreenshots(
44
+ client: InitClient,
45
+ acl: Acl,
46
+ components: Array<Component>
47
+ ): Promise<Array<SliceSM>> {
48
+ return Promise.all(
49
+ components.map(async (component) => {
50
+ const { screenshotPaths, model } = component;
51
+
52
+ const variationsUpdated: VariationSM[] = await Promise.all(
53
+ model.variations.map(async (variation) =>
54
+ updateVariationWithScreenshot(
55
+ client,
56
+ acl,
57
+ screenshotPaths,
58
+ model.id,
59
+ variation
60
+ )
61
+ )
62
+ );
63
+
64
+ return {
65
+ ...model,
66
+ variations: variationsUpdated,
67
+ };
68
+ })
69
+ );
70
+ }