@slicemachine/init 1.1.9-alpha.3 → 1.1.10-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- const core = require('@slicemachine/core');
5
+ const client = require('@slicemachine/client');
6
6
  const Prismic = require('@slicemachine/core/build/prismic');
7
7
  const ServerAnalytics = require('analytics-node');
8
8
  const uuid = require('uuid');
@@ -11,18 +11,24 @@ const util = require('util');
11
11
  const child_process = require('child_process');
12
12
  const chalk = require('chalk');
13
13
  const ora = require('ora');
14
+ const core = require('@slicemachine/core');
14
15
  const hapi = require('@hapi/hapi');
15
16
  const open = require('open');
17
+ const t = require('io-ts');
18
+ const fs = require('fs');
16
19
  const NodeUtils = require('@slicemachine/core/build/node-utils');
17
20
  const inquirer = require('inquirer');
18
21
  const Separator = require('inquirer/lib/objects/separator');
19
- const axios = require('axios');
20
- const _function = require('fp-ts/function');
21
- const Either = require('fp-ts/Either');
22
22
  const tmp = require('tmp');
23
23
  const AdmZip = require('adm-zip');
24
24
  const fsExtra = require('fs-extra');
25
- const fs = require('fs');
25
+ const axios = require('axios');
26
+ const Either = require('fp-ts/Either');
27
+ const models = require('@slicemachine/core/build/models');
28
+ const Libraries = require('@slicemachine/core/build/libraries');
29
+ const customtypes = require('@prismicio/types-internal/lib/customtypes');
30
+ const Either$1 = require('fp-ts/lib/Either');
31
+ const SharedConfig = require('@slicemachine/core/build/prismic/SharedConfig');
26
32
 
27
33
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
28
34
 
@@ -53,14 +59,17 @@ const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
53
59
  const ora__default = /*#__PURE__*/_interopDefaultLegacy(ora);
54
60
  const hapi__namespace = /*#__PURE__*/_interopNamespace(hapi);
55
61
  const open__default = /*#__PURE__*/_interopDefaultLegacy(open);
62
+ const t__namespace = /*#__PURE__*/_interopNamespace(t);
63
+ const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
56
64
  const NodeUtils__namespace = /*#__PURE__*/_interopNamespace(NodeUtils);
57
65
  const inquirer__namespace = /*#__PURE__*/_interopNamespace(inquirer);
66
+ const inquirer__default = /*#__PURE__*/_interopDefaultLegacy(inquirer);
58
67
  const Separator__default = /*#__PURE__*/_interopDefaultLegacy(Separator);
59
- const axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
60
68
  const tmp__default = /*#__PURE__*/_interopDefaultLegacy(tmp);
61
69
  const AdmZip__default = /*#__PURE__*/_interopDefaultLegacy(AdmZip);
62
70
  const fsExtra__default = /*#__PURE__*/_interopDefaultLegacy(fsExtra);
63
- const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
71
+ const axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
72
+ const Libraries__namespace = /*#__PURE__*/_interopNamespace(Libraries);
64
73
 
