@plasmicapp/cli 0.1.304 → 0.1.306
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/dist/actions/export.d.ts +16 -0
- package/dist/actions/localization-strings.d.ts +9 -0
- package/dist/actions/sync-global-contexts.d.ts +1 -0
- package/dist/actions/sync-images.d.ts +1 -0
- package/dist/actions/sync.d.ts +0 -1
- package/dist/api.d.ts +22 -1
- package/dist/index.js +3587 -3320
- package/dist/lib.js +29 -44
- package/dist/utils/config-utils.d.ts +1 -11
- package/dist/utils/get-context.d.ts +6 -1
- package/dist/utils/test-utils.d.ts +1 -3
- package/package.json +2 -2
- package/src/__tests__/project-api-token-spec.ts +0 -51
- package/src/actions/export.ts +326 -0
- package/src/actions/localization-strings.ts +19 -0
- package/src/actions/sync-components.ts +1 -1
- package/src/actions/sync-global-contexts.ts +1 -0
- package/src/actions/sync-images.ts +1 -1
- package/src/actions/sync.ts +2 -55
- package/src/api.ts +34 -1
- package/src/index.ts +34 -20
- package/src/test-common/fixtures.ts +3 -4
- package/src/utils/config-utils.ts +0 -11
- package/src/utils/error.ts +2 -2
- package/src/utils/file-utils.ts +8 -0
- package/src/utils/get-context.ts +7 -2
- package/src/utils/test-utils.ts +0 -10
package/dist/lib.js
CHANGED
|
@@ -731091,6 +731091,12 @@ function eqPagePath(a, b) {
|
|
|
731091
731091
|
if (a === b) {
|
|
731092
731092
|
return true;
|
|
731093
731093
|
}
|
|
731094
|
+
const normPagePathBrackets = (p) => {
|
|
731095
|
+
return p.replace("[[", "[").replace("]]", "]");
|
|
731096
|
+
};
|
|
731097
|
+
if (normPagePathBrackets(a) === normPagePathBrackets(b)) {
|
|
731098
|
+
return true;
|
|
731099
|
+
}
|
|
731094
731100
|
if (!a.endsWith("/index") && `${a}/index` === b) {
|
|
731095
731101
|
return true;
|
|
731096
731102
|
}
|
|
@@ -731539,7 +731545,7 @@ var handleError = (p) => {
|
|
|
731539
731545
|
return p.catch((e) => {
|
|
731540
731546
|
if (e.message) {
|
|
731541
731547
|
logger.error(
|
|
731542
|
-
import_chalk.default.bold(import_chalk.default.redBright("\nPlasmic error: ")) + e.message
|
|
731548
|
+
import_chalk.default.bold(import_chalk.default.redBright("\nPlasmic error: ")) + e.message + e.stack
|
|
731543
731549
|
);
|
|
731544
731550
|
}
|
|
731545
731551
|
if (checkEngineStrict()) {
|
|
@@ -731557,7 +731563,6 @@ var DEFAULT_HOST = process.env.PLASMIC_DEFAULT_HOST || "https://studio.plasmic.a
|
|
|
731557
731563
|
var AUTH_FILE_NAME = ".plasmic.auth";
|
|
731558
731564
|
var CONFIG_FILE_NAME = "plasmic.json";
|
|
731559
731565
|
var LOCK_FILE_NAME = "plasmic.lock";
|
|
731560
|
-
var LOADER_CONFIG_FILE_NAME = "plasmic-loader.json";
|
|
731561
731566
|
var ENV_AUTH_HOST = "PLASMIC_AUTH_HOST";
|
|
731562
731567
|
var ENV_AUTH_USER = "PLASMIC_AUTH_USER";
|
|
731563
731568
|
var ENV_AUTH_TOKEN = "PLASMIC_AUTH_TOKEN";
|
|
@@ -731782,6 +731787,20 @@ var PlasmicApi = class {
|
|
|
731782
731787
|
);
|
|
731783
731788
|
return result.data;
|
|
731784
731789
|
}
|
|
731790
|
+
/**
|
|
731791
|
+
* Code-gen endpoint.
|
|
731792
|
+
* This will fetch components from a given branch at an exact specified version
|
|
731793
|
+
* using the "plain" scheme
|
|
731794
|
+
*/
|
|
731795
|
+
async exportProject(projectId, branchName, opts) {
|
|
731796
|
+
const result = await this.post(
|
|
731797
|
+
`${this.codegenHost}/api/v1/projects/${projectId}/code/components?branchName=${branchName}&export=true`,
|
|
731798
|
+
{
|
|
731799
|
+
...opts
|
|
731800
|
+
}
|
|
731801
|
+
);
|
|
731802
|
+
return result.data;
|
|
731803
|
+
}
|
|
731785
731804
|
async projectMeta(projectId) {
|
|
731786
731805
|
const result = await this.post(
|
|
731787
731806
|
`${this.codegenHost}/api/v1/projects/${projectId}/code/meta`
|
|
@@ -733060,7 +733079,8 @@ async function resolveMissingFilesInConfig(context, config) {
|
|
|
733060
733079
|
}
|
|
733061
733080
|
async function getContext(args, {
|
|
733062
733081
|
enableSkipAuth = false,
|
|
733063
|
-
skipMissingFiles = false
|
|
733082
|
+
skipMissingFiles = false,
|
|
733083
|
+
skipInit = false
|
|
733064
733084
|
} = {}) {
|
|
733065
733085
|
if (!args.baseDir)
|
|
733066
733086
|
args.baseDir = process.cwd();
|
|
@@ -734149,25 +734169,7 @@ async function ensureRequiredPackages(context, baseDir, yes) {
|
|
|
734149
734169
|
}
|
|
734150
734170
|
}
|
|
734151
734171
|
}
|
|
734152
|
-
function getLoaderConfigPath(opts) {
|
|
734153
|
-
return opts.loaderConfig || LOADER_CONFIG_FILE_NAME;
|
|
734154
|
-
}
|
|
734155
|
-
function maybeReadLoaderConfig(opts) {
|
|
734156
|
-
const path14 = getLoaderConfigPath(opts);
|
|
734157
|
-
if (!existsBuffered(path14)) {
|
|
734158
|
-
return {};
|
|
734159
|
-
}
|
|
734160
|
-
return JSON.parse(readFileText(path14));
|
|
734161
|
-
}
|
|
734162
|
-
function writeLoaderConfig(opts, config) {
|
|
734163
|
-
const loaderConfigPath = getLoaderConfigPath(opts);
|
|
734164
|
-
writeFileText(
|
|
734165
|
-
loaderConfigPath,
|
|
734166
|
-
formatAsLocal(JSON.stringify(config), loaderConfigPath, opts.baseDir)
|
|
734167
|
-
);
|
|
734168
|
-
}
|
|
734169
734172
|
async function sync(opts, metadataDefaults) {
|
|
734170
|
-
var _a;
|
|
734171
734173
|
if (!opts.baseDir)
|
|
734172
734174
|
opts.baseDir = process.cwd();
|
|
734173
734175
|
const baseDir = opts.baseDir;
|
|
@@ -734181,18 +734183,17 @@ async function sync(opts, metadataDefaults) {
|
|
|
734181
734183
|
}
|
|
734182
734184
|
fixFileExtension(context);
|
|
734183
734185
|
assertAllPathsInRootDir(context);
|
|
734184
|
-
const loaderConfig = process.env.PLASMIC_LOADER ? maybeReadLoaderConfig(opts) : {};
|
|
734185
734186
|
const projectIdToToken = new Map(
|
|
734186
|
-
[...context.config.projects
|
|
734187
|
+
[...context.config.projects].filter((p) => p.projectApiToken).map((p) => tuple(p.projectId, p.projectApiToken))
|
|
734187
734188
|
);
|
|
734188
734189
|
const projectConfigMap = import_lodash17.default.keyBy(context.config.projects, (p) => p.projectId);
|
|
734189
734190
|
const projectWithVersion = opts.projects.map((p) => {
|
|
734190
|
-
var
|
|
734191
|
+
var _a, _b, _c;
|
|
734191
734192
|
const [projectIdToken, versionRange] = p.split("@");
|
|
734192
734193
|
const [projectId, projectApiToken] = projectIdToken.split(":");
|
|
734193
734194
|
return {
|
|
734194
734195
|
projectId,
|
|
734195
|
-
branchName: (_b = (
|
|
734196
|
+
branchName: (_b = (_a = projectConfigMap[projectId]) == null ? void 0 : _a.projectBranchName) != null ? _b : "main",
|
|
734196
734197
|
versionRange: versionRange || ((_c = projectConfigMap[projectId]) == null ? void 0 : _c.version) || "latest",
|
|
734197
734198
|
componentIdOrNames: void 0,
|
|
734198
734199
|
// Get all components!
|
|
@@ -734201,10 +734202,10 @@ async function sync(opts, metadataDefaults) {
|
|
|
734201
734202
|
};
|
|
734202
734203
|
});
|
|
734203
734204
|
const projectSyncParams = projectWithVersion.length ? projectWithVersion : context.config.projects.map((p) => {
|
|
734204
|
-
var
|
|
734205
|
+
var _a;
|
|
734205
734206
|
return {
|
|
734206
734207
|
projectId: p.projectId,
|
|
734207
|
-
branchName: (
|
|
734208
|
+
branchName: (_a = p.projectBranchName) != null ? _a : "main",
|
|
734208
734209
|
versionRange: p.version,
|
|
734209
734210
|
componentIdOrNames: void 0,
|
|
734210
734211
|
// Get all components!
|
|
@@ -734222,7 +734223,7 @@ async function sync(opts, metadataDefaults) {
|
|
|
734222
734223
|
context = await getContext(opts);
|
|
734223
734224
|
} catch (e) {
|
|
734224
734225
|
if (e.message.includes("Unable to authenticate Plasmic")) {
|
|
734225
|
-
const configFileName =
|
|
734226
|
+
const configFileName = CONFIG_FILE_NAME;
|
|
734226
734227
|
throw new HandledError(
|
|
734227
734228
|
`Unable to authenticate Plasmic. Please run 'plasmic auth' or check the projectApiTokens in your ${configFileName}, and try again.`
|
|
734228
734229
|
);
|
|
@@ -734259,7 +734260,6 @@ async function sync(opts, metadataDefaults) {
|
|
|
734259
734260
|
const externalNpmPackages = /* @__PURE__ */ new Set();
|
|
734260
734261
|
const externalCssImports = /* @__PURE__ */ new Set();
|
|
734261
734262
|
const doSync = async () => {
|
|
734262
|
-
var _a2;
|
|
734263
734263
|
for (const projectMeta of projectsToSync) {
|
|
734264
734264
|
await syncProject(
|
|
734265
734265
|
context,
|
|
@@ -734303,21 +734303,6 @@ async function sync(opts, metadataDefaults) {
|
|
|
734303
734303
|
});
|
|
734304
734304
|
}
|
|
734305
734305
|
await fixAllImportStatements(context, opts.baseDir, summary);
|
|
734306
|
-
if (process.env.PLASMIC_LOADER) {
|
|
734307
|
-
const rootProjectIds = new Set(projectSyncParams.map((p) => p.projectId));
|
|
734308
|
-
const freshIdsAndTokens = projectIdsAndTokens.filter((p) => rootProjectIds.has(p.projectId)).map((p) => import_lodash17.default.pick(p, "projectId", "projectApiToken"));
|
|
734309
|
-
const config = {
|
|
734310
|
-
...loaderConfig,
|
|
734311
|
-
projects: import_lodash17.default.sortBy(
|
|
734312
|
-
import_lodash17.default.uniqBy(
|
|
734313
|
-
[...freshIdsAndTokens, ...(_a2 = loaderConfig == null ? void 0 : loaderConfig.projects) != null ? _a2 : []],
|
|
734314
|
-
(p) => p.projectId
|
|
734315
|
-
),
|
|
734316
|
-
(p) => p.projectId
|
|
734317
|
-
)
|
|
734318
|
-
};
|
|
734319
|
-
writeLoaderConfig(opts, config);
|
|
734320
|
-
}
|
|
734321
734306
|
const codegenVersion = await context.api.latestCodegenVersion();
|
|
734322
734307
|
context.lock.projects.forEach((p) => {
|
|
734323
734308
|
if (projectsToSync.some(
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
import { DeepPartial } from "utility-types";
|
|
2
|
-
import { PlasmicApi
|
|
2
|
+
import { PlasmicApi } from "../api";
|
|
3
3
|
export declare const DEFAULT_HOST: string;
|
|
4
4
|
export declare const AUTH_FILE_NAME = ".plasmic.auth";
|
|
5
5
|
export declare const CONFIG_FILE_NAME = "plasmic.json";
|
|
6
6
|
export declare const LOCK_FILE_NAME = "plasmic.lock";
|
|
7
|
-
export declare const LOADER_CONFIG_FILE_NAME = "plasmic-loader.json";
|
|
8
7
|
export declare const CONFIG_SCHEMA_FILE_NAME = "plasmic.schema.json";
|
|
9
8
|
export declare const ENV_AUTH_HOST = "PLASMIC_AUTH_HOST";
|
|
10
9
|
export declare const ENV_AUTH_USER = "PLASMIC_AUTH_USER";
|
|
11
10
|
export declare const ENV_AUTH_TOKEN = "PLASMIC_AUTH_TOKEN";
|
|
12
|
-
export interface PlasmicLoaderConfig {
|
|
13
|
-
projects: ProjectIdAndToken[];
|
|
14
|
-
aboutThisFile: string;
|
|
15
|
-
dir: string;
|
|
16
|
-
plasmicDir: string;
|
|
17
|
-
pageDir: string;
|
|
18
|
-
initArgs: Record<string, string>;
|
|
19
|
-
substitutions?: Record<string, any>;
|
|
20
|
-
}
|
|
21
11
|
export interface PlasmicConfig {
|
|
22
12
|
/** Target platform to generate code for */
|
|
23
13
|
platform: "react" | "nextjs" | "gatsby";
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { CommonArgs } from "../index";
|
|
2
2
|
import { PlasmicContext, PlasmicLock } from "./config-utils";
|
|
3
3
|
export declare function readLock(lockFile: string): PlasmicLock;
|
|
4
|
-
export declare function getContext(args: CommonArgs, { enableSkipAuth, skipMissingFiles, }?: {
|
|
4
|
+
export declare function getContext(args: CommonArgs, { enableSkipAuth, skipMissingFiles, skipInit, }?: {
|
|
5
5
|
enableSkipAuth?: boolean;
|
|
6
6
|
skipMissingFiles?: boolean;
|
|
7
|
+
skipInit?: boolean;
|
|
7
8
|
}): Promise<PlasmicContext>;
|
|
9
|
+
/**
|
|
10
|
+
* Use empty user/token to signify no auth (only returning to provide a default host).
|
|
11
|
+
*/
|
|
12
|
+
export declare function getCurrentOrDefaultAuth(args: CommonArgs): Promise<import("./config-utils").AuthConfig>;
|
|
8
13
|
/**
|
|
9
14
|
* Table of where this metadata will be set
|
|
10
15
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as tmp from "tmp";
|
|
2
|
-
import { AuthConfig, PlasmicConfig
|
|
2
|
+
import { AuthConfig, PlasmicConfig } from "../utils/config-utils";
|
|
3
3
|
export declare class TempRepo {
|
|
4
4
|
tmpDir: tmp.DirResult;
|
|
5
5
|
constructor();
|
|
@@ -17,6 +17,4 @@ export declare class TempRepo {
|
|
|
17
17
|
readPlasmicJson(): PlasmicConfig;
|
|
18
18
|
writePlasmicJson(json: PlasmicConfig): void;
|
|
19
19
|
deletePlasmicJson(): void;
|
|
20
|
-
plasmicLoaderJsonPath(): string;
|
|
21
|
-
readPlasmicLoaderJson(): PlasmicLoaderConfig;
|
|
22
20
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plasmicapp/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.306",
|
|
4
4
|
"description": "plasmic cli for syncing local code with Plasmic designs",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=12"
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"wrap-ansi": "^7.0.0",
|
|
79
79
|
"yargs": "^15.4.1"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "cd709d627ae388ad77010119787ecef6d555362b"
|
|
82
82
|
}
|
|
@@ -158,55 +158,4 @@ describe("Project API tokens", () => {
|
|
|
158
158
|
});
|
|
159
159
|
await expect(sync(opts)).rejects.toThrow("Unable to authenticate");
|
|
160
160
|
});
|
|
161
|
-
|
|
162
|
-
test("should use plasmic-loader.json for API tokens in loader mode", async () => {
|
|
163
|
-
process.env.PLASMIC_LOADER = "1";
|
|
164
|
-
|
|
165
|
-
opts.projects = ["projectId1"];
|
|
166
|
-
await expect(sync(opts)).resolves.toBeUndefined();
|
|
167
|
-
|
|
168
|
-
const loaderConfig = tmpRepo.readPlasmicLoaderJson();
|
|
169
|
-
expect(loaderConfig).toEqual({
|
|
170
|
-
projects: [
|
|
171
|
-
{
|
|
172
|
-
projectId: "projectId1",
|
|
173
|
-
projectApiToken: "abc",
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// Re-run, this time with no auth and no tokens in plasmic.json, only in plasmic-loader.json.
|
|
179
|
-
removeAuth();
|
|
180
|
-
tmpRepo.writePlasmicJson(defaultPlasmicJson);
|
|
181
|
-
await expect(sync(opts)).resolves.toBeUndefined();
|
|
182
|
-
|
|
183
|
-
delete process.env["PLASMIC_LOADER"];
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
test("works in PlasmicLoader mode even if root project was determined to not need an update", async () => {
|
|
187
|
-
process.env.PLASMIC_LOADER = "1";
|
|
188
|
-
|
|
189
|
-
// Make project1 have a dependency.
|
|
190
|
-
standardTestSetup();
|
|
191
|
-
|
|
192
|
-
// Explicitly sync both - we had a bug writing back the plasmic-loader.json in this case.
|
|
193
|
-
opts.projects = ["projectId1", "dependencyId1"];
|
|
194
|
-
await expect(sync(opts)).resolves.toBeUndefined();
|
|
195
|
-
|
|
196
|
-
// We sync project1 which got updated, but the dependency is still same version.
|
|
197
|
-
opts.force = false;
|
|
198
|
-
removeAuth();
|
|
199
|
-
mockApi.getMockProject("projectId1", "main", "1.2.3").version = "1.2.4";
|
|
200
|
-
await expect(sync(opts)).resolves.toBeUndefined();
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
test("should fail in loader mode if not available", async () => {
|
|
204
|
-
process.env.PLASMIC_LOADER = "1";
|
|
205
|
-
|
|
206
|
-
opts.projects = ["projectId1"];
|
|
207
|
-
removeAuth();
|
|
208
|
-
await expect(sync(opts)).rejects.toThrow();
|
|
209
|
-
|
|
210
|
-
delete process.env["PLASMIC_LOADER"];
|
|
211
|
-
});
|
|
212
161
|
});
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { keyBy, snakeCase } from "lodash";
|
|
2
|
+
import { CommonArgs } from "..";
|
|
3
|
+
import { ComponentBundle, PlasmicApi, ProjectBundle } from "../api";
|
|
4
|
+
import {
|
|
5
|
+
CodeConfig,
|
|
6
|
+
I18NConfig,
|
|
7
|
+
ImagesConfig,
|
|
8
|
+
PlasmicConfig,
|
|
9
|
+
StyleConfig,
|
|
10
|
+
findConfigFile,
|
|
11
|
+
} from "../utils/config-utils";
|
|
12
|
+
import { getContext, getCurrentOrDefaultAuth } from "../utils/get-context";
|
|
13
|
+
import { tuple } from "../utils/lang-utils";
|
|
14
|
+
import {
|
|
15
|
+
fixAllImportStatements,
|
|
16
|
+
formatAsLocal,
|
|
17
|
+
maybeConvertTsxToJsx,
|
|
18
|
+
} from "../utils/code-utils";
|
|
19
|
+
import { promises as fs, write } from "fs";
|
|
20
|
+
import path from "path";
|
|
21
|
+
import { DEFAULT_GLOBAL_CONTEXTS_NAME } from "./sync-global-contexts";
|
|
22
|
+
import { ensureImageAssetContents } from "./sync-images";
|
|
23
|
+
import { logger } from "../deps";
|
|
24
|
+
|
|
25
|
+
export interface ExportArgs extends CommonArgs {
|
|
26
|
+
projects: readonly string[];
|
|
27
|
+
platform: "" | "react" | "nextjs" | "gatsby";
|
|
28
|
+
codeLang: "" | "ts" | "js";
|
|
29
|
+
styleScheme: "" | "css" | "css-modules";
|
|
30
|
+
imagesScheme: "" | "inlined" | "files" | "public-files";
|
|
31
|
+
imagesPublicDir: string;
|
|
32
|
+
imagesPublicUrlPrefix: string;
|
|
33
|
+
i18nKeyScheme: "" | I18NConfig["keyScheme"];
|
|
34
|
+
i18nTagPrefix: "" | I18NConfig["tagPrefix"];
|
|
35
|
+
|
|
36
|
+
skipFormatting?: boolean;
|
|
37
|
+
|
|
38
|
+
outDir: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function exportProjectsCli(opts: ExportArgs): Promise<void> {
|
|
42
|
+
if (!opts.baseDir) opts.baseDir = process.cwd();
|
|
43
|
+
let configFile =
|
|
44
|
+
opts.config || findConfigFile(opts.baseDir, { traverseParents: true });
|
|
45
|
+
let context = configFile
|
|
46
|
+
? await getContext(opts, { enableSkipAuth: true })
|
|
47
|
+
: undefined;
|
|
48
|
+
const projectConfigMap = keyBy(
|
|
49
|
+
context?.config.projects ?? [],
|
|
50
|
+
(p) => p.projectId
|
|
51
|
+
);
|
|
52
|
+
const projectIdToToken = new Map(
|
|
53
|
+
[...(context?.config.projects ?? [])]
|
|
54
|
+
.filter((p) => p.projectApiToken)
|
|
55
|
+
.map((p) => tuple(p.projectId, p.projectApiToken))
|
|
56
|
+
);
|
|
57
|
+
const projectWithVersion = opts.projects.map((p) => {
|
|
58
|
+
const [projectIdToken, versionRange] = p.split("@");
|
|
59
|
+
const [projectId, projectApiToken] = projectIdToken.split(":");
|
|
60
|
+
return {
|
|
61
|
+
projectId,
|
|
62
|
+
branchName: projectConfigMap[projectId]?.projectBranchName ?? "main",
|
|
63
|
+
versionRange:
|
|
64
|
+
versionRange || projectConfigMap[projectId]?.version || "latest",
|
|
65
|
+
componentIdOrNames: undefined, // Get all components!
|
|
66
|
+
projectApiToken: projectApiToken || projectIdToToken.get(projectId),
|
|
67
|
+
indirect: false,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const auth = await getCurrentOrDefaultAuth(opts);
|
|
72
|
+
const api = new PlasmicApi(auth);
|
|
73
|
+
const result = await exportProjects(api, {
|
|
74
|
+
projects: projectWithVersion.map((p) => ({
|
|
75
|
+
id: p.projectId,
|
|
76
|
+
token: p.projectApiToken,
|
|
77
|
+
branchName: p.branchName,
|
|
78
|
+
version: p.versionRange,
|
|
79
|
+
})),
|
|
80
|
+
platform: opts.platform || "react",
|
|
81
|
+
codeOpts: { lang: opts.codeLang || "ts" },
|
|
82
|
+
stylesOpts: { scheme: opts.styleScheme || "css-modules" },
|
|
83
|
+
imageOpts: { scheme: opts.imagesScheme || "files" },
|
|
84
|
+
i18nOpts: opts.i18nKeyScheme
|
|
85
|
+
? { keyScheme: opts.i18nKeyScheme, tagPrefix: opts.i18nTagPrefix }
|
|
86
|
+
: undefined,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const extx = opts.codeLang === "js" ? "jsx" : "tsx";
|
|
90
|
+
|
|
91
|
+
const writeProj = async (bundle: ProjectBundle) => {
|
|
92
|
+
await ensureImageAssetContents(bundle.imageAssets);
|
|
93
|
+
const outPath = path.resolve(opts.outDir);
|
|
94
|
+
const promises: Promise<void>[] = [];
|
|
95
|
+
const writeFile = (fileName: string, content: string | Buffer) => {
|
|
96
|
+
if (typeof content === "string" && !opts.skipFormatting) {
|
|
97
|
+
content = formatAsLocal(content, fileName, opts.outDir);
|
|
98
|
+
}
|
|
99
|
+
const projectName = snakeCase(bundle.projectConfig.projectName);
|
|
100
|
+
promises.push(
|
|
101
|
+
(async () => {
|
|
102
|
+
await fs.mkdir(path.join(outPath, projectName), { recursive: true });
|
|
103
|
+
await fs.writeFile(
|
|
104
|
+
path.join(outPath, projectName, fileName),
|
|
105
|
+
content
|
|
106
|
+
);
|
|
107
|
+
})()
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
for (const comp of bundle.components) {
|
|
111
|
+
writeFile(comp.skeletonModuleFileName, comp.skeletonModule);
|
|
112
|
+
writeFile(comp.cssFileName, comp.cssRules);
|
|
113
|
+
}
|
|
114
|
+
for (const icon of bundle.iconAssets) {
|
|
115
|
+
writeFile(icon.fileName, icon.module);
|
|
116
|
+
}
|
|
117
|
+
for (const gv of bundle.globalVariants) {
|
|
118
|
+
writeFile(gv.contextFileName, gv.contextModule);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const img of bundle.imageAssets) {
|
|
122
|
+
writeFile(img.fileName, Buffer.from(img.blob, "base64"));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
writeFile(bundle.projectConfig.cssFileName, bundle.projectConfig.cssRules);
|
|
126
|
+
if (bundle.projectConfig.globalContextBundle) {
|
|
127
|
+
writeFile(
|
|
128
|
+
`${DEFAULT_GLOBAL_CONTEXTS_NAME}.${extx}`,
|
|
129
|
+
bundle.projectConfig.globalContextBundle.contextModule
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await Promise.all(promises);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
await Promise.all(result.map((res) => writeProj(res)));
|
|
137
|
+
|
|
138
|
+
await fixAllImportStatements(
|
|
139
|
+
{
|
|
140
|
+
configFile: "",
|
|
141
|
+
lockFile: "",
|
|
142
|
+
rootDir: path.resolve(opts.outDir),
|
|
143
|
+
absoluteSrcDir: path.resolve(opts.outDir),
|
|
144
|
+
config: {
|
|
145
|
+
platform: opts.platform || "react",
|
|
146
|
+
srcDir: "./",
|
|
147
|
+
defaultPlasmicDir: "./",
|
|
148
|
+
code: {
|
|
149
|
+
lang: opts.codeLang || "ts",
|
|
150
|
+
scheme: "blackbox",
|
|
151
|
+
reactRuntime: "classic",
|
|
152
|
+
},
|
|
153
|
+
images: {
|
|
154
|
+
scheme: opts.imagesScheme || "files",
|
|
155
|
+
publicDir: opts.imagesPublicDir,
|
|
156
|
+
publicUrlPrefix: opts.imagesPublicUrlPrefix,
|
|
157
|
+
},
|
|
158
|
+
style: {
|
|
159
|
+
scheme: opts.styleScheme || "css-modules",
|
|
160
|
+
defaultStyleCssFilePath: "",
|
|
161
|
+
},
|
|
162
|
+
tokens: {} as any,
|
|
163
|
+
globalVariants: {
|
|
164
|
+
variantGroups: result.flatMap((bundle) => {
|
|
165
|
+
const projectName = snakeCase(bundle.projectConfig.projectName);
|
|
166
|
+
return bundle.globalVariants.map((gv) => ({
|
|
167
|
+
id: gv.id,
|
|
168
|
+
name: gv.name,
|
|
169
|
+
projectId: bundle.projectConfig.projectId,
|
|
170
|
+
contextFilePath: `./${projectName}/${gv.contextFileName}`,
|
|
171
|
+
}));
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
projects: result.map((bundle) => {
|
|
175
|
+
const projectName = snakeCase(bundle.projectConfig.projectName);
|
|
176
|
+
return {
|
|
177
|
+
projectId: bundle.projectConfig.projectId,
|
|
178
|
+
projectName: bundle.projectConfig.projectName,
|
|
179
|
+
version: "latest",
|
|
180
|
+
cssFilePath: `${projectName}/${bundle.projectConfig.cssFileName}`,
|
|
181
|
+
globalContextsFilePath: bundle.projectConfig.globalContextBundle
|
|
182
|
+
? `${projectName}/${DEFAULT_GLOBAL_CONTEXTS_NAME}.${extx}`
|
|
183
|
+
: "",
|
|
184
|
+
components: bundle.components.map((comp) => ({
|
|
185
|
+
id: comp.id,
|
|
186
|
+
name: comp.componentName,
|
|
187
|
+
projectId: bundle.projectConfig.projectId,
|
|
188
|
+
type: "managed",
|
|
189
|
+
importSpec: {
|
|
190
|
+
modulePath: `${projectName}/${comp.skeletonModuleFileName}`,
|
|
191
|
+
},
|
|
192
|
+
renderModuleFilePath: `${projectName}/${comp.skeletonModuleFileName}`,
|
|
193
|
+
cssFilePath: `${projectName}/${comp.cssFileName}`,
|
|
194
|
+
scheme: "blackbox",
|
|
195
|
+
componentType: `${comp.isPage ? "page" : "component"}`,
|
|
196
|
+
plumeType: comp.plumeType,
|
|
197
|
+
})),
|
|
198
|
+
codeComponents: bundle.codeComponentMetas.map((comp) => ({
|
|
199
|
+
id: comp.id,
|
|
200
|
+
name: comp.name,
|
|
201
|
+
displayName: comp.displayName,
|
|
202
|
+
componentImportPath: comp.importPath,
|
|
203
|
+
helper: comp.helper,
|
|
204
|
+
})),
|
|
205
|
+
icons: bundle.iconAssets.map((icon) => ({
|
|
206
|
+
id: icon.id,
|
|
207
|
+
name: icon.name,
|
|
208
|
+
moduleFilePath: `${projectName}/${icon.fileName}`,
|
|
209
|
+
})),
|
|
210
|
+
images: bundle.imageAssets.map((image) => ({
|
|
211
|
+
id: image.id,
|
|
212
|
+
name: image.name,
|
|
213
|
+
filePath: `${projectName}/${image.fileName}`,
|
|
214
|
+
})),
|
|
215
|
+
indirect: false,
|
|
216
|
+
};
|
|
217
|
+
}),
|
|
218
|
+
wrapPagesWithGlobalContexts: true,
|
|
219
|
+
},
|
|
220
|
+
lock: {} as any,
|
|
221
|
+
auth: {} as any,
|
|
222
|
+
api: api,
|
|
223
|
+
cliArgs: {} as any,
|
|
224
|
+
},
|
|
225
|
+
opts.outDir
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
interface ExportOpts {
|
|
230
|
+
projects: {
|
|
231
|
+
id: string;
|
|
232
|
+
token?: string;
|
|
233
|
+
branchName?: string;
|
|
234
|
+
version?: string;
|
|
235
|
+
}[];
|
|
236
|
+
platform?: PlasmicConfig["platform"];
|
|
237
|
+
imageOpts?: ImagesConfig;
|
|
238
|
+
stylesOpts?: Omit<StyleConfig, "defaultStyleCssFilePath">;
|
|
239
|
+
i18nOpts?: I18NConfig;
|
|
240
|
+
codeOpts?: Omit<CodeConfig, "scheme" | "reactRuntime">;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function exportProjects(api: PlasmicApi, opts: ExportOpts) {
|
|
244
|
+
api.attachProjectIdsAndTokens(
|
|
245
|
+
opts.projects.map((proj) => ({
|
|
246
|
+
projectId: proj.id,
|
|
247
|
+
projectApiToken: proj.token,
|
|
248
|
+
}))
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
const versionResolution = await api.resolveSync(
|
|
252
|
+
opts.projects.map((p) => ({
|
|
253
|
+
projectId: p.id,
|
|
254
|
+
branchName: p.branchName ?? "main",
|
|
255
|
+
versionRange: p.version,
|
|
256
|
+
componentIdOrNames: undefined,
|
|
257
|
+
projectApiToken: p.token,
|
|
258
|
+
indirect: false,
|
|
259
|
+
})),
|
|
260
|
+
true
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const versionsToSync = [
|
|
264
|
+
...versionResolution.dependencies,
|
|
265
|
+
...versionResolution.projects,
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
const result = await Promise.all(
|
|
269
|
+
versionsToSync.map(async (v) => {
|
|
270
|
+
return api.exportProject(v.projectId, v.branchName, {
|
|
271
|
+
platform: opts.platform ?? "react",
|
|
272
|
+
platformOptions: {},
|
|
273
|
+
version: v.version,
|
|
274
|
+
imageOpts: opts.imageOpts ?? {
|
|
275
|
+
scheme: "files",
|
|
276
|
+
},
|
|
277
|
+
stylesOpts: {
|
|
278
|
+
defaultStyleCssFilePath: "",
|
|
279
|
+
scheme: "css-modules",
|
|
280
|
+
...opts.stylesOpts,
|
|
281
|
+
},
|
|
282
|
+
i18nOpts: opts.i18nOpts,
|
|
283
|
+
codeOpts: opts.codeOpts ?? { lang: "ts" },
|
|
284
|
+
indirect: v.indirect,
|
|
285
|
+
wrapPagesWithGlobalContexts: true,
|
|
286
|
+
});
|
|
287
|
+
})
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (opts.codeOpts?.lang === "js") {
|
|
291
|
+
for (const proj of result) {
|
|
292
|
+
for (const comp of proj.components) {
|
|
293
|
+
[comp.skeletonModuleFileName, comp.skeletonModule] =
|
|
294
|
+
maybeConvertTsxToJsx(
|
|
295
|
+
comp.skeletonModuleFileName,
|
|
296
|
+
comp.skeletonModule,
|
|
297
|
+
"."
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
for (const icon of proj.iconAssets) {
|
|
301
|
+
[icon.fileName, icon.module] = maybeConvertTsxToJsx(
|
|
302
|
+
icon.fileName,
|
|
303
|
+
icon.module,
|
|
304
|
+
"."
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
for (const gv of proj.globalVariants) {
|
|
308
|
+
[gv.contextFileName, gv.contextModule] = maybeConvertTsxToJsx(
|
|
309
|
+
gv.contextFileName,
|
|
310
|
+
gv.contextModule,
|
|
311
|
+
"."
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
if (proj.projectConfig.globalContextBundle) {
|
|
315
|
+
const res = maybeConvertTsxToJsx(
|
|
316
|
+
`${DEFAULT_GLOBAL_CONTEXTS_NAME}.tsx`,
|
|
317
|
+
proj.projectConfig.globalContextBundle.contextModule,
|
|
318
|
+
"."
|
|
319
|
+
);
|
|
320
|
+
proj.projectConfig.globalContextBundle.contextModule = res[1];
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
@@ -22,6 +22,25 @@ export interface LocalizationStringsArgs extends CommonArgs {
|
|
|
22
22
|
excludeDeps: boolean | undefined;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export function getLocalizationYargs(key: "key-scheme" | "tag-prefix") {
|
|
26
|
+
if (key === "key-scheme") {
|
|
27
|
+
return {
|
|
28
|
+
describe:
|
|
29
|
+
"What value to use as message keys; `content` uses the message content itself, `hash` uses a hash of the content, and `path` uses a a hierarchical string containing the project id, component name, element name, and related variants, and does not encode the text content in the key. Defaults to whatever is specified in plasmic.json, or `content`",
|
|
30
|
+
type: "string" as const,
|
|
31
|
+
choices: ["content", "hash", "path"],
|
|
32
|
+
};
|
|
33
|
+
} else if (key === "tag-prefix") {
|
|
34
|
+
return {
|
|
35
|
+
describe:
|
|
36
|
+
"By default, rich text with markup tags look like '<0>hello</0>'. If your localization framework requires num-numeric tags, then specify a prefix; for example a prefix of 'n' turns it into '<n0>hello</n0>'.",
|
|
37
|
+
type: "string" as const,
|
|
38
|
+
};
|
|
39
|
+
} else {
|
|
40
|
+
throw new Error(`Unexpected localization option ${key}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
25
44
|
export async function localizationStrings(
|
|
26
45
|
opts: LocalizationStringsArgs
|
|
27
46
|
): Promise<void> {
|
|
@@ -233,7 +233,7 @@ export async function syncProjectComponents(
|
|
|
233
233
|
|
|
234
234
|
compConfig.plumeType = plumeType;
|
|
235
235
|
|
|
236
|
-
if (scheme === "direct") {
|
|
236
|
+
if ((scheme as any) === "direct") {
|
|
237
237
|
throw new Error(`Direct update codegen scheme is no longer supported`);
|
|
238
238
|
} else if (/\/\/\s*plasmic-managed-jsx\/\d+/.test(editedFile)) {
|
|
239
239
|
if (forceOverwrite) {
|
|
@@ -130,7 +130,7 @@ export async function syncProjectImageAssets(
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
async function ensureImageAssetContents(bundles: ImageBundle[]) {
|
|
133
|
+
export async function ensureImageAssetContents(bundles: ImageBundle[]) {
|
|
134
134
|
// The server may send images as a url instead of a base64 blob. In that
|
|
135
135
|
// case, we fetch the images here in the cli, instead of on the server.
|
|
136
136
|
// If you have a lot of images, this moves the expensive / long fetch
|