@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
package/src/index.ts ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+ import semver from "semver";
3
+ import updateNotifier from "update-notifier";
4
+ import yargs from "yargs";
5
+ import * as auth from "./actions/auth";
6
+ import { fixImports, FixImportsArgs } from "./actions/fix-imports";
7
+ import { getYargsOption, InitArgs, initPlasmic } from "./actions/init";
8
+ import * as projectToken from "./actions/project-token";
9
+ import { sync, SyncArgs } from "./actions/sync";
10
+ import { UploadBundleArgs, uploadJsBundle } from "./actions/upload-bundle";
11
+ import { WatchArgs, watchProjects } from "./actions/watch";
12
+ import { LOADER_CONFIG_FILE_NAME } from "./utils/config-utils";
13
+ import { handleError } from "./utils/error";
14
+
15
+ if (process.env.DEBUG_CHDIR) {
16
+ process.chdir(process.env.DEBUG_CHDIR);
17
+ }
18
+
19
+ // Check once an hour
20
+ const pkg = require("../package.json");
21
+ const notifier = updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 });
22
+ // Workaround for this bug
23
+ // https://github.com/yeoman/update-notifier/issues/181
24
+ if (
25
+ !!notifier.update &&
26
+ semver.gt(notifier.update.latest, notifier.update.current)
27
+ ) {
28
+ notifier.notify();
29
+ }
30
+
31
+ yargs
32
+ .usage("Usage: $0 <command> [options]")
33
+ .option("auth", {
34
+ describe:
35
+ "Plasmic auth file to use; by default, uses ~/.plasmic.auth, or the first .plasmic.auth file found in current and parent directories",
36
+ })
37
+ .option("config", {
38
+ describe:
39
+ "Plasmic config file to use; by default, uses the first plasmic.json file found in the current or parent directories",
40
+ })
41
+ .option("yes", {
42
+ type: "boolean",
43
+ describe: "Automatic yes to prompts.",
44
+ default: false,
45
+ })
46
+ .command<InitArgs>(
47
+ "init",
48
+ "Initializes Plasmic for a project.",
49
+ (yags) => {
50
+ yags
51
+ .option("enable-skip-auth", {
52
+ describe: "Enable skipping auth, just initialize a plasmic.json",
53
+ type: "boolean",
54
+ default: false,
55
+ })
56
+ .option("host", getYargsOption("host", "https://studio.plasmic.app"))
57
+ .option("platform", getYargsOption("platform"))
58
+ .option("code-lang", getYargsOption("codeLang"))
59
+ .option("code-scheme", getYargsOption("codeScheme"))
60
+ .option("react-runtime", {
61
+ describe: "React runtime to use; either classic or automatic",
62
+ choices: ["classic", "automatic"],
63
+ default: "classic",
64
+ })
65
+ .option("src-dir", getYargsOption("srcDir"))
66
+ .option("plasmic-dir", getYargsOption("plasmicDir"))
67
+ .option("pages-dir", getYargsOption("pagesDir"))
68
+ .option("style-scheme", getYargsOption("styleScheme"))
69
+ .option("images-scheme", getYargsOption("imagesScheme"))
70
+ .option("images-public-dir", getYargsOption("imagesPublicDir"))
71
+ .option(
72
+ "images-public-url-prefix",
73
+ getYargsOption("imagesPublicUrlPrefix")
74
+ );
75
+ },
76
+ (argv) => handleError(initPlasmic(argv))
77
+ )
78
+ .command<auth.AuthArgs>(
79
+ "auth",
80
+ "Authenticates you to plasmic.",
81
+ (yags) => {
82
+ yags
83
+ .option("host", {
84
+ describe: "Plasmic host to use",
85
+ type: "string",
86
+ default: "https://studio.plasmic.app",
87
+ })
88
+ .option("check", {
89
+ alias: "c",
90
+ describe: "Just verifies if the current credentials are valid.",
91
+ type: "boolean",
92
+ })
93
+ .option("email", {
94
+ describe:
95
+ "Print the email of the currently authenticated user and exit.",
96
+ type: "boolean",
97
+ });
98
+ },
99
+ (argv) => {
100
+ handleError(auth.auth(argv));
101
+ }
102
+ )
103
+ .command<SyncArgs>(
104
+ "sync",
105
+ "Syncs designs from Plasmic to local files.",
106
+ (yags) => configureSyncArgs(yags),
107
+ (argv) => {
108
+ handleError(
109
+ sync(argv, {
110
+ source: "cli",
111
+ scheme: "codegen",
112
+ command: "sync",
113
+ })
114
+ );
115
+ }
116
+ )
117
+ .command<WatchArgs>(
118
+ "watch",
119
+ "Watches for updates to projects, and syncs them automatically to local files.",
120
+ (yags) => configureSyncArgs(yags, false),
121
+ (argv) => {
122
+ handleError(
123
+ watchProjects(argv, {
124
+ source: "cli",
125
+ scheme: "codegen",
126
+ command: "watch",
127
+ })
128
+ );
129
+ }
130
+ )
131
+ .command<FixImportsArgs>(
132
+ "fix-imports",
133
+ "Fixes import paths after you've moved around Plasmic blackbox files",
134
+ (yags) => 0,
135
+ (argv) => handleError(fixImports(argv))
136
+ )
137
+ .command<UploadBundleArgs>(
138
+ "upload-bundle",
139
+ false,
140
+ (yargs) =>
141
+ yargs
142
+ .option("project", {
143
+ alias: "p",
144
+ describe: "ID of Plasmic project to upload the bundle to.",
145
+ type: "string",
146
+ })
147
+ .option("bundleName", {
148
+ describe: "Name of the bundle",
149
+ type: "string",
150
+ })
151
+ .option("bundleJsFile", {
152
+ describe: "Path of the bundled Javascript file in AMD format",
153
+ type: "string",
154
+ })
155
+ .option("cssFiles", {
156
+ describe: "Path of the bundled css files to load",
157
+ type: "array",
158
+ default: [],
159
+ })
160
+ .option("metaJsonFile", {
161
+ describe:
162
+ "Path of the meta data file (in JSON format) describing the component",
163
+ type: "string",
164
+ })
165
+ .option("extraPropMetaJsonFile", {
166
+ describe:
167
+ "Path of the extra meta data file (in JSON format) describing the component's additional controlled properties and initial properties",
168
+ type: "string",
169
+ })
170
+ .option("pkgVersion", {
171
+ describe:
172
+ "version of the package to include in the generated package.json",
173
+ type: "string",
174
+ default: "latest",
175
+ })
176
+ .option("genModulePath", {
177
+ describe:
178
+ "the path of include when generating import statement and generate package.json for. Default to bundleName.",
179
+ type: "string",
180
+ })
181
+ .option("themeProviderWrapper", {
182
+ describe: "the wrapper that inject theme to the bundle.",
183
+ type: "string",
184
+ })
185
+ .option("themeModuleFile", {
186
+ describe:
187
+ "the typescript file that contains and exports the implementation of themeProviderWrapper. Used for code generation. It must be specified together with themeProviderWrapper.",
188
+ type: "string",
189
+ })
190
+ .option("genCssPaths", {
191
+ describe:
192
+ "the list of css paths to import in generate code whenever a component in this bundle is used",
193
+ type: "array",
194
+ default: [],
195
+ }),
196
+ (argv) => handleError(uploadJsBundle(argv))
197
+ )
198
+ .command<projectToken.ProjectTokenArgs>(
199
+ "project-token <projectId>",
200
+ "Get projectApiToken for a given project",
201
+ (yargs) =>
202
+ yargs
203
+ .positional("projectId", {
204
+ describe: "projectId",
205
+ type: "string",
206
+ })
207
+ .option("host", {
208
+ describe: "Plasmic host to use",
209
+ type: "string",
210
+ default: "https://studio.plasmic.app",
211
+ }),
212
+ (argv) => handleError(projectToken.projectToken(argv))
213
+ )
214
+ .demandCommand()
215
+ .strict()
216
+ .help("h")
217
+ .alias("h", "help").argv;
218
+
219
+ function configureSyncArgs(
220
+ yags: yargs.Argv,
221
+ includeQuietOption: boolean = true
222
+ ) {
223
+ let args = yags
224
+ .option("projects", {
225
+ alias: "p",
226
+ describe:
227
+ "One or more projects to sync, separated by comma. Version constraints can be specified using @. Example: projectid, projectid@>=version",
228
+ type: "array",
229
+ default: [],
230
+ })
231
+ .option("force", {
232
+ type: "boolean",
233
+ describe: "Force sync to bypass specified version ranges.",
234
+ default: false,
235
+ })
236
+ .option("loader-config", {
237
+ type: "string",
238
+ describe:
239
+ "Path to loader config file, and causes CLI to run in PlasmicLoader mode.",
240
+ hidden: true,
241
+ default: LOADER_CONFIG_FILE_NAME,
242
+ })
243
+ .option("non-recursive", {
244
+ type: "boolean",
245
+ describe:
246
+ "Do not recursively sync dependencies, only sync the specified projects",
247
+ default: false,
248
+ })
249
+ .option("force-overwrite", {
250
+ type: "boolean",
251
+ describe:
252
+ "Overwrite the skeleton file with newly generated version. Useful when switching between codegen schemes.",
253
+ default: false,
254
+ })
255
+ .option("append-jsx-on-missing-base", {
256
+ type: "boolean",
257
+ describe:
258
+ "When the base metadata is missing to perform the three-way merge for direct edit component, append the jsx of the new version so that user can perform manual merge.",
259
+ default: false,
260
+ })
261
+ .option("new-component-scheme", {
262
+ type: "string",
263
+ choices: ["blackbox", "direct"],
264
+ describe:
265
+ "Sync the new components using this code scheme rather than the default code scheme.",
266
+ })
267
+ .option("ignore-post-sync", {
268
+ type: "boolean",
269
+ describe: "Ignore post-sync commands in plasmic.json",
270
+ default: false,
271
+ })
272
+ .option("metadata", {
273
+ type: "string",
274
+ describe:
275
+ "Pass metadata through to the server. Use querystring format (e.g. command=sync&source=cli&cli_version=1.0.0",
276
+ default: "source=cli",
277
+ hidden: true,
278
+ })
279
+ .option("all-files", {
280
+ type: "boolean",
281
+ describe:
282
+ "Sync all files, including those that haven't changed since last sync",
283
+ default: "",
284
+ });
285
+ if (includeQuietOption) {
286
+ args = args.option("quiet", {
287
+ type: "boolean",
288
+ describe: "Do not inform each asset to be synced",
289
+ default: false,
290
+ });
291
+ }
292
+ return args;
293
+ }
294
+
295
+ export interface CommonArgs {
296
+ baseDir: string;
297
+ auth?: string;
298
+ config?: string;
299
+ yes?: boolean;
300
+ }
package/src/lib.ts ADDED
@@ -0,0 +1,10 @@
1
+ export { auth, AuthArgs } from "./actions/auth";
2
+ export { fixImports, FixImportsArgs } from "./actions/fix-imports";
3
+ export { InitArgs, initPlasmic } from "./actions/init";
4
+ export { getProjectApiToken } from "./actions/project-token";
5
+ export { sync, SyncArgs } from "./actions/sync";
6
+ export { UploadBundleArgs, uploadJsBundle } from "./actions/upload-bundle";
7
+ export { WatchArgs, watchProjects } from "./actions/watch";
8
+ export { logger } from "./deps";
9
+ export { HandledError, handleError } from "./utils/error";
10
+ export { Metadata, setMetadataEnv } from "./utils/get-context";
@@ -0,0 +1,16 @@
1
+ import { PlasmicLock } from "../utils/config-utils";
2
+
3
+ export function ensureFileLocks(lock: PlasmicLock) {
4
+ for (const project of lock.projects) {
5
+ // Ensure all `ProjectLock`s have `fileLock` array
6
+ if (!project.fileLocks) {
7
+ project.fileLocks = [];
8
+ }
9
+ // Ensure all `FileLock`s have valid checksums
10
+ project.fileLocks = project.fileLocks.filter(
11
+ (fileLock) =>
12
+ typeof fileLock.checksum === "string" && fileLock.checksum.length === 32
13
+ );
14
+ }
15
+ return lock;
16
+ }
@@ -0,0 +1,8 @@
1
+ import { PlasmicConfig } from "../utils/config-utils";
2
+
3
+ export function ensureReactRuntime(config: PlasmicConfig) {
4
+ if (!config.code.reactRuntime) {
5
+ config.code.reactRuntime = "classic";
6
+ }
7
+ return config;
8
+ }
@@ -0,0 +1,4 @@
1
+ export function migrateInit(prev: any) {
2
+ // Just stamping the first migration
3
+ return prev;
4
+ }
@@ -0,0 +1,37 @@
1
+ import glob from "glob";
2
+ import L from "lodash";
3
+ import path from "upath";
4
+ import { logger } from "../deps";
5
+ import { PlasmicConfig } from "../utils/config-utils";
6
+ import {
7
+ existsBuffered,
8
+ findSrcDirPath,
9
+ renameFileBuffered,
10
+ } from "../utils/file-utils";
11
+ import { MigrateContext } from "./migrations";
12
+
13
+ export function tsToTsx(config: PlasmicConfig, context: MigrateContext) {
14
+ const srcDir = context.absoluteSrcDir;
15
+ const allFiles = glob.sync(`${srcDir}/**/*.+(ts)`, {
16
+ ignore: [`${srcDir}/**/node_modules/**/*`],
17
+ });
18
+ const existingFiles = L.groupBy(allFiles, (f) => path.basename(f));
19
+ config.projects.forEach((project) => {
20
+ project.components.forEach((c) => {
21
+ if (c.renderModuleFilePath.endsWith("ts")) {
22
+ const relFilePath = findSrcDirPath(
23
+ context.absoluteSrcDir,
24
+ c.renderModuleFilePath,
25
+ existingFiles
26
+ );
27
+ const absFilePath = path.join(context.absoluteSrcDir, relFilePath);
28
+ if (existsBuffered(absFilePath)) {
29
+ logger.info(`rename file from ${absFilePath} to ${absFilePath}x`);
30
+ renameFileBuffered(absFilePath, `${absFilePath}x`);
31
+ }
32
+ c.renderModuleFilePath = `${c.renderModuleFilePath}x`;
33
+ }
34
+ });
35
+ });
36
+ return config;
37
+ }
@@ -0,0 +1,10 @@
1
+ import { PlasmicConfig } from "../utils/config-utils";
2
+
3
+ export function ensureProjectIcons(config: PlasmicConfig) {
4
+ for (const proj of config.projects) {
5
+ if (!proj.icons) {
6
+ proj.icons = [];
7
+ }
8
+ }
9
+ return config;
10
+ }
@@ -0,0 +1,10 @@
1
+ import { PlasmicConfig } from "../utils/config-utils";
2
+
3
+ export function ensureVersion(config: PlasmicConfig) {
4
+ for (const proj of config.projects) {
5
+ if (!proj.version) {
6
+ proj.version = "latest";
7
+ }
8
+ }
9
+ return config;
10
+ }
@@ -0,0 +1,10 @@
1
+ import { PlasmicConfig } from "../utils/config-utils";
2
+
3
+ export function ensureJsBundleThemes(config: PlasmicConfig) {
4
+ for (const proj of config.projects) {
5
+ if (!proj.jsBundleThemes) {
6
+ proj.jsBundleThemes = [];
7
+ }
8
+ }
9
+ return config;
10
+ }
@@ -0,0 +1,15 @@
1
+ import { PlasmicConfig } from "../utils/config-utils";
2
+
3
+ export function ensureImageFiles(config: PlasmicConfig) {
4
+ if (!config.images) {
5
+ config.images = {
6
+ scheme: "inlined",
7
+ };
8
+ }
9
+ for (const proj of config.projects) {
10
+ if (!proj.images) {
11
+ proj.images = [];
12
+ }
13
+ }
14
+ return config;
15
+ }
@@ -0,0 +1,14 @@
1
+ import { PlasmicConfig } from "../utils/config-utils";
2
+
3
+ export function ensureComponentType(config: PlasmicConfig) {
4
+ for (const project of config.projects) {
5
+ for (const component of project.components) {
6
+ if (component.componentType) {
7
+ continue;
8
+ }
9
+ const [_, componentPath] = component.importSpec.modulePath.split(/pages/);
10
+ component.componentType = componentPath ? "page" : "component";
11
+ }
12
+ }
13
+ return config;
14
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Super simple migration framework for cli.
3
+ *
4
+ * If you want to run some migration script (say, to fix up the schema of plasmic.json, etc),
5
+ * you should:
6
+ *
7
+ * 1. Bump your cli version.
8
+ * 2. Add a [version]-[desc].ts file to the migrations folder, exporting a function that takes
9
+ * the previous version of plasmic.json (or plasmic.lock) blob, and returns the new version
10
+ * of plasmic.json (or plasmic.lock) blob.
11
+ * 3. Add the migration function to the MIGRATIONS (or LOCK_MIGRATIONS) dict in this file.
12
+ *
13
+ * The framework will run migrations in sequence, so you are guaranteed that the plasmic.json blob
14
+ * passed into your migration function is valid as of the previous version.
15
+ */
16
+ import chalk from "chalk";
17
+ import L from "lodash";
18
+ import semver from "semver";
19
+ import path from "upath";
20
+ import { logger } from "../deps";
21
+ import {
22
+ PlasmicConfig,
23
+ PlasmicLock,
24
+ readConfig,
25
+ writeConfig,
26
+ writeLock,
27
+ } from "../utils/config-utils";
28
+ import { HandledError } from "../utils/error";
29
+ import { existsBuffered, readFileText } from "../utils/file-utils";
30
+ import {
31
+ getCliVersion,
32
+ installUpgrade,
33
+ isCliGloballyInstalled,
34
+ } from "../utils/npm-utils";
35
+ import { confirmWithUser } from "../utils/user-utils";
36
+ import { ensureFileLocks } from "./0.1.110-fileLocks";
37
+ import { ensureReactRuntime } from "./0.1.146-addReactRuntime";
38
+ import { migrateInit } from "./0.1.27-migrateInit";
39
+ import { tsToTsx } from "./0.1.28-tsToTsx";
40
+ import { ensureProjectIcons } from "./0.1.31-ensureProjectIcons";
41
+ import { ensureVersion } from "./0.1.42-ensureVersion";
42
+ import { ensureJsBundleThemes } from "./0.1.57-ensureJsBundleThemes";
43
+ import { ensureImageFiles } from "./0.1.64-imageFiles";
44
+ import { ensureComponentType } from "./0.1.95-componentType";
45
+ export interface MigrateContext {
46
+ absoluteSrcDir: string;
47
+ }
48
+
49
+ type MigrateConfigFunc = (
50
+ prev: PlasmicConfig,
51
+ context: MigrateContext
52
+ ) => PlasmicConfig;
53
+ type MigrateLockFunc = (
54
+ prev: PlasmicLock,
55
+ context: MigrateContext
56
+ ) => PlasmicLock;
57
+
58
+ export const MIGRATIONS: Record<string, MigrateConfigFunc> = {
59
+ "0.1.27": migrateInit,
60
+ "0.1.28": tsToTsx,
61
+ "0.1.31": ensureProjectIcons,
62
+ "0.1.42": ensureVersion,
63
+ "0.1.57": ensureJsBundleThemes,
64
+ "0.1.64": ensureImageFiles,
65
+ "0.1.95": ensureComponentType,
66
+ "0.1.146": ensureReactRuntime,
67
+ };
68
+
69
+ export const LOCK_MIGRATIONS: Record<string, MigrateLockFunc> = {
70
+ "0.1.110": ensureFileLocks,
71
+ };
72
+
73
+ export async function runNecessaryMigrations(
74
+ configFile: string,
75
+ lockFile: string,
76
+ baseDir: string,
77
+ yes?: boolean
78
+ ) {
79
+ const cliVersion = getCliVersion();
80
+ // If we don't have a lock file, we don't need to run migrations on it!
81
+ const maybeReadLock = (): PlasmicLock | undefined => {
82
+ if (existsBuffered(lockFile)) {
83
+ return JSON.parse(readFileText(lockFile));
84
+ }
85
+ return undefined;
86
+ };
87
+ const cur = readConfig(configFile, false);
88
+ const curVersion: string | undefined = cur.cliVersion;
89
+
90
+ if (!!curVersion && semver.lt(cliVersion, curVersion)) {
91
+ const confirm = await confirmWithUser(
92
+ `Project requires @plasmicapp/cli>=${curVersion} (You currently have ${cliVersion}). Would you like to upgrade it?`,
93
+ yes
94
+ );
95
+ if (!confirm) {
96
+ throw new HandledError("Upgrading is required to continue.");
97
+ }
98
+
99
+ const success = installUpgrade("@plasmicapp/cli", baseDir, {
100
+ global: isCliGloballyInstalled(path.dirname(configFile)),
101
+ dev: true,
102
+ });
103
+
104
+ logger.info(
105
+ chalk.bold("@plasmicapp/cli has been upgraded; please try again!")
106
+ );
107
+
108
+ throw new HandledError(success ? "" : "Error upgrading @plasmicapp/cli");
109
+ }
110
+
111
+ const context: MigrateContext = {
112
+ absoluteSrcDir: path.isAbsolute(cur.srcDir)
113
+ ? cur.srcDir
114
+ : path.resolve(path.dirname(configFile), cur.srcDir),
115
+ };
116
+ const greaterVersions = semver.sort(
117
+ [...L.keys(MIGRATIONS), ...L.keys(LOCK_MIGRATIONS)].filter(
118
+ (v) => !curVersion || semver.gt(v, curVersion)
119
+ )
120
+ );
121
+ for (const version of greaterVersions) {
122
+ logger.info(`Migrating to plasmic.json version ${version}`);
123
+ const migrationFunc = MIGRATIONS[version];
124
+ if (migrationFunc !== undefined) {
125
+ const prev = readConfig(configFile, false);
126
+ const next = migrationFunc(prev, context);
127
+ next.cliVersion = version;
128
+ await writeConfig(configFile, next, baseDir);
129
+ }
130
+
131
+ const lockMigrationFunc = LOCK_MIGRATIONS[version];
132
+ if (lockMigrationFunc !== undefined) {
133
+ const prev = maybeReadLock();
134
+ if (prev) {
135
+ const next = lockMigrationFunc(prev, context);
136
+ await writeLock(lockFile, next, baseDir);
137
+ }
138
+ }
139
+ }
140
+
141
+ // Finally, stamp the latest version
142
+ const latestConfig = readConfig(configFile, false);
143
+ if (latestConfig.cliVersion !== cliVersion) {
144
+ latestConfig.cliVersion = cliVersion;
145
+ await writeConfig(configFile, latestConfig, baseDir);
146
+ }
147
+ }