65
74
  var __accessCheck = (obj, member, msg) => {
66
75
  if (!member.has(obj))
@@ -81,6 +90,13 @@ var __privateSet = (obj, member, value, setter) => {
81
90
  return value;
82
91
  };
83
92
  var _client, _isTrackingActive, _anonymousId, _userId, _repository;
93
+ var EventType;
94
+ (function(EventType2) {
95
+ EventType2["DownloadLibrary"] = "SliceMachine Download Library";
96
+ EventType2["InitStart"] = "SliceMachine Init Start";
97
+ EventType2["InitIdentify"] = "SliceMachine Init Identify";
98
+ EventType2["InitDone"] = "SliceMachine Init Done";
99
+ })(EventType || (EventType = {}));
84
100
  class InitTracker {
85
101
  constructor() {
86
102
  __privateAdd(this, _client, null);
@@ -147,16 +163,16 @@ class InitTracker {
147
163
  return this._identifyEvent(userId, intercomHash);
148
164
  }
149
165
  trackDownloadLibrary(library) {
150
- return this._trackEvent("SliceMachine Download Library" /* DownloadLibrary */, { library });
166
+ return this._trackEvent(EventType.DownloadLibrary, { library });
151
167
  }
152
168
  trackInitIdentify() {
153
- return this._trackEvent("SliceMachine Init Identify" /* InitIdentify */);
169
+ return this._trackEvent(EventType.InitIdentify);
154
170
  }
155
171
  trackInitStart(repoDomain) {
156
- return this._trackEvent("SliceMachine Init Start" /* InitStart */, { repo: repoDomain });
172
+ return this._trackEvent(EventType.InitStart, { repo: repoDomain });
157
173
  }
158
174
  trackInitDone(framework) {
159
- return this._trackEvent("SliceMachine Init Done" /* InitDone */, { framework });
175
+ return this._trackEvent(EventType.InitDone, { framework });
160
176
  }
161
177
  }
162
178
  _client = new WeakMap();
@@ -214,7 +230,7 @@ const logs = /*#__PURE__*/Object.freeze({
214
230
  });
215
231
 
216
232
  const { Cookie } = core.Utils;
217
- const { DEFAULT_BASE: DEFAULT_BASE$1, DEFAULT_SERVER_PORT } = core.CONSTS;
233
+ const { DEFAULT_BASE, DEFAULT_SERVER_PORT } = core.CONSTS;
218
234
  const { bold, underline, spinner, writeError } = logs;
219
235
  const isHandlerData = (data) => {
220
236
  if (typeof data != "object")
@@ -257,13 +273,16 @@ const authenticationHandler = (server) => (onSuccess, onFail) => {
257
273
  }
258
274
  };
259
275
  };
276
+ function stripTrailingSlash(str) {
277
+ return str.endsWith("/") ? str.slice(0, -1) : str;
278
+ }
260
279
  function buildServer(base, port, host) {
261
280
  const server = hapi__namespace.server({
262
281
  port,
263
282
  host,
264
283
  routes: {
265
284
  cors: {
266
- origin: [base],
285
+ origin: [stripTrailingSlash(base)],
267
286
  headers: ["Origin", "X-Requested-With", "Content-Type", "Accept"]
268
287
  }
269
288
  }
@@ -286,7 +305,7 @@ function askSingleChar(title) {
286
305
  process.stdin.on("data", handler);
287
306
  });
288
307
  }
289
- async function startServerAndOpenBrowser(url, action, base = DEFAULT_BASE$1, port = DEFAULT_SERVER_PORT) {
308
+ async function startServerAndOpenBrowser(url, action, base = DEFAULT_BASE, port = DEFAULT_SERVER_PORT) {
290
309
  const confirmation = await askSingleChar(`>> Press any key to open the browser to ${action} or q to exit:`);
291
310
  if (confirmation === "q" || confirmation === "")
292
311
  return process.exit(-1);
@@ -323,46 +342,92 @@ async function startServerAndOpenBrowser(url, action, base = DEFAULT_BASE$1, por
323
342
  }
324
343
 
325
344
  async function startAuth({
326
- base,
345
+ client,
327
346
  url,
328
347
  action
329
348
  }) {
330
- const { onLoginFail } = await startServerAndOpenBrowser(url, action, base);
349
+ const { onLoginFail } = await startServerAndOpenBrowser(url, action, client.apisEndpoints.Wroom);
331
350
  try {
332
- await core.Utils.Poll.startPolling(() => Auth.validateSession(base), (user) => !!user, 3e3, 60);
351
+ await core.Utils.Poll.startPolling(() => Auth.validateSession(client), (isSessionValid) => isSessionValid == true, 3e3, 60);
333
352
  return;
334
353
  } catch (e) {
335
354
  onLoginFail();
336
355
  }
337
356
  }
338
357
  const Auth = {
339
- login: async (base) => {
340
- const endpoints = Prismic.Endpoints.buildEndpoints(base);
358
+ login: async (client) => {
359
+ const endpoints = Prismic.Endpoints.buildEndpoints(client.apisEndpoints.Wroom);
341
360
  return startAuth({
342
- base,
361
+ client,
343
362
  url: endpoints.Dashboard.cliLogin,
344
363
  action: "login"
345
364
  });
346
365
  },
347
- signup: async (base) => {
348
- const endpoints = Prismic.Endpoints.buildEndpoints(base);
349
- return startAuth({
350
- base,
351
- url: endpoints.Dashboard.cliSignup,
352
- action: "signup"
353
- });
354
- },
355
- logout: () => Prismic.PrismicSharedConfigManager.remove(),
356
- validateSession: async (requiredBase) => {
357
- const config = Prismic.PrismicSharedConfigManager.get();
358
- if (!config.cookies.length)
359
- return Promise.resolve(null);
360
- if (requiredBase != config.base)
361
- return Promise.resolve(null);
362
- return Prismic.Communication.validateSession(config.cookies, requiredBase).catch(() => null);
366
+ validateSession: async (client) => {
367
+ const authToken = Prismic.PrismicSharedConfigManager.getAuth();
368
+ return client.updateAuthenticationToken(authToken).profile().then((userProfile) => {
369
+ Prismic.PrismicSharedConfigManager.setProperties({
370
+ shortId: userProfile.shortId,
371
+ intercomHash: userProfile.intercomHash
372
+ });
373
+ return true;
374
+ }).catch(() => false);
363
375
  }
364
376
  };
365
377
 
378
+ class InitClient extends client.Client {
379
+ async listRepositories() {
380
+ return client.getAndValidateResponse(this._get(`${this.apisEndpoints.Users}repositories`), "repository list", t__namespace.array(core.Models.Repository));
381
+ }
382
+ async createRepository(domain, framework) {
383
+ const data = {
384
+ domain,
385
+ framework,
386
+ plan: "personal",
387
+ isAnnual: "false",
388
+ role: "developer"
389
+ };
390
+ return this._fetch({
391
+ method: "post",
392
+ url: `${this.apisEndpoints.Wroom}authentication/newrepository?app=slicemachine`,
393
+ data,
394
+ headers: {
395
+ Cookie: Prismic.PrismicSharedConfigManager.get().cookies,
396
+ "User-Agent": "prismic-cli/sm"
397
+ }
398
+ }).then(() => domain);
399
+ }
400
+ async domainExist(domain) {
401
+ return client.getAndValidateResponse(this._get(`${this.apisEndpoints.Wroom}app/dashboard/repositories/${domain}/exists`), "repository exists", t__namespace.boolean);
402
+ }
403
+ async pushDocuments(signature, documents, cookies) {
404
+ if (!this.repository)
405
+ throw new Error("Repository undefined in the client");
406
+ const repositoryDirectUrl = new URL(this.apisEndpoints.Wroom);
407
+ repositoryDirectUrl.hostname = `${this.repository}.${repositoryDirectUrl.hostname}`;
408
+ return this._fetch({
409
+ method: "post",
410
+ url: `${repositoryDirectUrl.toString()}starter/documents`,
411
+ data: { signature, documents: JSON.stringify(documents) },
412
+ headers: {
413
+ Cookie: cookies,
414
+ "User-Agent": "prismic-cli/0"
415
+ }
416
+ });
417
+ }
418
+ }
419
+
420
+ async function lsdir(dir) {
421
+ return fs__default["default"].promises.readdir(dir).then((dirs) => {
422
+ return dirs.filter((name) => fs__default["default"].statSync(path__default["default"].join(dir, name)).isDirectory()).map((subdirectory) => path__default["default"].join(dir, subdirectory));
423
+ });
424
+ }
425
+ async function lsfiles(dir) {
426
+ return fs__default["default"].promises.readdir(dir).then((dirs) => {
427
+ return dirs.filter((name) => fs__default["default"].statSync(path__default["default"].join(dir, name)).isFile()).map((file) => path__default["default"].join(dir, file));
428
+ });
429
+ }
430
+
366
431
  function findArgument(args, name) {
367
432
  const flagIndex = args.indexOf(`--${name}`);
368
433
  if (flagIndex === -1)
@@ -374,7 +439,21 @@ function findArgument(args, name) {
374
439
  return;
375
440
  return flagValue;
376
441
  }
442
+ function findFlag(args, name) {
443
+ const toFind = `--${name}`;
444
+ return args.includes(toFind);
445
+ }
377
446
  const execCommand = util__default["default"].promisify(child_process.exec);
447
+ function getApplicationMode(argumentValue) {
448
+ switch (argumentValue) {
449
+ case client.ApplicationMode.PROD:
450
+ case client.ApplicationMode.STAGE:
451
+ case client.ApplicationMode.DEV:
452
+ return argumentValue;
453
+ default:
454
+ return null;
455
+ }
456
+ }
378
457
 
379
458
  const {
380
459
  PRISMIC_CLIENT,
@@ -403,16 +482,25 @@ function depsForFramework(framework) {
403
482
  return "";
404
483
  }
405
484
  }
406
- async function installRequiredDependencies(cwd, framework) {
407
- const yarnLock = NodeUtils__namespace.Files.exists(NodeUtils__namespace.YarnLockPath(cwd));
408
- const installDevDependencyCommand = yarnLock ? "yarn add -D" : "npm install --save-dev";
409
- const installDependencyCommand = yarnLock ? "yarn add" : "npm install --save";
410
- const spinner = spinner$1("Downloading Slice Machine");
411
- spinner.start();
485
+ async function addAndInstallDeps(framework, useYarn = false) {
486
+ const installDevDependencyCommand = useYarn ? "yarn add -D" : "npm install --save-dev";
487
+ const installDependencyCommand = useYarn ? "yarn add" : "npm install --save";
412
488
  const { stderr } = await execCommand(`${installDevDependencyCommand} ${SM_PACKAGE_NAME}`);
413
489
  const deps = depsForFramework(framework);
414
490
  if (deps)
415
491
  await execCommand(`${installDependencyCommand} ${deps}`);
492
+ return stderr;
493
+ }
494
+ async function installDeps(useYarn = false) {
495
+ const installCommand = useYarn ? "yarn" : "npm install";
496
+ const { stderr } = await execCommand(installCommand);
497
+ return stderr;
498
+ }
499
+ async function installRequiredDependencies(cwd, framework, skipDependencies) {
500
+ const yarnLock = NodeUtils__namespace.Files.exists(NodeUtils__namespace.YarnLockPath(cwd));
501
+ const spinner = spinner$1("Installing Slice Machine");
502
+ spinner.start();
503
+ const stderr = await (skipDependencies ? installDeps(yarnLock) : addAndInstallDeps(framework, yarnLock));
416
504
  const pathToPkg = path__default["default"].join(NodeUtils__namespace.PackagePaths(cwd).value(), SM_PACKAGE_NAME);
417
505
  const isPackageInstalled = NodeUtils__namespace.Files.exists(pathToPkg);
418
506
  if (isPackageInstalled || !stderr.length) {
@@ -435,16 +523,15 @@ function validatePkg(cwd) {
435
523
  }
436
524
  }
437
525
 
438
- function createRepository(domain, framework, cookies, base) {
526
+ function createRepository(client, domain, framework) {
439
527
  const spinner = spinner$1("Creating Prismic Repository");
440
528
  spinner.start();
441
- return Prismic__namespace.Communication.createRepository(domain, cookies, framework, base).then((res) => {
442
- const addressUrl = new URL(base);
443
- const repoDomainName = res.data.domain || domain;
444
- addressUrl.hostname = `${repoDomainName}.${addressUrl.hostname}`;
529
+ return client.createRepository(domain, framework).then((domain2) => {
530
+ const addressUrl = new URL(client.apisEndpoints.Wroom);
531
+ addressUrl.hostname = `${domain2}.${addressUrl.hostname}`;
445
532
  const address = addressUrl.toString();
446
533
  spinner.succeed(`We created your new repository ${address}`);
447
- return repoDomainName;
534
+ return domain2;
448
535
  }).catch((error) => {
449
536
  spinner.fail(`Error creating repository ${domain}`);
450
537
  if (error.message) {
@@ -456,14 +543,38 @@ function createRepository(domain, framework, cookies, base) {
456
543
  });
457
544
  }
458
545
 
546
+ async function validateRepositoryName(client, name) {
547
+ const domain = name.trim();
548
+ const errors = [];
549
+ const startsWithLetter = /^[a-zA-Z]/.test(domain);
550
+ if (!startsWithLetter)
551
+ errors.push("Must start with a letter.");
552
+ const acceptedChars = /^[a-z0-9-]+$/.test(domain);
553
+ if (!acceptedChars)
554
+ errors.push("Must contain only lowercase letters, numbers and hyphens.");
555
+ const fourCharactersOrMore = domain.length >= 4;
556
+ if (!fourCharactersOrMore)
557
+ errors.push("Must have four or more alphanumeric characters and/or hyphens.");
558
+ const endsWithALetterOrNumber = /[a-z0-9]$/.test(domain);
559
+ if (!endsWithALetterOrNumber)
560
+ errors.push("Must end in a letter or a number.");
561
+ const thirtyCharacterOrLess = domain.length <= 30;
562
+ if (!thirtyCharacterOrLess)
563
+ errors.push("Must be 30 characters or less");
564
+ if (errors.length > 0) {
565
+ const errorString = errors.map((d, i) => `(${i + 1}: ${d}`).join(" ");
566
+ const msg = `Validation errors: ${errorString}`;
567
+ return Promise.reject(new Error(msg));
568
+ }
569
+ return client.domainExist(domain).then((isAvailable) => isAvailable ? true : Promise.reject(new Error(`${name} is already in use`))).catch(() => Promise.reject(new Error(`${name} is already in use`)));
570
+ }
571
+
459
572
  const CREATE_REPO = "$_CREATE_REPO";
460
- const DEFAULT_BASE = core.CONSTS.DEFAULT_BASE;
461
- function prettyRepoName(address, value) {
462
- const repoName = value ? cyan(value) : dim.cyan("repo-name");
463
- return `${cyan.dim(`${address.protocol}//`)}${repoName}${cyan.dim(`.${address.hostname}`)}`;
573
+ function prettyRepoName(address, domain) {
574
+ return `${cyan.dim(`${address.protocol}//`)}${cyan(domain)}${cyan.dim(`.${address.hostname}`)}`;
464
575
  }
465
- async function promptForRepoDomain(base, defaultValue) {
466
- const address = new URL(base);
576
+ async function promptForRepoDomain(client, defaultValue) {
577
+ const address = new URL(client.apisEndpoints.Wroom);
467
578
  writeInfo("The name acts as a domain/endpoint for your content repo and should be completely unique.");
468
579
  return inquirer__namespace.prompt([
469
580
  {
@@ -472,11 +583,8 @@ async function promptForRepoDomain(base, defaultValue) {
472
583
  type: "input",
473
584
  required: true,
474
585
  default: defaultValue,
475
- transformer: (value) => prettyRepoName(address, value || defaultValue),
476
- async validate(name) {
477
- const result = await Prismic__namespace.Communication.validateRepositoryName(name, base, false);
478
- return result === name || result;
479
- }
586
+ transformer: (value) => prettyRepoName(address, value || defaultValue || "repository"),
587
+ validate: (name) => validateRepositoryName(client, name)
480
588
  }
481
589
  ]).then((res) => res.repoDomain);
482
590
  }
@@ -530,26 +638,26 @@ function sortReposForPrompt(repos, base, cwd) {
530
638
  createNew
531
639
  ]).sort(orderPrompts(maybeConfiguredRepoName));
532
640
  }
533
- async function chooseOrCreateARepository(cwd, framework, cookies, base = DEFAULT_BASE, domain) {
534
- const token = core.Utils.Cookie.parsePrismicAuthToken(cookies);
535
- const repos = await Prismic__namespace.Communication.listRepositories(token, base);
536
- const hasRepo = domain && repos.find((d) => d.domain === domain);
537
- if (hasRepo)
538
- return domain;
539
- if (repos.length === 0) {
540
- const domainName = await promptForRepoDomain(base, domain);
541
- return await createRepository(domainName, framework, cookies, base);
542
- }
543
- const choices = sortReposForPrompt(repos, base, cwd);
641
+ async function chooseOrCreateARepository(client, cwd, framework, preSelectedRepository) {
642
+ const repositories = await client.listRepositories();
643
+ const isPreSelectedValid = preSelectedRepository && repositories.find((repository) => repository.domain === preSelectedRepository);
644
+ if (isPreSelectedValid)
645
+ return preSelectedRepository;
646
+ if (repositories.length === 0) {
647
+ const domainName = await promptForRepoDomain(client, preSelectedRepository);
648
+ await createRepository(client, domainName, framework);
649
+ return domainName;
650
+ }
651
+ const choices = sortReposForPrompt(repositories, client.apisEndpoints.Wroom, cwd);
544
652
  const numberOfDisabledRepos = choices.filter((repo) => {
545
653
  if (repo instanceof Separator__default["default"])
546
654
  return false;
547
655
  return repo.disabled;
548
656
  }).length;
549
- const res = await inquirer__namespace.prompt([
657
+ const promptResult = await inquirer__namespace.prompt([
550
658
  {
551
659
  type: "list",
552
- name: "chosenRepo",
660
+ name: "chosenRepository",
553
661
  default: 0,
554
662
  required: true,
555
663
  message: "Connect a Prismic Repository or create a new one",
@@ -557,11 +665,12 @@ async function chooseOrCreateARepository(cwd, framework, cookies, base = DEFAULT
557
665
  pageSize: numberOfDisabledRepos + 2 <= 7 ? 7 : numberOfDisabledRepos + 2
558
666
  }
559
667
  ]);
560
- if (res.chosenRepo === CREATE_REPO) {
561
- const domainName = await promptForRepoDomain(base, domain);
562
- return await createRepository(domainName, framework, cookies, base);
668
+ if (promptResult.chosenRepository === CREATE_REPO) {
669
+ const domainName = await promptForRepoDomain(client, preSelectedRepository);
670
+ await createRepository(client, domainName, framework);
671
+ return domainName;
563
672
  }
564
- return res.chosenRepo;
673
+ return promptResult.chosenRepository;
565
674
  }
566
675
 
567
676
  async function promptForFramework() {
@@ -622,67 +731,34 @@ async function detectFramework(cwd) {
622
731
  }
623
732
  }
624
733
 
625
- async function getUserProfile(cookies, base = core.CONSTS.DEFAULT_BASE) {
626
- const userServiceBase = core.CONSTS.DEFAULT_BASE === base ? core.CONSTS.USER_SERVICE_BASE : core.CONSTS.USER_SERVICE_STAGING_BASE;
627
- const url = new URL(userServiceBase);
628
- url.pathname = "profile";
629
- const endpoint = url.toString();
630
- const token = core.Utils.Cookie.parsePrismicAuthToken(cookies);
631
- return axios__default["default"].get(endpoint, {
632
- headers: {
633
- Authorization: `Bearer ${token}`
634
- }
635
- }).then((res) => _function.pipe(core.Models.UserProfile.decode(res.data), Either.fold(() => {
636
- throw new Error("Can't parse user profile");
637
- }, (data) => data)));
638
- }
639
- async function validateSessionAndGetProfile(base = core.CONSTS.DEFAULT_BASE) {
640
- const config = Prismic__namespace.PrismicSharedConfigManager.get();
641
- if (!config.cookies.length)
642
- return Promise.resolve(null);
643
- if (base != config.base)
644
- return Promise.resolve(null);
645
- try {
646
- const info = await Prismic__namespace.Communication.validateSession(config.cookies, base);
647
- const profile = await getUserProfile(config.cookies, base).catch(() => null);
648
- if (profile == null ? void 0 : profile.shortId) {
649
- Prismic__namespace.PrismicSharedConfigManager.setProperties({
650
- shortId: profile.shortId,
651
- intercomHash: profile.intercomHash
652
- });
653
- }
654
- return { info, profile };
655
- } catch (e) {
656
- return null;
657
- }
658
- }
659
-
660
- async function loginOrBypass(base) {
661
- const user = await validateSessionAndGetProfile(base).catch((err) => console.log(err));
734
+ async function loginOrBypass(client) {
735
+ const user = await client.profile().catch(() => null);
662
736
  if (user) {
663
- const email = user.info.email;
737
+ const email = user.email;
664
738
  writeCheck(`Logged in as ${bold$1(email)}`);
665
739
  return user;
666
- } else {
667
- await Auth.login(base);
668
- const user2 = await validateSessionAndGetProfile(base);
669
- return user2;
670
740
  }
741
+ await Auth.login(client);
742
+ client.updateAuthenticationToken(Prismic.PrismicSharedConfigManager.getAuth());
743
+ const userAfterLogin = await client.profile();
744
+ return userAfterLogin;
671
745
  }
672
746
 
673
747
  const defaultSliceMachineVersion = "0.0.41";
674
- async function configureProject(cwd, base, repositoryDomainName, framework, sliceLibPath = [], tracking = true) {
675
- const spinner = spinner$1(`Configuring your ${framework.value} & Prismic project...`);
748
+ async function configureProject(client, cwd, repositoryDomainName, framework, sliceLibPath = [], tracking = true) {
749
+ const frameworkName = NodeUtils__namespace.Framework.fancyName(framework.value);
750
+ const spinner = spinner$1(`Configuring your ${frameworkName} and Prismic project...`);
676
751
  spinner.start();
677
752
  try {
678
753
  const manifest = NodeUtils__namespace.retrieveManifest(cwd);
679
754
  const packageJson = NodeUtils__namespace.retrieveJsonPackage(cwd);
680
755
  const sliceMachineVersionInstalled = getTheSliceMachineVersionInstalled(packageJson);
681
756
  const manifestAlreadyExistWithContent = manifest.exists && manifest.content;
757
+ const libs = manifest.content && manifest.content.libraries && manifest.content.libraries.length > 0 ? manifest.content.libraries : ["@/slices"];
682
758
  const manifestUpdated = {
683
759
  ...manifestAlreadyExistWithContent ? manifest.content : { _latest: sliceMachineVersionInstalled },
684
- apiEndpoint: Prismic__namespace.Endpoints.buildRepositoryEndpoint(base, repositoryDomainName),
685
- libraries: ["@/slices", ...sliceLibPath],
760
+ apiEndpoint: Prismic__namespace.Endpoints.buildRepositoryEndpoint(client.apisEndpoints.Wroom, repositoryDomainName),
761
+ libraries: [...libs, ...sliceLibPath],
686
762
  ...framework.manuallyAdded ? { framework: framework.value } : {},
687
763
  ...!tracking ? { tracking } : {}
688
764
  };
@@ -691,7 +767,7 @@ async function configureProject(cwd, base, repositoryDomainName, framework, slic
691
767
  else
692
768
  NodeUtils__namespace.patchManifest(cwd, manifestUpdated);
693
769
  const pathToSlicesFolder = NodeUtils__namespace.CustomPaths(cwd).library("slices").value();
694
- if (!NodeUtils__namespace.Files.exists(pathToSlicesFolder)) {
770
+ if (!NodeUtils__namespace.Files.exists(pathToSlicesFolder) && libs.includes("@/slices")) {
695
771
  NodeUtils__namespace.Files.mkdir(pathToSlicesFolder, { recursive: true });
696
772
  }
697
773
  NodeUtils__namespace.addJsonPackageSmScript(cwd);
@@ -726,10 +802,19 @@ const extractVersionNumberFromSemver = (semver) => {
726
802
  return null;
727
803
  };
728
804
 
729
- function displayFinalMessage(cwd) {
805
+ function displayFinalMessage(cwd, wasStarter, reponame, base) {
730
806
  const yarnLock = NodeUtils__namespace.Files.exists(NodeUtils__namespace.YarnLockPath(cwd));
731
807
  const command = `${yarnLock ? "yarn" : "npm"} run ${core.CONSTS.SCRIPT_NAME}`;
732
- console.log(`${white("\u25A0")} Run ${purple(command)} to now launch Slice Machine`);
808
+ console.log();
809
+ if (wasStarter) {
810
+ const repoUrl = new URL(base);
811
+ repoUrl.hostname = `${reponame}.${repoUrl.hostname}`;
812
+ const urlAsString = repoUrl.toString();
813
+ const message = `${white("\u25A0")} Start editing your content in Prismic ${purple(urlAsString)}`;
814
+ console.log(message);
815
+ } else {
816
+ console.log(`${white("\u25A0")} Run ${purple(command)} to launch Slice Machine and create your first Custom Type`);
817
+ }
733
818
  }
734
819
 
735
820
  const Dependencies = {
@@ -837,32 +922,237 @@ async function installLib(cwd, libGithubPath, branch = "HEAD") {
837
922
  }
838
923
  }
839
924
 
925
+ async function promptToPushSlices() {
926
+ return inquirer__default["default"].prompt([
927
+ {
928
+ type: "confirm",
929
+ name: "pushSlices",
930
+ default: false,
931
+ message: "Your repository already contains Slices. Do you want to continue pushing your local Slices?"
932
+ }
933
+ ]).then((res) => res.pushSlices);
934
+ }
935
+ async function promptToPushCustomTypes() {
936
+ return inquirer__default["default"].prompt([
937
+ {
938
+ type: "confirm",
939
+ name: "pushCustomTypes",
940
+ default: false,
941
+ message: "Your repository already contains Custom Types. Do you want to continue pushing your local Slices?"
942
+ }
943
+ ]).then((res) => res.pushCustomTypes);
944
+ }
945
+
946
+ async function updateVariationWithScreenshot(client, acl, screenshotPaths, sliceName, variation) {
947
+ const screenshot = screenshotPaths[variation.id];
948
+ if (!screenshot || !screenshot.path)
949
+ return Promise.resolve(variation);
950
+ return client.uploadScreenshot({
951
+ acl,
952
+ sliceName,
953
+ variationId: variation.id,
954
+ filePath: screenshot.path
955
+ }).then((screenshotUrl) => {
956
+ return {
957
+ ...variation,
958
+ imageUrl: screenshotUrl
959
+ };
960
+ }).catch((error) => {
961
+ writeError$1(`Couldn't upload screenshot slice: ${sliceName} - variation: ${variation.id}`);
962
+ writeError$1(error.message, "Full error:");
963
+ return variation;
964
+ });
965
+ }
966
+ async function updateSlicesWithScreenshots(client, acl, components) {
967
+ return Promise.all(components.map(async (component) => {
968
+ const { screenshotPaths, model } = component;
969
+ const variationsUpdated = await Promise.all(model.variations.map(async (variation) => updateVariationWithScreenshot(client, acl, screenshotPaths, model.id, variation)));
970
+ return {
971
+ ...model,
972
+ variations: variationsUpdated
973
+ };
974
+ }));
975
+ }
976
+
977
+ async function sendSlices(client, cwd, manifest) {
978
+ if (!manifest.libraries)
979
+ return Promise.resolve(false);
980
+ const libraries = Libraries__namespace.libraries(cwd, manifest.libraries);
981
+ const components = libraries.reduce((acc, lib) => {
982
+ return [...acc, ...lib.components];
983
+ }, []);
984
+ if (components.length === 0)
985
+ return Promise.resolve(false);
986
+ const remoteSlicesIds = await client.getSlices().then((slices) => slices.map((slice) => slice.id));
987
+ if (remoteSlicesIds.length) {
988
+ const pushAnyway = await promptToPushSlices();
989
+ if (pushAnyway === false)
990
+ return Promise.resolve(true);
991
+ }
992
+ const spinner = spinner$1("Pushing existing Slice models to your repository");
993
+ spinner.start();
994
+ const acl = await client.createAcl().catch((error) => {
995
+ writeError$1("Uploading screenshots for your slices failed, please contact us.");
996
+ writeError$1(error.message, "Full error:");
997
+ return null;
998
+ });
999
+ const models$1 = acl ? await updateSlicesWithScreenshots(client, acl, components) : components.map((component) => component.model);
1000
+ await Promise.all(models$1.map(async (model) => {
1001
+ const slice = models.Slices.fromSM(model);
1002
+ const promise = remoteSlicesIds.includes(slice.id) ? client.updateSlice(slice) : client.insertSlice(slice);
1003
+ return promise.catch((error) => {
1004
+ writeError$1(`Sending slice ${model.id} - ${error.message}`);
1005
+ throw error;
1006
+ });
1007
+ })).catch(() => {
1008
+ process.exit(1);
1009
+ });
1010
+ spinner.succeed();
1011
+ return Promise.resolve(true);
1012
+ }
1013
+
1014
+ function readLocalCustomTypes(cwd) {
1015
+ const customTypePaths = NodeUtils.CustomTypesPaths(cwd);
1016
+ const dir = customTypePaths.value();
1017
+ if (NodeUtils.Files.isDirectory(dir) === false)
1018
+ return [];
1019
+ const fileNames = NodeUtils.Files.readDirectory(dir);
1020
+ const files = fileNames.reduce((acc, fileName) => {
1021
+ const filePath = customTypePaths.customType(fileName).model();
1022
+ const json = NodeUtils.Files.safeReadJson(filePath);
1023
+ if (!json)
1024
+ return acc;
1025
+ const file = customtypes.CustomType.decode(json);
1026
+ if (file instanceof Error) {
1027
+ writeError$1(`reading ${filePath}: ${file.message}`);
1028
+ return acc;
1029
+ }
1030
+ if (Either$1.isLeft(file)) {
1031
+ writeError$1(`validating ${filePath}: ${JSON.stringify(file.left)}`);
1032
+ return acc;
1033
+ }
1034
+ return [...acc, file.right];
1035
+ }, []);
1036
+ return files;
1037
+ }
1038
+ async function sendCustomTypes(client, cwd) {
1039
+ const localCustomTypes = readLocalCustomTypes(cwd);
1040
+ if (localCustomTypes.length === 0)
1041
+ return Promise.resolve(false);
1042
+ const remoteCustomTypeIds = await client.getCustomTypes().then((customTypes) => customTypes.map((customType) => customType.id));
1043
+ if (remoteCustomTypeIds.length) {
1044
+ const shouldPush = await promptToPushCustomTypes();
1045
+ if (shouldPush === false)
1046
+ return Promise.resolve(false);
1047
+ }
1048
+ const spinner = spinner$1("Pushing existing custom types to your repository");
1049
+ spinner.start();
1050
+ await Promise.all(localCustomTypes.map(async (customType) => {
1051
+ const promise = remoteCustomTypeIds.includes(customType.id) ? client.updateCustomType(customType) : client.insertCustomType(customType);
1052
+ return promise.catch((error) => {
1053
+ writeError$1(`Sending custom type ${customType.id} - ${error.message}`);
1054
+ throw error;
1055
+ });
1056
+ })).catch(() => {
1057
+ process.exit(1);
1058
+ });
1059
+ spinner.succeed();
1060
+ return Promise.resolve(true);
1061
+ }
1062
+
1063
+ const SignatureFileReader = t__namespace.type({
1064
+ signature: t__namespace.string
1065
+ });
1066
+ async function readSignatureFile(cwd) {
1067
+ const pathToFile = path__default["default"].join(cwd, "documents", "index.json");
1068
+ return fs__default["default"].promises.readFile(pathToFile, "utf-8").then((res) => {
1069
+ const data = JSON.parse(res);
1070
+ return Either.getOrElseW(() => {
1071
+ throw new Error("Unable to read document signature file");
1072
+ })(SignatureFileReader.decode(data));
1073
+ });
1074
+ }
1075
+ async function readDocuments(cwd) {
1076
+ const documentDir = path__default["default"].join(cwd, "documents");
1077
+ const dirs = await lsdir(documentDir);
1078
+ const files = (await Promise.all(dirs.map((dir) => lsfiles(dir)))).flat();
1079
+ const documentObj = files.reduce((acc, file) => {
1080
+ const filename = path__default["default"].parse(file).name;
1081
+ const fileContent = fs__default["default"].readFileSync(file, "utf-8");
1082
+ const json = JSON.parse(fileContent);
1083
+ return { ...acc, [filename]: json };
1084
+ }, {});
1085
+ return documentObj;
1086
+ }
1087
+ async function sendDocuments(client, cwd) {
1088
+ const pathToDocuments = path__default["default"].join(cwd, "documents");
1089
+ const pathToSignatureFile = path__default["default"].join(pathToDocuments, "index.json");
1090
+ if (!fs__default["default"].existsSync(pathToSignatureFile))
1091
+ return Promise.resolve(false);
1092
+ const signatureObj = await readSignatureFile(cwd);
1093
+ const documents = await readDocuments(cwd);
1094
+ if (Object.keys(documents).length === 0)
1095
+ return Promise.resolve(false);
1096
+ const spinner = spinner$1("Pushing existing documents to your repository");
1097
+ spinner.start();
1098
+ return client.pushDocuments(signatureObj.signature, documents, SharedConfig.PrismicSharedConfigManager.get().cookies).then(() => {
1099
+ spinner.succeed();
1100
+ fs__default["default"].rmSync(pathToDocuments, { recursive: true, force: true });
1101
+ return true;
1102
+ }).catch((e) => {
1103
+ var _a;
1104
+ spinner.fail();
1105
+ if (((_a = e.response) == null ? void 0 : _a.data) === "Repository should not contain documents") {
1106
+ writeError$1("The selected repository is not empty, documents cannot be uploaded. Please choose an empty repository or delete the documents contained in your repository.");
1107
+ } else {
1108
+ writeError$1("Sending documents failed, please try again. If the problem persists, contact us.");
1109
+ writeError$1(`Full error: ${e.code || 500} - ${e.message}`);
1110
+ }
1111
+ process.exit(1);
1112
+ });
1113
+ }
1114
+
1115
+ async function sendStarterData(client, cwd, pushDocuments = true) {
1116
+ const manifest = NodeUtils.retrieveManifest(cwd);
1117
+ const documentsPath = path__default["default"].join(cwd, "documents");
1118
+ const hasDocuments = NodeUtils.Files.exists(documentsPath);
1119
+ if (manifest.exists === false || hasDocuments === false)
1120
+ return Promise.resolve(false);
1121
+ if (manifest.content)
1122
+ await sendSlices(client, cwd, manifest.content);
1123
+ await sendCustomTypes(client, cwd);
1124
+ if (!pushDocuments) {
1125
+ fs__default["default"].rmSync(documentsPath, { recursive: true, force: true });
1126
+ return Promise.resolve(true);
1127
+ }
1128
+ return sendDocuments(client, cwd);
1129
+ }
1130
+
840
1131
  async function init() {
841
1132
  const cwd = findArgument(process.argv, "cwd") || process.cwd();
842
- const base = findArgument(process.argv, "base") || core.CONSTS.DEFAULT_BASE;
1133
+ const mode = getApplicationMode(findArgument(process.argv, "mode")) || client.ApplicationMode.PROD;
843
1134
  const lib = findArgument(process.argv, "library");
844
1135
  const branch = findArgument(process.argv, "branch");
845
1136
  const isTrackingAvailable = findArgument(process.argv, "tracking") !== "false";
846
- const maybeRepositorySubdomain = findArgument(process.argv, "repository");
1137
+ const preSelectedRepository = findArgument(process.argv, "repository");
1138
+ const pushDocuments = !findFlag(process.argv, "no-docs");
847
1139
  Tracker.get().initialize("JfTfmHaATChc4xueS7RcCBsixI71dJIJ" , isTrackingAvailable);
848
- void Tracker.get().trackInitStart(maybeRepositorySubdomain);
1140
+ void Tracker.get().trackInitStart(preSelectedRepository);
1141
+ const client$1 = new InitClient(mode, null, Prismic__default["default"].PrismicSharedConfigManager.getAuth());
849
1142
  console.log(purple("You're about to configure Slicemachine... Press ctrl + C to cancel"));
850
1143
  validatePkg(cwd);
851
- const user = await loginOrBypass(base);
852
- if (!user)
853
- throw new Error("The user should be logged in!");
854
- if (user.profile) {
855
- Tracker.get().identifyUser(user.profile.shortId, user.profile.intercomHash);
856
- }
1144
+ const user = await loginOrBypass(client$1);
1145
+ Tracker.get().identifyUser(user.shortId, user.intercomHash);
857
1146
  void Tracker.get().trackInitIdentify();
858
- const config = Prismic__default["default"].PrismicSharedConfigManager.get();
859
1147
  const frameworkResult = await detectFramework(cwd);
860
- const repositoryDomainName = await chooseOrCreateARepository(cwd, frameworkResult.value, config.cookies, config.base, maybeRepositorySubdomain);
861
- Tracker.get().setRepository(repositoryDomainName);
862
- await installRequiredDependencies(cwd, frameworkResult.value);
1148
+ const repository = await chooseOrCreateARepository(client$1, cwd, frameworkResult.value, preSelectedRepository);
1149
+ Tracker.get().setRepository(repository);
1150
+ client$1.updateRepository(repository);
863
1151
  const sliceLibPath = lib ? await installLib(cwd, lib, branch) : void 0;
864
- await configureProject(cwd, base, repositoryDomainName, frameworkResult, sliceLibPath, isTrackingAvailable);
865
- displayFinalMessage(cwd);
1152
+ const wasStarter = await sendStarterData(client$1, cwd, pushDocuments);
1153
+ await configureProject(client$1, cwd, repository, frameworkResult, sliceLibPath, isTrackingAvailable);
1154
+ await installRequiredDependencies(cwd, frameworkResult.value, wasStarter);
1155
+ displayFinalMessage(cwd, wasStarter, repository, client$1.apisEndpoints.Wroom);
866
1156
  }
867
1157
  init().then(() => {
868
1158
  process.exit(0);