@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.
- package/.eslintrc.js +61 -0
- package/.idea/cli.iml +11 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README +16 -0
- package/README.internal +46 -0
- package/README.md +17 -0
- package/build.sh +8 -0
- package/dist/__mocks__/api.d.ts +16 -0
- package/dist/__mocks__/api.js +297 -0
- package/dist/__tests__/code-utils-spec.d.ts +1 -0
- package/dist/__tests__/code-utils-spec.js +838 -0
- package/dist/__tests__/ftue-spec.d.ts +1 -0
- package/dist/__tests__/ftue-spec.js +39 -0
- package/dist/__tests__/project-api-token-spec.d.ts +1 -0
- package/dist/__tests__/project-api-token-spec.js +147 -0
- package/dist/__tests__/versioned-sync-spec.d.ts +1 -0
- package/dist/__tests__/versioned-sync-spec.js +145 -0
- package/dist/actions/auth.d.ts +8 -0
- package/dist/actions/auth.js +47 -0
- package/dist/actions/fix-imports.d.ts +4 -0
- package/dist/actions/fix-imports.js +25 -0
- package/dist/actions/init.d.ts +62 -0
- package/dist/actions/init.js +460 -0
- package/dist/actions/project-token.d.ts +6 -0
- package/dist/actions/project-token.js +42 -0
- package/dist/actions/sync-components.d.ts +10 -0
- package/dist/actions/sync-components.js +242 -0
- package/dist/actions/sync-global-variants.d.ts +3 -0
- package/dist/actions/sync-global-variants.js +89 -0
- package/dist/actions/sync-icons.d.ts +7 -0
- package/dist/actions/sync-icons.js +92 -0
- package/dist/actions/sync-images.d.ts +6 -0
- package/dist/actions/sync-images.js +137 -0
- package/dist/actions/sync-styles.d.ts +3 -0
- package/dist/actions/sync-styles.js +58 -0
- package/dist/actions/sync.d.ts +25 -0
- package/dist/actions/sync.js +417 -0
- package/dist/actions/upload-bundle.d.ts +15 -0
- package/dist/actions/upload-bundle.js +28 -0
- package/dist/actions/watch.d.ts +14 -0
- package/dist/actions/watch.js +90 -0
- package/dist/api.d.ts +182 -0
- package/dist/api.js +202 -0
- package/dist/deps.d.ts +2 -0
- package/dist/deps.js +20 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +247 -0
- package/dist/lib.d.ts +10 -0
- package/dist/lib.js +23 -0
- package/dist/migrations/0.1.110-fileLocks.d.ts +2 -0
- package/dist/migrations/0.1.110-fileLocks.js +15 -0
- package/dist/migrations/0.1.143-ensureImportModuleType.d.ts +2 -0
- package/dist/migrations/0.1.143-ensureImportModuleType.js +12 -0
- package/dist/migrations/0.1.146-addReactRuntime.d.ts +2 -0
- package/dist/migrations/0.1.146-addReactRuntime.js +10 -0
- package/dist/migrations/0.1.27-migrateInit.d.ts +1 -0
- package/dist/migrations/0.1.27-migrateInit.js +8 -0
- package/dist/migrations/0.1.28-tsToTsx.d.ts +3 -0
- package/dist/migrations/0.1.28-tsToTsx.js +33 -0
- package/dist/migrations/0.1.31-ensureProjectIcons.d.ts +2 -0
- package/dist/migrations/0.1.31-ensureProjectIcons.js +12 -0
- package/dist/migrations/0.1.42-ensureVersion.d.ts +2 -0
- package/dist/migrations/0.1.42-ensureVersion.js +12 -0
- package/dist/migrations/0.1.57-ensureJsBundleThemes.d.ts +2 -0
- package/dist/migrations/0.1.57-ensureJsBundleThemes.js +12 -0
- package/dist/migrations/0.1.64-imageFiles.d.ts +2 -0
- package/dist/migrations/0.1.64-imageFiles.js +17 -0
- package/dist/migrations/0.1.95-componentType.d.ts +2 -0
- package/dist/migrations/0.1.95-componentType.js +16 -0
- package/dist/migrations/migrations.d.ts +10 -0
- package/dist/migrations/migrations.js +119 -0
- package/dist/plasmic.schema.json +463 -0
- package/dist/test-common/fixtures.d.ts +13 -0
- package/dist/test-common/fixtures.js +165 -0
- package/dist/tsconfig-transform.json +68 -0
- package/dist/utils/auth-utils.d.ts +31 -0
- package/dist/utils/auth-utils.js +236 -0
- package/dist/utils/checksum.d.ts +4 -0
- package/dist/utils/checksum.js +63 -0
- package/dist/utils/code-utils.d.ts +46 -0
- package/dist/utils/code-utils.js +457 -0
- package/dist/utils/config-utils.d.ts +271 -0
- package/dist/utils/config-utils.js +178 -0
- package/dist/utils/envdetect.d.ts +4 -0
- package/dist/utils/envdetect.js +42 -0
- package/dist/utils/error.d.ts +14 -0
- package/dist/utils/error.js +42 -0
- package/dist/utils/file-utils.d.ts +71 -0
- package/dist/utils/file-utils.js +433 -0
- package/dist/utils/get-context.d.ts +40 -0
- package/dist/utils/get-context.js +339 -0
- package/dist/utils/help.d.ts +2 -0
- package/dist/utils/help.js +56 -0
- package/dist/utils/lang-utils.d.ts +10 -0
- package/dist/utils/lang-utils.js +52 -0
- package/dist/utils/npm-utils.d.ts +28 -0
- package/dist/utils/npm-utils.js +215 -0
- package/dist/utils/prompts.d.ts +6 -0
- package/dist/utils/prompts.js +23 -0
- package/dist/utils/resolve-utils.d.ts +13 -0
- package/dist/utils/resolve-utils.js +198 -0
- package/dist/utils/semver.d.ts +34 -0
- package/dist/utils/semver.js +61 -0
- package/dist/utils/test-utils.d.ts +22 -0
- package/dist/utils/test-utils.js +106 -0
- package/dist/utils/user-utils.d.ts +7 -0
- package/dist/utils/user-utils.js +48 -0
- package/jest.config.js +6 -0
- package/package.json +80 -0
- package/src/__mocks__/api.ts +394 -0
- package/src/__tests__/code-utils-spec.ts +881 -0
- package/src/__tests__/ftue-spec.ts +43 -0
- package/src/__tests__/project-api-token-spec.ts +208 -0
- package/src/__tests__/versioned-sync-spec.ts +176 -0
- package/src/actions/auth.ts +43 -0
- package/src/actions/fix-imports.ts +13 -0
- package/src/actions/init.ts +638 -0
- package/src/actions/project-token.ts +36 -0
- package/src/actions/sync-components.ts +405 -0
- package/src/actions/sync-global-variants.ts +129 -0
- package/src/actions/sync-icons.ts +135 -0
- package/src/actions/sync-images.ts +191 -0
- package/src/actions/sync-styles.ts +71 -0
- package/src/actions/sync.ts +747 -0
- package/src/actions/upload-bundle.ts +38 -0
- package/src/actions/watch.ts +95 -0
- package/src/api.ts +407 -0
- package/src/deps.ts +18 -0
- package/src/index.ts +300 -0
- package/src/lib.ts +10 -0
- package/src/migrations/0.1.110-fileLocks.ts +16 -0
- package/src/migrations/0.1.146-addReactRuntime.ts +8 -0
- package/src/migrations/0.1.27-migrateInit.ts +4 -0
- package/src/migrations/0.1.28-tsToTsx.ts +37 -0
- package/src/migrations/0.1.31-ensureProjectIcons.ts +10 -0
- package/src/migrations/0.1.42-ensureVersion.ts +10 -0
- package/src/migrations/0.1.57-ensureJsBundleThemes.ts +10 -0
- package/src/migrations/0.1.64-imageFiles.ts +15 -0
- package/src/migrations/0.1.95-componentType.ts +14 -0
- package/src/migrations/migrations.ts +147 -0
- package/src/test-common/fixtures.ts +178 -0
- package/src/utils/auth-utils.ts +276 -0
- package/src/utils/checksum.ts +106 -0
- package/src/utils/code-utils.ts +656 -0
- package/src/utils/config-utils.ts +551 -0
- package/src/utils/envdetect.ts +39 -0
- package/src/utils/error.ts +36 -0
- package/src/utils/file-utils.ts +526 -0
- package/src/utils/get-context.ts +451 -0
- package/src/utils/help.ts +75 -0
- package/src/utils/lang-utils.ts +52 -0
- package/src/utils/npm-utils.ts +223 -0
- package/src/utils/prompts.ts +22 -0
- package/src/utils/resolve-utils.ts +245 -0
- package/src/utils/semver.ts +67 -0
- package/src/utils/test-utils.ts +116 -0
- package/src/utils/user-utils.ts +37 -0
- package/testData/fixImports_plasmic.json +66 -0
- package/tsconfig-transform.json +68 -0
- package/tsconfig.json +67 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import L from "lodash";
|
|
2
|
+
import { SyncArgs } from "../actions/sync";
|
|
3
|
+
import { PlasmicConfig, ProjectConfig } from "../utils/config-utils";
|
|
4
|
+
import { TempRepo } from "../utils/test-utils";
|
|
5
|
+
import { MockProject } from "../__mocks__/api";
|
|
6
|
+
|
|
7
|
+
jest.mock("../api");
|
|
8
|
+
|
|
9
|
+
export const mockApi = require("../api");
|
|
10
|
+
export let opts: SyncArgs; // Options to pass to sync
|
|
11
|
+
export let tmpRepo: TempRepo;
|
|
12
|
+
|
|
13
|
+
export const defaultPlasmicJson: PlasmicConfig = {
|
|
14
|
+
platform: "react",
|
|
15
|
+
code: {
|
|
16
|
+
lang: "ts",
|
|
17
|
+
scheme: "blackbox",
|
|
18
|
+
reactRuntime: "classic",
|
|
19
|
+
},
|
|
20
|
+
style: {
|
|
21
|
+
scheme: "css",
|
|
22
|
+
defaultStyleCssFilePath: "plasmic/PP__plasmic__default_style.css",
|
|
23
|
+
},
|
|
24
|
+
images: {
|
|
25
|
+
scheme: "inlined",
|
|
26
|
+
},
|
|
27
|
+
tokens: {
|
|
28
|
+
scheme: "theo",
|
|
29
|
+
tokensFilePath: "plasmic-tokens.theo.json",
|
|
30
|
+
},
|
|
31
|
+
srcDir: "src/",
|
|
32
|
+
defaultPlasmicDir: "./plasmic",
|
|
33
|
+
projects: [],
|
|
34
|
+
globalVariants: {
|
|
35
|
+
variantGroups: [],
|
|
36
|
+
},
|
|
37
|
+
cliVersion: "0.1.44",
|
|
38
|
+
};
|
|
39
|
+
export function standardTestSetup(includeDep = true) {
|
|
40
|
+
process.env.PLASMIC_DISABLE_AUTH_SEARCH = "1";
|
|
41
|
+
|
|
42
|
+
// Setup server-side mock data
|
|
43
|
+
const project1: MockProject = {
|
|
44
|
+
projectId: "projectId1",
|
|
45
|
+
projectApiToken: "abc",
|
|
46
|
+
version: "1.2.3",
|
|
47
|
+
projectName: "project1",
|
|
48
|
+
components: [
|
|
49
|
+
{
|
|
50
|
+
id: "buttonId",
|
|
51
|
+
name: "Button",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "containerId",
|
|
55
|
+
name: "Container",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
dependencies: includeDep
|
|
59
|
+
? {
|
|
60
|
+
dependencyId1: "2.3.4",
|
|
61
|
+
}
|
|
62
|
+
: {},
|
|
63
|
+
};
|
|
64
|
+
const dependency: MockProject = {
|
|
65
|
+
projectId: "dependencyId1",
|
|
66
|
+
projectApiToken: "def",
|
|
67
|
+
version: "2.3.4",
|
|
68
|
+
projectName: "dependency1",
|
|
69
|
+
components: [
|
|
70
|
+
{
|
|
71
|
+
id: "depComponentId",
|
|
72
|
+
name: "DepComponent",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
dependencies: {},
|
|
76
|
+
};
|
|
77
|
+
[project1, dependency].forEach((p) => mockApi.addMockProject(p));
|
|
78
|
+
|
|
79
|
+
// Setup client-side directory
|
|
80
|
+
tmpRepo = new TempRepo();
|
|
81
|
+
tmpRepo.writePlasmicAuth({
|
|
82
|
+
host: "http://localhost:3003",
|
|
83
|
+
user: "yang@plasmic.app",
|
|
84
|
+
token: "faketoken",
|
|
85
|
+
});
|
|
86
|
+
tmpRepo.writePlasmicJson(defaultPlasmicJson);
|
|
87
|
+
|
|
88
|
+
// Default opts and config
|
|
89
|
+
opts = {
|
|
90
|
+
projects: [],
|
|
91
|
+
yes: true,
|
|
92
|
+
force: true,
|
|
93
|
+
nonRecursive: false,
|
|
94
|
+
skipUpgradeCheck: true,
|
|
95
|
+
forceOverwrite: true,
|
|
96
|
+
newComponentScheme: "blackbox",
|
|
97
|
+
appendJsxOnMissingBase: false,
|
|
98
|
+
config: tmpRepo.plasmicJsonPath(),
|
|
99
|
+
auth: tmpRepo.plasmicAuthPath(),
|
|
100
|
+
loaderConfig: tmpRepo.plasmicLoaderJsonPath(),
|
|
101
|
+
baseDir: process.cwd(),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function standardTestTeardown() {
|
|
106
|
+
tmpRepo.destroy();
|
|
107
|
+
mockApi.clear();
|
|
108
|
+
delete process.env["PLASMIC_DISABLE_AUTH_SEARCH"];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function expectProject1Components() {
|
|
112
|
+
// Check correct files exist
|
|
113
|
+
const button = mockApi.stringToMockComponent(
|
|
114
|
+
tmpRepo.getComponentFileContents("projectId1", "buttonId")
|
|
115
|
+
);
|
|
116
|
+
const container = mockApi.stringToMockComponent(
|
|
117
|
+
tmpRepo.getComponentFileContents("projectId1", "containerId")
|
|
118
|
+
);
|
|
119
|
+
expect(button).toBeTruthy();
|
|
120
|
+
expect(container).toBeTruthy();
|
|
121
|
+
expect(button?.name).toEqual("Button");
|
|
122
|
+
expect(button?.version).toEqual("1.2.3");
|
|
123
|
+
expect(container?.name).toEqual("Container");
|
|
124
|
+
expect(container?.version).toEqual("1.2.3");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const project1Config: ProjectConfig = {
|
|
128
|
+
projectId: "projectId1",
|
|
129
|
+
projectName: "Project 1",
|
|
130
|
+
version: "latest",
|
|
131
|
+
cssFilePath: "plasmic/PP__demo.css",
|
|
132
|
+
components: [
|
|
133
|
+
{
|
|
134
|
+
id: "buttonId",
|
|
135
|
+
name: "Button",
|
|
136
|
+
type: "managed",
|
|
137
|
+
projectId: "projectId1",
|
|
138
|
+
renderModuleFilePath: "plasmic/project_id_1/PlasmicButton.tsx",
|
|
139
|
+
importSpec: {
|
|
140
|
+
modulePath: "Button.tsx",
|
|
141
|
+
},
|
|
142
|
+
cssFilePath: "plasmic/PlasmicButton.css",
|
|
143
|
+
scheme: "blackbox",
|
|
144
|
+
componentType: "component",
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
icons: [],
|
|
148
|
+
images: [],
|
|
149
|
+
jsBundleThemes: [],
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export function expectProject1PlasmicJson() {
|
|
153
|
+
const plasmicJson = tmpRepo.readPlasmicJson();
|
|
154
|
+
expect(plasmicJson.projects.length).toEqual(1);
|
|
155
|
+
const projectConfig = plasmicJson.projects[0];
|
|
156
|
+
expect(projectConfig.projectApiToken).toBe("abc");
|
|
157
|
+
expect(projectConfig.components.length).toEqual(2);
|
|
158
|
+
const componentNames = projectConfig.components.map((c) => c.name);
|
|
159
|
+
expect(componentNames).toContain("Button");
|
|
160
|
+
expect(componentNames).toContain("Container");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function expectProjectAndDepPlasmicJson() {
|
|
164
|
+
const plasmicJson = tmpRepo.readPlasmicJson();
|
|
165
|
+
expect(plasmicJson.projects.length).toEqual(2);
|
|
166
|
+
const projectConfigMap = L.keyBy(plasmicJson.projects, (p) => p.projectId);
|
|
167
|
+
expect(projectConfigMap["projectId1"]).toBeTruthy();
|
|
168
|
+
expect(projectConfigMap["dependencyId1"]).toBeTruthy();
|
|
169
|
+
const projectComponentNames = projectConfigMap["projectId1"].components.map(
|
|
170
|
+
(c) => c.name
|
|
171
|
+
);
|
|
172
|
+
const depComponentNames = projectConfigMap["dependencyId1"].components.map(
|
|
173
|
+
(c) => c.name
|
|
174
|
+
);
|
|
175
|
+
expect(projectComponentNames).toContain("Button");
|
|
176
|
+
expect(projectComponentNames).toContain("Container");
|
|
177
|
+
expect(depComponentNames).toContain("DepComponent");
|
|
178
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
import open from "open";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import socketio from "socket.io-client";
|
|
6
|
+
import path from "upath";
|
|
7
|
+
import { v4 as uuidv4 } from "uuid";
|
|
8
|
+
import { PlasmicApi } from "../api";
|
|
9
|
+
import { logger } from "../deps";
|
|
10
|
+
import { CommonArgs } from "../index";
|
|
11
|
+
import { HandledError } from "../utils/error";
|
|
12
|
+
import {
|
|
13
|
+
AuthConfig,
|
|
14
|
+
AUTH_FILE_NAME,
|
|
15
|
+
DEFAULT_HOST,
|
|
16
|
+
ENV_AUTH_HOST,
|
|
17
|
+
ENV_AUTH_TOKEN,
|
|
18
|
+
ENV_AUTH_USER,
|
|
19
|
+
} from "./config-utils";
|
|
20
|
+
import {
|
|
21
|
+
existsBuffered,
|
|
22
|
+
findFile,
|
|
23
|
+
readFileText,
|
|
24
|
+
writeFileContentRaw,
|
|
25
|
+
} from "./file-utils";
|
|
26
|
+
|
|
27
|
+
export type AuthData = {
|
|
28
|
+
user: string;
|
|
29
|
+
token: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type CancellablePromise<T> = {
|
|
33
|
+
promise: Promise<T>;
|
|
34
|
+
cancel: () => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export function authByPolling(
|
|
38
|
+
host: string,
|
|
39
|
+
initToken: string
|
|
40
|
+
): CancellablePromise<AuthData> {
|
|
41
|
+
const socket = socketio.connect(host, {
|
|
42
|
+
path: `/api/v1/init-token`,
|
|
43
|
+
transportOptions: {
|
|
44
|
+
polling: {
|
|
45
|
+
extraHeaders: {
|
|
46
|
+
"x-plasmic-init-token": initToken,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const promise = new Promise<AuthData>((resolve, reject) => {
|
|
53
|
+
socket.on("connect", (reason: string) => {
|
|
54
|
+
logger.info("Waiting for token...");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
socket.on("token", (data: AuthData) => {
|
|
58
|
+
resolve(data);
|
|
59
|
+
socket.close();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
socket.on("error", (error: {}) => {
|
|
63
|
+
logger.warn(error);
|
|
64
|
+
reject(error);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const cancel = () => {
|
|
69
|
+
socket.close();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return { promise, cancel };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function authByPrompt(host: string) {
|
|
76
|
+
const promise = inquirer.prompt([
|
|
77
|
+
{
|
|
78
|
+
name: "user",
|
|
79
|
+
message: "Your Plasmic user email",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "token",
|
|
83
|
+
message: `Your personal access token (create one at ${host}/self/settings)`,
|
|
84
|
+
},
|
|
85
|
+
]);
|
|
86
|
+
|
|
87
|
+
const cancel = () => {
|
|
88
|
+
logger.info("Cancelling prompt...");
|
|
89
|
+
process.stdin.pause();
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return { promise, cancel };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function startAuth(opts: Partial<CommonArgs> & { host: string }) {
|
|
96
|
+
if (opts.yes) {
|
|
97
|
+
throw new HandledError("Plasmic credentials could not be found.");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const auth = await new Promise<AuthData>((resolve, reject) => {
|
|
101
|
+
let prompt: CancellablePromise<AuthData>;
|
|
102
|
+
|
|
103
|
+
const initToken = uuidv4();
|
|
104
|
+
const url = `${opts.host}/auth/plasmic-init/${initToken}`;
|
|
105
|
+
open(url);
|
|
106
|
+
logger.info(
|
|
107
|
+
`\nIf your browser doesn't automatically open, enter the following URL:\n${url}\n`
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
logger.info(`Please log in and authorize Plasmic CLI.`);
|
|
111
|
+
const polling = authByPolling(opts.host, initToken);
|
|
112
|
+
polling.promise.then((auth) => {
|
|
113
|
+
if (prompt) {
|
|
114
|
+
prompt.cancel();
|
|
115
|
+
} else {
|
|
116
|
+
clearTimeout(timeout);
|
|
117
|
+
}
|
|
118
|
+
resolve(auth);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Default to 1 minute.
|
|
122
|
+
const authPollTimeout =
|
|
123
|
+
Number(process.env.PLASMIC_AUTH_POLL_TIMEOUT) || 60 * 1000;
|
|
124
|
+
if (authPollTimeout === -1) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const timeout = setTimeout(() => {
|
|
128
|
+
logger.info(`We haven't received an auth token from Plasmic yet.`);
|
|
129
|
+
prompt = authByPrompt(opts.host);
|
|
130
|
+
prompt.promise
|
|
131
|
+
.then((auth) => {
|
|
132
|
+
polling.cancel();
|
|
133
|
+
resolve(auth);
|
|
134
|
+
})
|
|
135
|
+
.catch(reject);
|
|
136
|
+
}, authPollTimeout);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (!auth.user || !auth.token) {
|
|
140
|
+
logger.error(`Could not get auth token.`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const newAuthFile = opts.auth || path.join(os.homedir(), AUTH_FILE_NAME);
|
|
145
|
+
|
|
146
|
+
await writeAuth(newAuthFile, {
|
|
147
|
+
host: opts.host,
|
|
148
|
+
user: auth.user,
|
|
149
|
+
token: auth.token,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
logger.info(
|
|
153
|
+
`Successfully created Plasmic credentials file at ${newAuthFile}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function readAuth(authFile: string) {
|
|
158
|
+
if (!existsBuffered(authFile)) {
|
|
159
|
+
throw new HandledError(`No Plasmic auth file found at ${authFile}`);
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const parsed = JSON.parse(readFileText(authFile)) as AuthConfig;
|
|
163
|
+
// Strip trailing slashes.
|
|
164
|
+
return {
|
|
165
|
+
...parsed,
|
|
166
|
+
host: parsed.host.replace(/\/+$/, ""),
|
|
167
|
+
};
|
|
168
|
+
} catch (e) {
|
|
169
|
+
logger.error(
|
|
170
|
+
`Error encountered reading plasmic credentials at ${authFile}: ${e}`
|
|
171
|
+
);
|
|
172
|
+
throw e;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function getEnvAuth(): AuthConfig | undefined {
|
|
177
|
+
const host = process.env[ENV_AUTH_HOST];
|
|
178
|
+
const user = process.env[ENV_AUTH_USER];
|
|
179
|
+
const token = process.env[ENV_AUTH_TOKEN];
|
|
180
|
+
|
|
181
|
+
// both user and token are required
|
|
182
|
+
if (!user || !token) {
|
|
183
|
+
// Try to give a hint if they partially entered a credential
|
|
184
|
+
if (user || token) {
|
|
185
|
+
logger.warn(
|
|
186
|
+
`Your Plasmic credentials were only partially set via environment variables. Try both ${ENV_AUTH_USER} and ${ENV_AUTH_TOKEN}`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
host: host ?? DEFAULT_HOST,
|
|
194
|
+
user,
|
|
195
|
+
token,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function readCurrentAuth(authPath?: string) {
|
|
200
|
+
const authFromEnv = getEnvAuth();
|
|
201
|
+
if (authFromEnv) return authFromEnv;
|
|
202
|
+
|
|
203
|
+
if (!authPath && !process.env.PLASMIC_DISABLE_AUTH_SEARCH) {
|
|
204
|
+
authPath = findAuthFile(process.cwd(), { traverseParents: true });
|
|
205
|
+
}
|
|
206
|
+
if (!authPath) {
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
return readAuth(authPath);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function getCurrentAuth(authPath?: string) {
|
|
213
|
+
const auth = readCurrentAuth(authPath);
|
|
214
|
+
if (!auth) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
const api = new PlasmicApi(auth);
|
|
218
|
+
try {
|
|
219
|
+
await api.getCurrentUser();
|
|
220
|
+
return auth;
|
|
221
|
+
} catch (e) {
|
|
222
|
+
if (e.response?.status === 401) {
|
|
223
|
+
logger.error(`The current credentials expired or are not valid.`);
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
throw e;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function failAuth() {
|
|
231
|
+
throw new HandledError(
|
|
232
|
+
`Unable to authenticate Plasmic. Please run 'plasmic auth'.`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export async function getOrStartAuth(
|
|
237
|
+
opts: CommonArgs & { host: string; enableSkipAuth?: boolean }
|
|
238
|
+
) {
|
|
239
|
+
let auth = await getCurrentAuth(opts.auth);
|
|
240
|
+
if (!auth && opts.enableSkipAuth) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!auth && opts.yes) {
|
|
244
|
+
failAuth();
|
|
245
|
+
}
|
|
246
|
+
if (!auth) {
|
|
247
|
+
await startAuth(opts);
|
|
248
|
+
auth = await getCurrentAuth(opts.auth);
|
|
249
|
+
}
|
|
250
|
+
if (!auth) {
|
|
251
|
+
failAuth();
|
|
252
|
+
}
|
|
253
|
+
return auth;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function findAuthFile(
|
|
257
|
+
dir: string,
|
|
258
|
+
opts: {
|
|
259
|
+
traverseParents?: boolean;
|
|
260
|
+
}
|
|
261
|
+
) {
|
|
262
|
+
let file = findFile(dir, (f) => f === AUTH_FILE_NAME, opts);
|
|
263
|
+
if (!file) {
|
|
264
|
+
file = findFile(os.homedir(), (f) => f === AUTH_FILE_NAME, {
|
|
265
|
+
traverseParents: false,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return file;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export async function writeAuth(authFile: string, config: AuthConfig) {
|
|
272
|
+
await writeFileContentRaw(authFile, JSON.stringify(config, undefined, 2), {
|
|
273
|
+
force: true,
|
|
274
|
+
});
|
|
275
|
+
fs.chmodSync(authFile, "600");
|
|
276
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { SyncArgs } from "../actions/sync";
|
|
2
|
+
import { ChecksumBundle } from "../api";
|
|
3
|
+
import { PlasmicContext } from "./config-utils";
|
|
4
|
+
import { assert } from "./lang-utils";
|
|
5
|
+
|
|
6
|
+
export function getChecksums(
|
|
7
|
+
context: PlasmicContext,
|
|
8
|
+
opts: SyncArgs,
|
|
9
|
+
projectId: string,
|
|
10
|
+
componentIds: string[]
|
|
11
|
+
): ChecksumBundle {
|
|
12
|
+
const projectConfig = context.config.projects.find(
|
|
13
|
+
(p) => p.projectId === projectId
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const projectLock = context.lock.projects.find(
|
|
17
|
+
(projectLock) => projectLock.projectId === projectId
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
if (!projectConfig || !projectLock || opts.allFiles) {
|
|
21
|
+
return {
|
|
22
|
+
imageChecksums: [],
|
|
23
|
+
iconChecksums: [],
|
|
24
|
+
renderModuleChecksums: [],
|
|
25
|
+
cssRulesChecksums: [],
|
|
26
|
+
globalVariantChecksums: [],
|
|
27
|
+
projectCssChecksum: "",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const fileLocks = projectLock.fileLocks;
|
|
32
|
+
|
|
33
|
+
const knownImages = new Set(projectConfig.images.map((i) => i.id));
|
|
34
|
+
const knownIcons = new Set(projectConfig.icons.map((i) => i.id));
|
|
35
|
+
const knownComponents = new Set(projectConfig.components.map((c) => c.id));
|
|
36
|
+
const knownGlobalVariants = new Set(
|
|
37
|
+
context.config.globalVariants.variantGroups
|
|
38
|
+
.filter((vg) => vg.projectId === projectId)
|
|
39
|
+
.map((vg) => vg.id)
|
|
40
|
+
);
|
|
41
|
+
const knownThemes = new Set(
|
|
42
|
+
(projectConfig.jsBundleThemes || []).map((theme) => theme.bundleName)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const toBeSyncedComponents = new Set(componentIds);
|
|
46
|
+
|
|
47
|
+
const imageChecksums = fileLocks
|
|
48
|
+
.filter(
|
|
49
|
+
(fileLock) =>
|
|
50
|
+
fileLock.type === "image" && knownImages.has(fileLock.assetId)
|
|
51
|
+
)
|
|
52
|
+
.map((fileLock): [string, string] => [fileLock.assetId, fileLock.checksum]);
|
|
53
|
+
|
|
54
|
+
const iconChecksums = fileLocks
|
|
55
|
+
.filter(
|
|
56
|
+
(fileLock) =>
|
|
57
|
+
projectLock.lang === context.config.code.lang &&
|
|
58
|
+
fileLock.type === "icon" &&
|
|
59
|
+
knownIcons.has(fileLock.assetId)
|
|
60
|
+
)
|
|
61
|
+
.map((fileLock): [string, string] => [fileLock.assetId, fileLock.checksum]);
|
|
62
|
+
|
|
63
|
+
const renderModuleChecksums = fileLocks
|
|
64
|
+
.filter(
|
|
65
|
+
(fileLock) =>
|
|
66
|
+
projectLock.lang === context.config.code.lang &&
|
|
67
|
+
fileLock.type === "renderModule" &&
|
|
68
|
+
toBeSyncedComponents.has(fileLock.assetId) &&
|
|
69
|
+
knownComponents.has(fileLock.assetId)
|
|
70
|
+
)
|
|
71
|
+
.map((fileLock): [string, string] => [fileLock.assetId, fileLock.checksum]);
|
|
72
|
+
|
|
73
|
+
const cssRulesChecksums = fileLocks
|
|
74
|
+
.filter(
|
|
75
|
+
(fileLock) =>
|
|
76
|
+
fileLock.type === "cssRules" &&
|
|
77
|
+
toBeSyncedComponents.has(fileLock.assetId) &&
|
|
78
|
+
knownComponents.has(fileLock.assetId)
|
|
79
|
+
)
|
|
80
|
+
.map((fileLock): [string, string] => [fileLock.assetId, fileLock.checksum]);
|
|
81
|
+
|
|
82
|
+
const globalVariantChecksums = fileLocks
|
|
83
|
+
.filter(
|
|
84
|
+
(fileLock) =>
|
|
85
|
+
projectLock.lang === context.config.code.lang &&
|
|
86
|
+
fileLock.type === "globalVariant" &&
|
|
87
|
+
knownGlobalVariants.has(fileLock.assetId)
|
|
88
|
+
)
|
|
89
|
+
.map((fileLock): [string, string] => [fileLock.assetId, fileLock.checksum]);
|
|
90
|
+
|
|
91
|
+
const projectCssChecksums = fileLocks.filter(
|
|
92
|
+
(fileLock) => fileLock.type === "projectCss"
|
|
93
|
+
);
|
|
94
|
+
assert(projectCssChecksums.length < 2);
|
|
95
|
+
const projectCssChecksum =
|
|
96
|
+
projectCssChecksums.length > 0 ? projectCssChecksums[0].checksum : "";
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
imageChecksums,
|
|
100
|
+
iconChecksums,
|
|
101
|
+
renderModuleChecksums,
|
|
102
|
+
cssRulesChecksums,
|
|
103
|
+
globalVariantChecksums,
|
|
104
|
+
projectCssChecksum,
|
|
105
|
+
};
|
|
106
|
+
}
|