@plasmicapp/cli 0.1.162

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 (162) hide show
  1. package/.eslintrc.js +61 -0
  2. package/.idea/cli.iml +11 -0
  3. package/.idea/misc.xml +6 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/vcs.xml +6 -0
  6. package/README +16 -0
  7. package/README.internal +46 -0
  8. package/README.md +17 -0
  9. package/build.sh +8 -0
  10. package/dist/__mocks__/api.d.ts +16 -0
  11. package/dist/__mocks__/api.js +297 -0
  12. package/dist/__tests__/code-utils-spec.d.ts +1 -0
  13. package/dist/__tests__/code-utils-spec.js +838 -0
  14. package/dist/__tests__/ftue-spec.d.ts +1 -0
  15. package/dist/__tests__/ftue-spec.js +39 -0
  16. package/dist/__tests__/project-api-token-spec.d.ts +1 -0
  17. package/dist/__tests__/project-api-token-spec.js +147 -0
  18. package/dist/__tests__/versioned-sync-spec.d.ts +1 -0
  19. package/dist/__tests__/versioned-sync-spec.js +145 -0
  20. package/dist/actions/auth.d.ts +8 -0
  21. package/dist/actions/auth.js +47 -0
  22. package/dist/actions/fix-imports.d.ts +4 -0
  23. package/dist/actions/fix-imports.js +25 -0
  24. package/dist/actions/init.d.ts +62 -0
  25. package/dist/actions/init.js +460 -0
  26. package/dist/actions/project-token.d.ts +6 -0
  27. package/dist/actions/project-token.js +42 -0
  28. package/dist/actions/sync-components.d.ts +10 -0
  29. package/dist/actions/sync-components.js +242 -0
  30. package/dist/actions/sync-global-variants.d.ts +3 -0
  31. package/dist/actions/sync-global-variants.js +89 -0
  32. package/dist/actions/sync-icons.d.ts +7 -0
  33. package/dist/actions/sync-icons.js +92 -0
  34. package/dist/actions/sync-images.d.ts +6 -0
  35. package/dist/actions/sync-images.js +137 -0
  36. package/dist/actions/sync-styles.d.ts +3 -0
  37. package/dist/actions/sync-styles.js +58 -0
  38. package/dist/actions/sync.d.ts +25 -0
  39. package/dist/actions/sync.js +417 -0
  40. package/dist/actions/upload-bundle.d.ts +15 -0
  41. package/dist/actions/upload-bundle.js +28 -0
  42. package/dist/actions/watch.d.ts +14 -0
  43. package/dist/actions/watch.js +90 -0
  44. package/dist/api.d.ts +182 -0
  45. package/dist/api.js +202 -0
  46. package/dist/deps.d.ts +2 -0
  47. package/dist/deps.js +20 -0
  48. package/dist/index.d.ts +7 -0
  49. package/dist/index.js +247 -0
  50. package/dist/lib.d.ts +10 -0
  51. package/dist/lib.js +23 -0
  52. package/dist/migrations/0.1.110-fileLocks.d.ts +2 -0
  53. package/dist/migrations/0.1.110-fileLocks.js +15 -0
  54. package/dist/migrations/0.1.143-ensureImportModuleType.d.ts +2 -0
  55. package/dist/migrations/0.1.143-ensureImportModuleType.js +12 -0
  56. package/dist/migrations/0.1.146-addReactRuntime.d.ts +2 -0
  57. package/dist/migrations/0.1.146-addReactRuntime.js +10 -0
  58. package/dist/migrations/0.1.27-migrateInit.d.ts +1 -0
  59. package/dist/migrations/0.1.27-migrateInit.js +8 -0
  60. package/dist/migrations/0.1.28-tsToTsx.d.ts +3 -0
  61. package/dist/migrations/0.1.28-tsToTsx.js +33 -0
  62. package/dist/migrations/0.1.31-ensureProjectIcons.d.ts +2 -0
  63. package/dist/migrations/0.1.31-ensureProjectIcons.js +12 -0
  64. package/dist/migrations/0.1.42-ensureVersion.d.ts +2 -0
  65. package/dist/migrations/0.1.42-ensureVersion.js +12 -0
  66. package/dist/migrations/0.1.57-ensureJsBundleThemes.d.ts +2 -0
  67. package/dist/migrations/0.1.57-ensureJsBundleThemes.js +12 -0
  68. package/dist/migrations/0.1.64-imageFiles.d.ts +2 -0
  69. package/dist/migrations/0.1.64-imageFiles.js +17 -0
  70. package/dist/migrations/0.1.95-componentType.d.ts +2 -0
  71. package/dist/migrations/0.1.95-componentType.js +16 -0
  72. package/dist/migrations/migrations.d.ts +10 -0
  73. package/dist/migrations/migrations.js +119 -0
  74. package/dist/plasmic.schema.json +463 -0
  75. package/dist/test-common/fixtures.d.ts +13 -0
  76. package/dist/test-common/fixtures.js +165 -0
  77. package/dist/tsconfig-transform.json +68 -0
  78. package/dist/utils/auth-utils.d.ts +31 -0
  79. package/dist/utils/auth-utils.js +236 -0
  80. package/dist/utils/checksum.d.ts +4 -0
  81. package/dist/utils/checksum.js +63 -0
  82. package/dist/utils/code-utils.d.ts +46 -0
  83. package/dist/utils/code-utils.js +457 -0
  84. package/dist/utils/config-utils.d.ts +271 -0
  85. package/dist/utils/config-utils.js +178 -0
  86. package/dist/utils/envdetect.d.ts +4 -0
  87. package/dist/utils/envdetect.js +42 -0
  88. package/dist/utils/error.d.ts +14 -0
  89. package/dist/utils/error.js +42 -0
  90. package/dist/utils/file-utils.d.ts +71 -0
  91. package/dist/utils/file-utils.js +433 -0
  92. package/dist/utils/get-context.d.ts +40 -0
  93. package/dist/utils/get-context.js +339 -0
  94. package/dist/utils/help.d.ts +2 -0
  95. package/dist/utils/help.js +56 -0
  96. package/dist/utils/lang-utils.d.ts +10 -0
  97. package/dist/utils/lang-utils.js +52 -0
  98. package/dist/utils/npm-utils.d.ts +28 -0
  99. package/dist/utils/npm-utils.js +215 -0
  100. package/dist/utils/prompts.d.ts +6 -0
  101. package/dist/utils/prompts.js +23 -0
  102. package/dist/utils/resolve-utils.d.ts +13 -0
  103. package/dist/utils/resolve-utils.js +198 -0
  104. package/dist/utils/semver.d.ts +34 -0
  105. package/dist/utils/semver.js +61 -0
  106. package/dist/utils/test-utils.d.ts +22 -0
  107. package/dist/utils/test-utils.js +106 -0
  108. package/dist/utils/user-utils.d.ts +7 -0
  109. package/dist/utils/user-utils.js +48 -0
  110. package/jest.config.js +6 -0
  111. package/package.json +80 -0
  112. package/src/__mocks__/api.ts +394 -0
  113. package/src/__tests__/code-utils-spec.ts +881 -0
  114. package/src/__tests__/ftue-spec.ts +43 -0
  115. package/src/__tests__/project-api-token-spec.ts +208 -0
  116. package/src/__tests__/versioned-sync-spec.ts +176 -0
  117. package/src/actions/auth.ts +43 -0
  118. package/src/actions/fix-imports.ts +13 -0
  119. package/src/actions/init.ts +638 -0
  120. package/src/actions/project-token.ts +36 -0
  121. package/src/actions/sync-components.ts +405 -0
  122. package/src/actions/sync-global-variants.ts +129 -0
  123. package/src/actions/sync-icons.ts +135 -0
  124. package/src/actions/sync-images.ts +191 -0
  125. package/src/actions/sync-styles.ts +71 -0
  126. package/src/actions/sync.ts +747 -0
  127. package/src/actions/upload-bundle.ts +38 -0
  128. package/src/actions/watch.ts +95 -0
  129. package/src/api.ts +407 -0
  130. package/src/deps.ts +18 -0
  131. package/src/index.ts +300 -0
  132. package/src/lib.ts +10 -0
  133. package/src/migrations/0.1.110-fileLocks.ts +16 -0
  134. package/src/migrations/0.1.146-addReactRuntime.ts +8 -0
  135. package/src/migrations/0.1.27-migrateInit.ts +4 -0
  136. package/src/migrations/0.1.28-tsToTsx.ts +37 -0
  137. package/src/migrations/0.1.31-ensureProjectIcons.ts +10 -0
  138. package/src/migrations/0.1.42-ensureVersion.ts +10 -0
  139. package/src/migrations/0.1.57-ensureJsBundleThemes.ts +10 -0
  140. package/src/migrations/0.1.64-imageFiles.ts +15 -0
  141. package/src/migrations/0.1.95-componentType.ts +14 -0
  142. package/src/migrations/migrations.ts +147 -0
  143. package/src/test-common/fixtures.ts +178 -0
  144. package/src/utils/auth-utils.ts +276 -0
  145. package/src/utils/checksum.ts +106 -0
  146. package/src/utils/code-utils.ts +656 -0
  147. package/src/utils/config-utils.ts +551 -0
  148. package/src/utils/envdetect.ts +39 -0
  149. package/src/utils/error.ts +36 -0
  150. package/src/utils/file-utils.ts +526 -0
  151. package/src/utils/get-context.ts +451 -0
  152. package/src/utils/help.ts +75 -0
  153. package/src/utils/lang-utils.ts +52 -0
  154. package/src/utils/npm-utils.ts +223 -0
  155. package/src/utils/prompts.ts +22 -0
  156. package/src/utils/resolve-utils.ts +245 -0
  157. package/src/utils/semver.ts +67 -0
  158. package/src/utils/test-utils.ts +116 -0
  159. package/src/utils/user-utils.ts +37 -0
  160. package/testData/fixImports_plasmic.json +66 -0
  161. package/tsconfig-transform.json +68 -0
  162. package/tsconfig.json +67 -0
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.TempRepo = void 0;
26
+ const fs_1 = __importDefault(require("fs"));
27
+ const path = __importStar(require("path"));
28
+ const tmp = __importStar(require("tmp"));
29
+ const config_utils_1 = require("../utils/config-utils");
30
+ const file_utils_1 = require("./file-utils");
31
+ class TempRepo {
32
+ constructor() {
33
+ this.tmpDir = tmp.dirSync({ unsafeCleanup: true });
34
+ }
35
+ destroy() {
36
+ this.tmpDir.removeCallback();
37
+ }
38
+ resolveFile(relativePath) {
39
+ return path.resolve(this.tmpDir.name, relativePath);
40
+ }
41
+ readFile(relativePath) {
42
+ const absPath = this.resolveFile(relativePath);
43
+ const buf = file_utils_1.readFileText(absPath);
44
+ return buf.toString();
45
+ }
46
+ writeFile(relativePath, data) {
47
+ const absPath = this.resolveFile(relativePath);
48
+ file_utils_1.writeFileText(absPath, data);
49
+ }
50
+ deleteFile(relativePath) {
51
+ const absPath = this.resolveFile(relativePath);
52
+ file_utils_1.deleteFileBuffered(absPath);
53
+ }
54
+ checkFile(relativePath) {
55
+ const absPath = this.resolveFile(relativePath);
56
+ try {
57
+ const stats = fs_1.default.statSync(absPath);
58
+ return !!stats ? true : false;
59
+ }
60
+ catch (e) {
61
+ return false;
62
+ }
63
+ }
64
+ getComponentFileContents(projectId, componentId) {
65
+ const plasmicJson = JSON.parse(this.readFile(config_utils_1.CONFIG_FILE_NAME));
66
+ const srcDir = plasmicJson.srcDir;
67
+ const projectConfig = plasmicJson.projects.find((p) => p.projectId === projectId);
68
+ if (!projectConfig) {
69
+ return;
70
+ }
71
+ const componentConfig = projectConfig.components.find((c) => c.id === componentId);
72
+ if (!componentConfig) {
73
+ return;
74
+ }
75
+ const data = this.readFile(path.join(srcDir, componentConfig.renderModuleFilePath));
76
+ return data;
77
+ }
78
+ plasmicAuthPath() {
79
+ return this.resolveFile(config_utils_1.AUTH_FILE_NAME);
80
+ }
81
+ writePlasmicAuth(json) {
82
+ this.writeFile(config_utils_1.AUTH_FILE_NAME, JSON.stringify(json));
83
+ }
84
+ deletePlasmicAuth() {
85
+ this.deleteFile(config_utils_1.AUTH_FILE_NAME);
86
+ }
87
+ plasmicJsonPath() {
88
+ return this.resolveFile(config_utils_1.CONFIG_FILE_NAME);
89
+ }
90
+ readPlasmicJson() {
91
+ return JSON.parse(this.readFile(config_utils_1.CONFIG_FILE_NAME));
92
+ }
93
+ writePlasmicJson(json) {
94
+ this.writeFile(config_utils_1.CONFIG_FILE_NAME, JSON.stringify(json));
95
+ }
96
+ deletePlasmicJson() {
97
+ this.deleteFile(config_utils_1.CONFIG_FILE_NAME);
98
+ }
99
+ plasmicLoaderJsonPath() {
100
+ return this.resolveFile(config_utils_1.LOADER_CONFIG_FILE_NAME);
101
+ }
102
+ readPlasmicLoaderJson() {
103
+ return JSON.parse(this.readFile(config_utils_1.LOADER_CONFIG_FILE_NAME));
104
+ }
105
+ }
106
+ exports.TempRepo = TempRepo;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Provide a standardized way to ask user to continue
3
+ * @param message
4
+ * @param yes - If true, always return true without prompting.
5
+ * @param default - Override the default value returned if the user presses enter
6
+ */
7
+ export declare function confirmWithUser(message: string, yes?: boolean, defaultAnswer?: "y" | "n"): Promise<boolean>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.confirmWithUser = void 0;
16
+ const inquirer_1 = __importDefault(require("inquirer"));
17
+ const deps_1 = require("../deps");
18
+ /**
19
+ * Provide a standardized way to ask user to continue
20
+ * @param message
21
+ * @param yes - If true, always return true without prompting.
22
+ * @param default - Override the default value returned if the user presses enter
23
+ */
24
+ function confirmWithUser(message, yes, defaultAnswer) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ if (process.env.QUIET) {
27
+ return true;
28
+ }
29
+ if (!!yes) {
30
+ if (!process.env.QUIET) {
31
+ deps_1.logger.info(`${message} (Y/n): y`);
32
+ }
33
+ return true;
34
+ }
35
+ defaultAnswer = defaultAnswer !== null && defaultAnswer !== void 0 ? defaultAnswer : "y";
36
+ const isDefaultYes = defaultAnswer === "y";
37
+ const choices = `(${isDefaultYes ? "Y" : "y"}/${isDefaultYes ? "n" : "N"})`;
38
+ const res = yield inquirer_1.default.prompt([
39
+ {
40
+ name: "continue",
41
+ message: `${message} ${choices}`,
42
+ default: defaultAnswer,
43
+ },
44
+ ]);
45
+ return ["y", "yes"].includes(res.continue.toLowerCase());
46
+ });
47
+ }
48
+ exports.confirmWithUser = confirmWithUser;
package/jest.config.js ADDED
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ preset: "ts-jest/presets/js-with-babel",
3
+ testEnvironment: "node",
4
+ testPathIgnorePatterns: ["/node_modules/", "/dist/"],
5
+ testRunner: "jest-circus/runner",
6
+ };
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@plasmicapp/cli",
3
+ "version": "0.1.162",
4
+ "description": "plasmic cli for syncing local code with Plasmic designs",
5
+ "engines": {
6
+ "node": ">=12"
7
+ },
8
+ "main": "./dist/lib.js",
9
+ "types": "./dist/lib.d.ts",
10
+ "bin": {
11
+ "plasmic": "./dist/index.js"
12
+ },
13
+ "scripts": {
14
+ "wtest": "jest --colors --watchAll",
15
+ "test": "jest --colors",
16
+ "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
17
+ "build": "bash build.sh",
18
+ "plasmic": "ts-node src/index.ts",
19
+ "prepare": "yarn build"
20
+ },
21
+ "devDependencies": {
22
+ "@babel/preset-typescript": "^7.12.1",
23
+ "@plasmicapp/react-web": "^0.2.18",
24
+ "@types/findup-sync": "^2.0.2",
25
+ "@types/glob": "^7.1.3",
26
+ "@types/inquirer": "^6.5.0",
27
+ "@types/jest": "^26.0.4",
28
+ "@types/latest-version": "^4.0.1",
29
+ "@types/lodash": "^4.14.157",
30
+ "@types/node": "^14.0.23",
31
+ "@types/pako": "^1.0.1",
32
+ "@types/prettier": "^2.0.2",
33
+ "@types/semver": "^7.3.1",
34
+ "@types/tmp": "^0.2.0",
35
+ "@types/update-notifier": "^4.1.0",
36
+ "@types/uuid": "^8.3.0",
37
+ "@types/wrap-ansi": "^3.0.0",
38
+ "@types/yargs": "^15.0.5",
39
+ "@typescript-eslint/eslint-plugin": "^3.8.0",
40
+ "@typescript-eslint/parser": "^3.8.0",
41
+ "eslint": "^7.7.0",
42
+ "jest": "^26.1.0",
43
+ "jest-circus": "^26.1.0",
44
+ "tmp": "^0.2.1",
45
+ "ts-jest": "^26.1.2",
46
+ "ts-node": "^8.10.2",
47
+ "typescript-json-schema": "^0.45.0"
48
+ },
49
+ "dependencies": {
50
+ "@babel/core": "^7.12.3",
51
+ "@babel/generator": "^7.12.1",
52
+ "@plasmicapp/code-merger": "^0.0.31",
53
+ "@sentry/node": "^5.19.2",
54
+ "@types/socket.io-client": "^1.4.34",
55
+ "axios": "^0.21.1",
56
+ "chalk": "^4.1.0",
57
+ "fast-glob": "^3.2.4",
58
+ "findup-sync": "^4.0.0",
59
+ "fs": "^0.0.1-security",
60
+ "glob": "^7.1.6",
61
+ "inquirer": "^7.3.2",
62
+ "latest-version": "^5.1.0",
63
+ "lodash": "^4.17.19",
64
+ "moment": "^2.27.0",
65
+ "open": "^8.0.9",
66
+ "pako": "^1.0.11",
67
+ "path": "^0.12.7",
68
+ "prettier": "^2.0.5",
69
+ "semver": "^7.3.2",
70
+ "socket.io-client": "^3.0.3",
71
+ "typescript": "^3.9.6",
72
+ "upath": "^1.2.0",
73
+ "update-notifier": "^4.1.0",
74
+ "utility-types": "^3.10.0",
75
+ "uuid": "^8.3.1",
76
+ "winston": "^3.3.3",
77
+ "wrap-ansi": "^7.0.0",
78
+ "yargs": "^15.4.1"
79
+ }
80
+ }
@@ -0,0 +1,394 @@
1
+ import { ProjectSyncMetadataModel } from "@plasmicapp/code-merger";
2
+ import L from "lodash";
3
+ import {
4
+ ChecksumBundle,
5
+ ComponentBundle,
6
+ ProjectBundle,
7
+ ProjectIconsResponse,
8
+ ProjectIdAndToken,
9
+ ProjectMetaBundle,
10
+ ProjectVersionMeta,
11
+ RequiredPackages,
12
+ StyleConfigResponse,
13
+ StyleTokensMap,
14
+ VersionResolution,
15
+ } from "../api";
16
+ import { AuthConfig } from "../utils/config-utils";
17
+ import { ensure } from "../utils/lang-utils";
18
+ import * as semver from "../utils/semver";
19
+
20
+ const api: any = jest.genMockFromModule("../api");
21
+
22
+ /**
23
+ * Store a simplified data model for use with testing
24
+ */
25
+ // Keyed by (projectId, version)
26
+ const PROJECTS: MockProject[] = [];
27
+ export interface MockProject {
28
+ projectId: string;
29
+ projectApiToken: string;
30
+ version: string;
31
+ projectName: string;
32
+ components: MockComponent[];
33
+ dependencies: {
34
+ [projectId: string]: string;
35
+ };
36
+ }
37
+ export interface MockComponent {
38
+ id: string;
39
+ name: string;
40
+ projectId?: string;
41
+ version?: string;
42
+ }
43
+
44
+ function clear() {
45
+ while (PROJECTS.length > 0) {
46
+ PROJECTS.shift();
47
+ }
48
+ }
49
+
50
+ function mockProjectToProjectVersionMeta(
51
+ mock: MockProject,
52
+ componentIdOrNames?: readonly string[]
53
+ ): ProjectVersionMeta {
54
+ return {
55
+ ...mock,
56
+ componentIds: mock.components
57
+ .filter(
58
+ (c) =>
59
+ !componentIdOrNames ||
60
+ componentIdOrNames.includes(c.name) ||
61
+ componentIdOrNames.includes(c.id)
62
+ )
63
+ .map((c) => c.id),
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Call this in test to setup the data model
69
+ * @param id componentId
70
+ * @param comp MockComponent
71
+ */
72
+ function addMockProject(proj: MockProject) {
73
+ const projectId = proj.projectId;
74
+ const version = proj.version;
75
+ // Populate projectId and version into each component
76
+ // will be useful when reading / writing components to files
77
+ proj.components = proj.components.map((c) => {
78
+ return {
79
+ ...c,
80
+ projectId,
81
+ version,
82
+ };
83
+ });
84
+
85
+ const existing = getMockProject(projectId, version);
86
+ if (!existing) {
87
+ PROJECTS.push(proj);
88
+ } else {
89
+ existing.components = proj.components;
90
+ existing.dependencies = proj.dependencies;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Used to interpret data that's stored in the "codegen" files from the Mock server
96
+ * @param data
97
+ */
98
+ function stringToMockComponent(data?: string): MockComponent | undefined {
99
+ if (!data) {
100
+ return;
101
+ }
102
+ const withoutComments = data.startsWith("//") ? data.slice(2) : data;
103
+ const cleaned = withoutComments.trim();
104
+ return JSON.parse(cleaned);
105
+ }
106
+
107
+ /**
108
+ * Used to write mock data into files for testing.
109
+ * Useful to see what version was written
110
+ * Need to prefix with a comment to satisfy the parser used in `fixAllImports`
111
+ * @param component
112
+ */
113
+ function mockComponentToString(component: MockComponent): string {
114
+ return "// " + JSON.stringify(component);
115
+ }
116
+
117
+ function getMockProject(
118
+ projectId: string,
119
+ version: string
120
+ ): MockProject | undefined {
121
+ return PROJECTS.find(
122
+ (m) => m.projectId === projectId && m.version === version
123
+ );
124
+ }
125
+
126
+ /**
127
+ * Only fetch top-level components that match the projectId (optionally also componentIdOrNames + version)
128
+ * Does not crawl the dependency tree
129
+ * @param projectId
130
+ * @param componentIdOrNames
131
+ * @param versionRange
132
+ */
133
+ function getMockComponents(
134
+ projectId: string,
135
+ version: string,
136
+ componentIdOrNames: readonly string[] | undefined
137
+ ): MockComponent[] {
138
+ const project = getMockProject(projectId, version);
139
+ return !project
140
+ ? []
141
+ : project.components.filter(
142
+ (c) =>
143
+ !componentIdOrNames ||
144
+ componentIdOrNames.includes(c.id) ||
145
+ componentIdOrNames.includes(c.name)
146
+ );
147
+ }
148
+
149
+ function genFilename(base: string, suffix: string) {
150
+ return "Plasmic" + base + "." + suffix;
151
+ }
152
+
153
+ function genComponentBundle(component: MockComponent): ComponentBundle {
154
+ return {
155
+ renderModule: mockComponentToString(component),
156
+ skeletonModule: mockComponentToString(component),
157
+ cssRules: `theClass {color: blue;}`,
158
+ renderModuleFileName: genFilename(component.name, "tsx"),
159
+ skeletonModuleFileName: component.name + ".tsx",
160
+ cssFileName: genFilename(component.name, "css"),
161
+ componentName: component.name,
162
+ id: component.id,
163
+ scheme: "blackbox",
164
+ nameInIdToUuid: [],
165
+ isPage: false,
166
+ };
167
+ }
168
+
169
+ function genEmptyStyleTokensMap() {
170
+ return {
171
+ props: [],
172
+ global: {
173
+ meta: {
174
+ source: "plasmic.app" as "plasmic.app",
175
+ },
176
+ },
177
+ };
178
+ }
179
+
180
+ function genProjectMetaBundle(projectId: string): ProjectMetaBundle {
181
+ return {
182
+ projectId,
183
+ projectName: projectId,
184
+ cssFileName: genFilename(projectId, "css"),
185
+ cssRules: `theClass {color: green;}`,
186
+ jsBundleThemes: [],
187
+ };
188
+ }
189
+
190
+ function* getDeps(projects: ProjectVersionMeta[]) {
191
+ const queue: ProjectVersionMeta[] = [...projects];
192
+ while (queue.length > 0) {
193
+ const curr = ensure(queue.shift());
194
+ for (const [projectId, version] of L.toPairs(curr.dependencies)) {
195
+ const mockProject = ensure(getMockProject(projectId, version));
196
+ const projectMeta = mockProjectToProjectVersionMeta(mockProject);
197
+ yield projectMeta;
198
+ queue.push(projectMeta);
199
+ }
200
+ }
201
+ }
202
+
203
+ class PlasmicApi {
204
+ constructor(private auth: AuthConfig) {}
205
+
206
+ async genStyleConfig(): Promise<StyleConfigResponse> {
207
+ const result = {
208
+ defaultStyleCssFileName: genFilename("default", "css"),
209
+ defaultStyleCssRules: `theClass {color: red;}`,
210
+ };
211
+ return result;
212
+ }
213
+
214
+ async resolveSync(
215
+ projects: {
216
+ projectId: string;
217
+ versionRange: string;
218
+ componentIdOrNames: readonly string[] | undefined;
219
+ projectApiToken?: string;
220
+ }[],
221
+ recursive?: boolean
222
+ ): Promise<VersionResolution> {
223
+ const results: VersionResolution = {
224
+ projects: [],
225
+ dependencies: [],
226
+ conflicts: [],
227
+ };
228
+
229
+ // Get top level projects
230
+ projects.forEach((proj) => {
231
+ const availableProjects = Array.from(PROJECTS.values()).filter(
232
+ (p) => p.projectId === proj.projectId
233
+ );
234
+ if (
235
+ !(
236
+ (this.auth.user && this.auth.token) ||
237
+ availableProjects.every(
238
+ (p) => p.projectApiToken === proj.projectApiToken
239
+ )
240
+ )
241
+ ) {
242
+ throw new Error("No user+token, and project API tokens don't match");
243
+ }
244
+ const availableVersions = availableProjects.map((p) => p.version);
245
+ const version = semver.maxSatisfying(
246
+ availableVersions,
247
+ proj.versionRange
248
+ );
249
+ if (version) {
250
+ const mockProject = ensure(getMockProject(proj.projectId, version));
251
+ const projectMeta = mockProjectToProjectVersionMeta(
252
+ mockProject,
253
+ proj.componentIdOrNames
254
+ );
255
+ results.projects.push(projectMeta);
256
+ }
257
+ });
258
+
259
+ // Get dependencies
260
+ if (!!recursive) {
261
+ const deps = [...getDeps(results.projects)];
262
+ results.dependencies.push(...deps);
263
+ }
264
+
265
+ return results;
266
+ }
267
+
268
+ async getCurrentUser() {
269
+ return true;
270
+ }
271
+
272
+ async projectComponents(
273
+ projectId: string,
274
+ opts: {
275
+ platform: string;
276
+ newCompScheme: "blackbox" | "direct";
277
+ // The list of existing components as [componentUuid, codeScheme]
278
+ existingCompScheme: Array<[string, "blackbox" | "direct"]>;
279
+ componentIdOrNames: readonly string[] | undefined;
280
+ version: string;
281
+ }
282
+ ): Promise<ProjectBundle> {
283
+ const { componentIdOrNames, version } = opts;
284
+ if (PROJECTS.length <= 0) {
285
+ throw new Error("Remember to call __addMockProject first!");
286
+ }
287
+ const maybeTokenPair = this.lastProjectIdsAndTokens.find(
288
+ (pair) => pair.projectId === projectId
289
+ );
290
+ const project = ensure(PROJECTS.find((p) => p.projectId === projectId));
291
+ if (
292
+ !(
293
+ (this.auth.user && this.auth.token) ||
294
+ project.projectApiToken === maybeTokenPair?.projectApiToken
295
+ )
296
+ ) {
297
+ throw new Error("No user+token and project API tokens don't match");
298
+ }
299
+ // Server also require tokens for the dependencies.
300
+ const deps = [...getDeps([mockProjectToProjectVersionMeta(project)])];
301
+ if (
302
+ !deps.every((dep) =>
303
+ this.lastProjectIdsAndTokens.find((p) => p.projectId === dep.projectId)
304
+ )
305
+ ) {
306
+ throw new Error(
307
+ "No user+token and project API tokens don't match on a dependency"
308
+ );
309
+ }
310
+ const mockComponents = getMockComponents(
311
+ projectId,
312
+ version,
313
+ componentIdOrNames
314
+ );
315
+ if (mockComponents.length <= 0) {
316
+ throw new Error(
317
+ `Code gen failed: no components match the parameters ${JSON.stringify(
318
+ { projectId, version, componentIdOrNames },
319
+ undefined,
320
+ 2
321
+ )}`
322
+ );
323
+ }
324
+
325
+ const components = mockComponents.map((c) => genComponentBundle(c));
326
+ const result = {
327
+ components,
328
+ codeComponentMetas: [],
329
+ projectConfig: genProjectMetaBundle(projectId),
330
+ globalVariants: [],
331
+ usedTokens: genEmptyStyleTokensMap(),
332
+ iconAssets: [],
333
+ imageAssets: [],
334
+ checksums: {
335
+ renderModuleChecksums: components.map((c) => [c.id, c.renderModule]),
336
+ cssRulesChecksums: components.map((c) => [c.id, c.cssRules]),
337
+ imageChecksums: [],
338
+ iconChecksums: [],
339
+ globalVariantChecksums: [],
340
+ projectCssChecksum: "",
341
+ } as ChecksumBundle,
342
+ };
343
+ return result;
344
+ }
345
+
346
+ async uploadBundle(
347
+ projectId: string,
348
+ bundleName: string,
349
+ bundleJs: string,
350
+ css: string[],
351
+ metaJson: string
352
+ ): Promise<StyleTokensMap> {
353
+ throw new Error("Unimplemented");
354
+ }
355
+
356
+ async projectStyleTokens(projectId: string): Promise<StyleTokensMap> {
357
+ throw new Error("Unimplemented");
358
+ }
359
+
360
+ async projectIcons(projectId: string): Promise<ProjectIconsResponse> {
361
+ throw new Error("Unimplemented");
362
+ }
363
+
364
+ async projectSyncMetadata(
365
+ projectId: string,
366
+ revision: number,
367
+ rethrowAppError: boolean
368
+ ): Promise<ProjectSyncMetadataModel> {
369
+ throw new Error("Unimplemented");
370
+ }
371
+
372
+ async requiredPackages(): Promise<RequiredPackages> {
373
+ return {
374
+ "@plasmicapp/loader": "0.0.1",
375
+ "@plasmicapp/cli": "0.0.1",
376
+ "@plasmicapp/react-web": "0.0.1",
377
+ "@plasmicapp/react-web-runtime": "0.0.1",
378
+ };
379
+ }
380
+
381
+ connectSocket() {}
382
+
383
+ lastProjectIdsAndTokens: ProjectIdAndToken[] = [];
384
+ attachProjectIdsAndTokens(idsAndTokens: ProjectIdAndToken[]) {
385
+ this.lastProjectIdsAndTokens = idsAndTokens;
386
+ }
387
+ }
388
+
389
+ api.PlasmicApi = PlasmicApi;
390
+ api.clear = clear;
391
+ api.getMockProject = getMockProject;
392
+ api.addMockProject = addMockProject;
393
+ api.stringToMockComponent = stringToMockComponent;
394
+ module.exports = api;