@uniformdev/cli 19.42.0 → 19.42.1-alpha.7

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 (2) hide show
  1. package/dist/index.mjs +213 -10
  2. package/package.json +10 -6
package/dist/index.mjs CHANGED
@@ -411,7 +411,9 @@ async function syncEngine({
411
411
  whatIf = false,
412
412
  // eslint-disable-next-line @typescript-eslint/no-empty-function
413
413
  log = () => {
414
- }
414
+ },
415
+ onBeforeCompareObjects,
416
+ onBeforeWriteObject
415
417
  }) {
416
418
  var _a, _b;
417
419
  const targetItems = /* @__PURE__ */ new Map();
@@ -445,18 +447,20 @@ async function syncEngine({
445
447
  }
446
448
  const actions = [];
447
449
  let sourceHasItems = false;
448
- for await (const sourceObject of source.objects) {
450
+ for await (let sourceObject of source.objects) {
449
451
  sourceHasItems = true;
450
452
  const ids = Array.isArray(sourceObject.id) ? sourceObject.id : [sourceObject.id];
451
453
  const targetObject = targetItems.get(ids[0]);
452
454
  const invalidTargetObjects = ids.map((i) => targetItems.get(i)).filter((o) => (o == null ? void 0 : o.object) !== (targetObject == null ? void 0 : targetObject.object));
453
455
  if (targetObject && invalidTargetObjects.length == 0) {
456
+ sourceObject = onBeforeCompareObjects ? await onBeforeCompareObjects(sourceObject, targetObject) : sourceObject;
454
457
  if (!compareContents(sourceObject, targetObject)) {
455
458
  if (mode === "createOrUpdate" || mode === "mirror") {
456
459
  const process2 = async (sourceObject2, targetObject2) => {
457
460
  if (!whatIf) {
458
461
  try {
459
- await target.writeObject(sourceObject2, targetObject2);
462
+ const finalSourceObject = onBeforeWriteObject ? await onBeforeWriteObject(sourceObject2, targetObject2) : sourceObject2;
463
+ await target.writeObject(finalSourceObject, targetObject2);
460
464
  } catch (e) {
461
465
  throw new SyncEngineError(e, sourceObject2);
462
466
  }
@@ -478,7 +482,8 @@ async function syncEngine({
478
482
  const process2 = async (sourceObject2, id) => {
479
483
  if (!whatIf) {
480
484
  try {
481
- await target.writeObject(sourceObject2);
485
+ const finalSourceObject = onBeforeWriteObject ? await onBeforeWriteObject(sourceObject2) : sourceObject2;
486
+ await target.writeObject(finalSourceObject);
482
487
  } catch (e) {
483
488
  throw new SyncEngineError(e, sourceObject2);
484
489
  }
@@ -1456,6 +1461,180 @@ var CompositionPublishModule = {
1456
1461
 
1457
1462
  // src/commands/canvas/commands/composition/pull.ts
1458
1463
  import { UncachedCanvasClient as UncachedCanvasClient10 } from "@uniformdev/canvas";
1464
+
1465
+ // src/files/index.ts
1466
+ import { preferredType } from "@thi.ng/mime";
1467
+ import { FILE_READY_STATE, getFileNameFromUrl } from "@uniformdev/files-sdk";
1468
+ import { createHash } from "crypto";
1469
+ import fsj from "fs-jetpack";
1470
+ import sizeOf from "image-size";
1471
+ import PQueue from "p-queue";
1472
+ import { join as join2 } from "path";
1473
+ var FILES_DIRECTORY_NAME = "files";
1474
+ var urlToHash = (url) => {
1475
+ const hash = createHash("sha256");
1476
+ hash.update(url);
1477
+ return hash.digest("hex");
1478
+ };
1479
+ var urlToFileName = (url) => {
1480
+ const fileName = urlToHash(url);
1481
+ const fileNameChunks = url.split(".");
1482
+ const fileExtension = fileNameChunks.length > 1 ? fileNameChunks.at(-1) : "";
1483
+ return `${fileName}${fileExtension ? `.${fileExtension}` : ""}`;
1484
+ };
1485
+ var extractAndDownloadUniformFilesForObject = async (object, options) => {
1486
+ const objectAsString = JSON.stringify(object);
1487
+ const uniformFileUrlMatches = objectAsString.matchAll(
1488
+ /"(https:\/\/(.*)?img\.uniform\.(rocks|global)\/(.*?))"/g
1489
+ );
1490
+ if (uniformFileUrlMatches) {
1491
+ const fileDownloadQueue = new PQueue({ concurrency: 10 });
1492
+ for (const match of uniformFileUrlMatches) {
1493
+ const url = match[1];
1494
+ fileDownloadQueue.add(async () => {
1495
+ try {
1496
+ const fileName = urlToFileName(url);
1497
+ const fileAlreadyExists = await fsj.existsAsync(
1498
+ join2(options.directory, FILES_DIRECTORY_NAME, fileName)
1499
+ );
1500
+ if (fileAlreadyExists) {
1501
+ return;
1502
+ }
1503
+ const response = await fetch(url);
1504
+ if (!response.ok) {
1505
+ return;
1506
+ }
1507
+ const fileBuffer = await response.arrayBuffer();
1508
+ await fsj.writeAsync(
1509
+ join2(options.directory, FILES_DIRECTORY_NAME, fileName),
1510
+ Buffer.from(fileBuffer)
1511
+ );
1512
+ } catch {
1513
+ console.warn(`Failed to download file ${url}`);
1514
+ }
1515
+ });
1516
+ }
1517
+ await fileDownloadQueue.onIdle();
1518
+ }
1519
+ return object;
1520
+ };
1521
+ var extractAndUploadUniformFilesForObject = async (object, options) => {
1522
+ let objectAsString = JSON.stringify(object);
1523
+ const uniformFileUrlMatches = objectAsString.matchAll(
1524
+ /"(https:\/\/(.*)?img\.uniform\.(rocks|global)\/(.*?))"/g
1525
+ );
1526
+ if (uniformFileUrlMatches) {
1527
+ const fileUploadQueue = new PQueue({ concurrency: 3 });
1528
+ for (const match of uniformFileUrlMatches) {
1529
+ const url = match[1];
1530
+ const hash = urlToHash(url);
1531
+ fileUploadQueue.add(async () => {
1532
+ try {
1533
+ const fileAlreadyExistsChecks = await Promise.all([
1534
+ options.fileClient.getFile({ projectId: options.projectId, url }).catch(() => null),
1535
+ options.fileClient.getFile({ projectId: options.projectId, sourceId: hash }).catch(() => null)
1536
+ ]);
1537
+ if (fileAlreadyExistsChecks.some((check) => check !== null)) {
1538
+ return;
1539
+ }
1540
+ const localFileName = urlToFileName(url);
1541
+ const fileExistsLocally = await fsj.existsAsync(
1542
+ join2(options.directory, FILES_DIRECTORY_NAME, localFileName)
1543
+ );
1544
+ if (!fileExistsLocally) {
1545
+ console.warn(`Skipping file ${url} as we couldn't find a local copy`);
1546
+ return;
1547
+ }
1548
+ const fileBuffer = await fsj.readAsync(
1549
+ join2(options.directory, FILES_DIRECTORY_NAME, localFileName),
1550
+ "buffer"
1551
+ );
1552
+ if (!fileBuffer) {
1553
+ console.warn(`Skipping file ${url} as we couldn't read it`);
1554
+ return;
1555
+ }
1556
+ const fileName = getFileNameFromUrl(url);
1557
+ const { width, height } = (() => {
1558
+ try {
1559
+ return sizeOf(fileBuffer);
1560
+ } catch {
1561
+ return {
1562
+ width: void 0,
1563
+ height: void 0
1564
+ };
1565
+ }
1566
+ })();
1567
+ const { id, method, uploadUrl } = await options.fileClient.createNewProjectFile({
1568
+ name: fileName,
1569
+ mediaType: preferredType(url.split(".").at(-1) ?? ""),
1570
+ size: fileBuffer.length,
1571
+ width,
1572
+ height,
1573
+ projectId: options.projectId,
1574
+ sourceId: hash
1575
+ });
1576
+ const uploadResponse = await fetch(uploadUrl, {
1577
+ method,
1578
+ body: fileBuffer
1579
+ });
1580
+ if (!uploadResponse.ok) {
1581
+ console.warn(`Failed to upload file ${url}`);
1582
+ return;
1583
+ }
1584
+ const checkForFile = async () => {
1585
+ const file = await options.fileClient.getFile({ id });
1586
+ if (!file || file.state !== FILE_READY_STATE) {
1587
+ await new Promise((resolve) => setTimeout(resolve, 500));
1588
+ return checkForFile();
1589
+ }
1590
+ return file.url;
1591
+ };
1592
+ const abortTimeout = setTimeout(() => {
1593
+ throw new Error(`Failed to upload file ${url}`);
1594
+ }, 1e4);
1595
+ const uploadedFileUrl = await checkForFile();
1596
+ clearTimeout(abortTimeout);
1597
+ objectAsString = objectAsString.replaceAll(`"${url}"`, `"${uploadedFileUrl}"`);
1598
+ } catch {
1599
+ console.warn(`Failed to upload file ${url}`);
1600
+ }
1601
+ });
1602
+ }
1603
+ await fileUploadQueue.onIdle();
1604
+ }
1605
+ return JSON.parse(objectAsString);
1606
+ };
1607
+ var swapOutUniformFileUrlsForTargetProject = async (object, options) => {
1608
+ let objectAsString = JSON.stringify(object);
1609
+ const uniformFileUrlMatches = objectAsString.matchAll(
1610
+ /"(https:\/\/(.*)?img\.uniform\.(rocks|global)\/(.*?))"/g
1611
+ );
1612
+ if (uniformFileUrlMatches) {
1613
+ const fileUrlReplacementQueue = new PQueue({ concurrency: 3 });
1614
+ for (const match of uniformFileUrlMatches) {
1615
+ const url = match[1];
1616
+ const hash = urlToHash(url);
1617
+ fileUrlReplacementQueue.add(async () => {
1618
+ try {
1619
+ const fileAlreadyExistsChecks = await Promise.all([
1620
+ options.fileClient.getFile({ projectId: options.projectId, url }).catch(() => null),
1621
+ options.fileClient.getFile({ projectId: options.projectId, sourceId: hash }).catch(() => null)
1622
+ ]);
1623
+ const file = fileAlreadyExistsChecks.find((check) => check !== null);
1624
+ if (!file) {
1625
+ return;
1626
+ }
1627
+ objectAsString = objectAsString.replaceAll(`"${url}"`, `"${file.url}"`);
1628
+ } catch {
1629
+ }
1630
+ });
1631
+ }
1632
+ await fileUrlReplacementQueue.onIdle();
1633
+ }
1634
+ return JSON.parse(objectAsString);
1635
+ };
1636
+
1637
+ // src/commands/canvas/commands/composition/pull.ts
1459
1638
  var CompositionPullModule = {
1460
1639
  command: "pull <directory>",
1461
1640
  describe: "Pulls all compositions to local files in a directory",
@@ -1542,13 +1721,19 @@ var CompositionPullModule = {
1542
1721
  target,
1543
1722
  mode,
1544
1723
  whatIf,
1545
- log: createSyncEngineConsoleLogger({ diffMode })
1724
+ log: createSyncEngineConsoleLogger({ diffMode }),
1725
+ onBeforeWriteObject: async (sourceObject) => {
1726
+ return extractAndDownloadUniformFilesForObject(sourceObject, {
1727
+ directory
1728
+ });
1729
+ }
1546
1730
  });
1547
1731
  }
1548
1732
  };
1549
1733
 
1550
1734
  // src/commands/canvas/commands/composition/push.ts
1551
1735
  import { UncachedCanvasClient as UncachedCanvasClient11 } from "@uniformdev/canvas";
1736
+ import { FileClient as FileClient2 } from "@uniformdev/files-sdk";
1552
1737
  var CompositionPushModule = {
1553
1738
  command: "push <directory>",
1554
1739
  describe: "Pushes all compositions from files in a directory to Uniform Canvas",
@@ -1618,12 +1803,26 @@ var CompositionPushModule = {
1618
1803
  });
1619
1804
  }
1620
1805
  const target = createComponentInstanceEngineDataSource({ client, state, onlyCompositions, onlyPatterns });
1806
+ const fileClient = new FileClient2({ apiKey, apiHost, fetch: fetch3, projectId });
1621
1807
  await syncEngine({
1622
1808
  source,
1623
1809
  target,
1624
1810
  mode,
1625
1811
  whatIf,
1626
- log: createSyncEngineConsoleLogger({ diffMode })
1812
+ log: createSyncEngineConsoleLogger({ diffMode }),
1813
+ onBeforeCompareObjects: async (sourceObject) => {
1814
+ return swapOutUniformFileUrlsForTargetProject(sourceObject, {
1815
+ fileClient,
1816
+ projectId
1817
+ });
1818
+ },
1819
+ onBeforeWriteObject: async (sourceObject) => {
1820
+ return extractAndUploadUniformFilesForObject(sourceObject, {
1821
+ directory,
1822
+ fileClient,
1823
+ projectId
1824
+ });
1825
+ }
1627
1826
  });
1628
1827
  }
1629
1828
  };
@@ -3791,8 +3990,10 @@ var package_default = {
3791
3990
  format: 'prettier --write "src/**/*.{js,ts,tsx}"'
3792
3991
  },
3793
3992
  dependencies: {
3993
+ "@thi.ng/mime": "^2.2.23",
3794
3994
  "@uniformdev/canvas": "workspace:*",
3795
3995
  "@uniformdev/context": "workspace:*",
3996
+ "@uniformdev/files-sdk": "workspace:*",
3796
3997
  "@uniformdev/project-map": "workspace:*",
3797
3998
  "@uniformdev/redirect": "workspace:*",
3798
3999
  colorette: "2.0.20",
@@ -3805,6 +4006,7 @@ var package_default = {
3805
4006
  graphql: "16.7.1",
3806
4007
  "graphql-request": "6.1.0",
3807
4008
  "https-proxy-agent": "^7.0.0",
4009
+ "image-size": "^1.0.2",
3808
4010
  inquirer: "9.2.9",
3809
4011
  "isomorphic-git": "1.24.5",
3810
4012
  "isomorphic-unfetch": "^3.1.0",
@@ -3813,6 +4015,7 @@ var package_default = {
3813
4015
  "lodash.isequalwith": "^4.4.0",
3814
4016
  open: "9.1.0",
3815
4017
  ora: "6.3.1",
4018
+ "p-queue": "7.3.4",
3816
4019
  "posthog-node": "3.1.1",
3817
4020
  slugify: "1.6.6",
3818
4021
  "update-check": "^1.5.4",
@@ -4150,7 +4353,7 @@ ${err.message}`);
4150
4353
  // src/projects/cloneStarter.ts
4151
4354
  import crypto2 from "crypto";
4152
4355
  import fs3 from "fs";
4153
- import fsj from "fs-jetpack";
4356
+ import fsj2 from "fs-jetpack";
4154
4357
  import * as git from "isomorphic-git";
4155
4358
  import * as http from "isomorphic-git/http/node/index.js";
4156
4359
  import os from "os";
@@ -4181,7 +4384,7 @@ async function cloneStarter({
4181
4384
  throw new Error(`"${targetDir}" is not empty`);
4182
4385
  }
4183
4386
  const starterDir = path.join(cloneDir, ...pathSegments);
4184
- fsj.copy(starterDir, targetDir, { overwrite: true });
4387
+ fsj2.copy(starterDir, targetDir, { overwrite: true });
4185
4388
  if (dotEnvFile) {
4186
4389
  fs3.writeFileSync(path.resolve(targetDir, ".env"), dotEnvFile, "utf-8");
4187
4390
  }
@@ -6085,7 +6288,7 @@ async function checkForUpdateMiddleware() {
6085
6288
 
6086
6289
  // src/middleware/checkLocalDepsVersionsMiddleware.ts
6087
6290
  import { magenta, red as red6 } from "colorette";
6088
- import { join as join2 } from "path";
6291
+ import { join as join3 } from "path";
6089
6292
 
6090
6293
  // src/fs.ts
6091
6294
  import { promises as fs5 } from "fs";
@@ -6124,7 +6327,7 @@ var checkLocalDepsVersions = async (args) => {
6124
6327
  try {
6125
6328
  let isOutside = false;
6126
6329
  let warning = `${magenta("Warning:")} Installed Uniform packages should be the same version`;
6127
- const localPackages = await tryReadJSON(join2(process.cwd(), "package.json"));
6330
+ const localPackages = await tryReadJSON(join3(process.cwd(), "package.json"));
6128
6331
  if (!localPackages)
6129
6332
  return;
6130
6333
  let firstVersion;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/cli",
3
- "version": "19.42.0",
3
+ "version": "19.42.1-alpha.7+1380aadd7",
4
4
  "description": "Uniform command line interface tool",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./cli.js",
@@ -16,10 +16,12 @@
16
16
  "format": "prettier --write \"src/**/*.{js,ts,tsx}\""
17
17
  },
18
18
  "dependencies": {
19
- "@uniformdev/canvas": "19.42.0",
20
- "@uniformdev/context": "19.42.0",
21
- "@uniformdev/project-map": "19.42.0",
22
- "@uniformdev/redirect": "19.42.0",
19
+ "@thi.ng/mime": "^2.2.23",
20
+ "@uniformdev/canvas": "19.42.1-alpha.7+1380aadd7",
21
+ "@uniformdev/context": "19.42.1-alpha.7+1380aadd7",
22
+ "@uniformdev/files-sdk": "19.37.0",
23
+ "@uniformdev/project-map": "19.42.1-alpha.7+1380aadd7",
24
+ "@uniformdev/redirect": "19.42.1-alpha.7+1380aadd7",
23
25
  "colorette": "2.0.20",
24
26
  "cosmiconfig": "8.2.0",
25
27
  "cosmiconfig-typescript-loader": "5.0.0",
@@ -30,6 +32,7 @@
30
32
  "graphql": "16.7.1",
31
33
  "graphql-request": "6.1.0",
32
34
  "https-proxy-agent": "^7.0.0",
35
+ "image-size": "^1.0.2",
33
36
  "inquirer": "9.2.9",
34
37
  "isomorphic-git": "1.24.5",
35
38
  "isomorphic-unfetch": "^3.1.0",
@@ -38,6 +41,7 @@
38
41
  "lodash.isequalwith": "^4.4.0",
39
42
  "open": "9.1.0",
40
43
  "ora": "6.3.1",
44
+ "p-queue": "7.3.4",
41
45
  "posthog-node": "3.1.1",
42
46
  "slugify": "1.6.6",
43
47
  "update-check": "^1.5.4",
@@ -62,5 +66,5 @@
62
66
  "publishConfig": {
63
67
  "access": "public"
64
68
  },
65
- "gitHead": "33ed87d09bfb50c8557c6bcf4eb232c76f7c99d8"
69
+ "gitHead": "1380aadd7c71f6f120f933a40e73e113518e3716"
66
70
  }