@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,638 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+ import L from "lodash";
4
+ import path from "upath";
5
+ import { CommonArgs } from "..";
6
+ import { logger } from "../deps";
7
+ import { getOrStartAuth } from "../utils/auth-utils";
8
+ import {
9
+ CONFIG_FILE_NAME,
10
+ DEFAULT_CONFIG,
11
+ DEFAULT_PUBLIC_FILES_CONFIG,
12
+ fillDefaults,
13
+ findConfigFile,
14
+ isPageAwarePlatform,
15
+ PlasmicConfig,
16
+ writeConfig,
17
+ } from "../utils/config-utils";
18
+ import {
19
+ detectCreateReactApp,
20
+ detectGatsby,
21
+ detectNextJs,
22
+ detectTypescript,
23
+ } from "../utils/envdetect";
24
+ import { existsBuffered } from "../utils/file-utils";
25
+ import { ensure, ensureString } from "../utils/lang-utils";
26
+ import {
27
+ findPackageJsonDir,
28
+ getCliVersion,
29
+ installUpgrade,
30
+ } from "../utils/npm-utils";
31
+ import { confirmWithUser } from "../utils/user-utils";
32
+
33
+ export interface InitArgs extends CommonArgs {
34
+ host: string;
35
+ platform: "" | "react" | "nextjs" | "gatsby";
36
+ codeLang: "" | "ts" | "js";
37
+ codeScheme: "" | "blackbox" | "direct";
38
+ styleScheme: "" | "css" | "css-modules";
39
+ imagesScheme: "" | "inlined" | "files" | "public-files";
40
+ imagesPublicDir: string;
41
+ imagesPublicUrlPrefix: string;
42
+ srcDir: string;
43
+ plasmicDir: string;
44
+ pagesDir?: string;
45
+ enableSkipAuth?: boolean;
46
+ reactRuntime?: "classic" | "automatic";
47
+ }
48
+
49
+ export async function initPlasmic(
50
+ opts: InitArgs & { enableSkipAuth?: boolean }
51
+ ) {
52
+ if (!opts.baseDir) opts.baseDir = process.cwd();
53
+ await getOrStartAuth(opts);
54
+
55
+ const configFile =
56
+ opts.config || findConfigFile(opts.baseDir, { traverseParents: false });
57
+ if (configFile && existsBuffered(configFile)) {
58
+ logger.error(
59
+ "You already have a plasmic.json file! Please either delete or edit it directly."
60
+ );
61
+ return;
62
+ }
63
+
64
+ // path to plasmic.json
65
+ const newConfigFile =
66
+ opts.config || path.join(opts.baseDir, CONFIG_FILE_NAME);
67
+
68
+ const answers = await deriveInitAnswers(opts);
69
+ await writeConfig(newConfigFile, createInitConfig(answers), opts.baseDir);
70
+
71
+ if (!process.env.QUIET) {
72
+ logger.info("Successfully created plasmic.json.\n");
73
+ }
74
+
75
+ const answer = await confirmWithUser(
76
+ "@plasmicapp/react-web is a small runtime required by Plasmic-generated code.\n Do you want to add it now?",
77
+ opts.yes
78
+ );
79
+ if (answer) {
80
+ installUpgrade("@plasmicapp/react-web", opts.baseDir);
81
+ }
82
+ }
83
+
84
+ function createInitConfig(opts: Omit<InitArgs, "baseDir">): PlasmicConfig {
85
+ return fillDefaults({
86
+ srcDir: opts.srcDir,
87
+ defaultPlasmicDir: opts.plasmicDir,
88
+ ...(opts.platform === "nextjs" && {
89
+ nextjsConfig: {
90
+ pagesDir: opts.pagesDir,
91
+ },
92
+ }),
93
+ ...(opts.platform === "gatsby" && {
94
+ gatsbyConfig: {
95
+ pagesDir: opts.pagesDir,
96
+ },
97
+ }),
98
+ code: {
99
+ ...(opts.codeLang && { lang: opts.codeLang }),
100
+ ...(opts.codeScheme && { scheme: opts.codeScheme }),
101
+ ...(opts.reactRuntime && { reactRuntime: opts.reactRuntime }),
102
+ },
103
+ style: {
104
+ ...(opts.styleScheme && { scheme: opts.styleScheme }),
105
+ },
106
+ images: {
107
+ ...(opts.imagesScheme && { scheme: opts.imagesScheme }),
108
+ ...(opts.imagesScheme && { publicDir: opts.imagesPublicDir }),
109
+ ...(opts.imagesScheme && { publicUrlPrefix: opts.imagesPublicUrlPrefix }),
110
+ },
111
+ ...(opts.platform && { platform: opts.platform }),
112
+ cliVersion: getCliVersion(),
113
+ });
114
+ }
115
+
116
+ type DefaultDeriver = {
117
+ [T in keyof Omit<InitArgs, "baseDir">]?:
118
+ | string
119
+ | ((srcDir: string) => string);
120
+ } & {
121
+ alwaysDerived: (keyof Omit<InitArgs, "baseDir">)[];
122
+ };
123
+
124
+ /**
125
+ * A simpler subset of the DistinctQuestion interface that we actually use.
126
+ */
127
+ interface SimpleQuestion {
128
+ name: string;
129
+ message: string;
130
+ type?: "list";
131
+ choices?: () => { name: string; value: string }[];
132
+ }
133
+
134
+ /**
135
+ * Pretty-print the question along with the default answer, as if that was the choice
136
+ * being made. Don't actually interactively prompt for a response.
137
+ */
138
+ function simulatePrompt(
139
+ question: SimpleQuestion,
140
+ defaultAnswer: string | boolean | undefined,
141
+ bold = false
142
+ ) {
143
+ const message = question.message.endsWith(">")
144
+ ? question.message
145
+ : question.message + ">";
146
+ process.stdout.write((bold ? chalk.bold(message) : message) + " ");
147
+ logger.info(
148
+ chalk.cyan(
149
+ question.choices?.().find((choice) => choice.value === defaultAnswer)
150
+ ?.name ?? defaultAnswer
151
+ )
152
+ );
153
+ }
154
+
155
+ async function deriveInitAnswers(
156
+ opts: Partial<InitArgs> & { baseDir: string }
157
+ ) {
158
+ const plasmicRootDir = opts.config ? path.dirname(opts.config) : opts.baseDir;
159
+
160
+ const platform = !!opts.platform
161
+ ? opts.platform
162
+ : detectNextJs()
163
+ ? "nextjs"
164
+ : detectGatsby()
165
+ ? "gatsby"
166
+ : "react";
167
+ const isCra = detectCreateReactApp();
168
+ const isNext = platform === "nextjs";
169
+ const isGatsby = platform === "gatsby";
170
+ const isGeneric = !isCra && !isNext && !isGatsby;
171
+ const isTypescript = detectTypescript();
172
+
173
+ if (isNext) {
174
+ logger.info("Detected Next.js...");
175
+ } else if (isGatsby) {
176
+ logger.info("Detected Gatsby...");
177
+ } else if (isCra) {
178
+ logger.info("Detected create-react-app...");
179
+ }
180
+
181
+ // Platform-specific defaults that take precedent
182
+ const deriver = isNext
183
+ ? getNextDefaults(plasmicRootDir)
184
+ : isGatsby
185
+ ? getGatsbyDefaults(plasmicRootDir)
186
+ : isCra
187
+ ? getCraDefaults(plasmicRootDir)
188
+ : getGenericDefaults(plasmicRootDir);
189
+ const srcDir = ensureString(deriver.srcDir);
190
+
191
+ const getDefaultAnswer = (
192
+ name: keyof Omit<InitArgs, "baseDir">,
193
+ defaultAnswer?: string
194
+ ) => {
195
+ // Try to get the user CLI arg override first
196
+ if (opts[name]) {
197
+ return opts[name];
198
+ } else if (deriver[name]) {
199
+ // Then get the platform-specific default
200
+ if (L.isFunction(deriver[name])) {
201
+ const fn = deriver[name] as (s: string) => string;
202
+ return fn(srcDir);
203
+ }
204
+ return deriver[name];
205
+ } else {
206
+ // Other specified default
207
+ return defaultAnswer;
208
+ }
209
+ };
210
+
211
+ // Start with a complete set of defaults. Some of these are not worth displaying.
212
+ const answers: Omit<InitArgs, "baseDir"> = {
213
+ host: getDefaultAnswer("host", "") as any,
214
+ platform,
215
+ codeLang: getDefaultAnswer("codeLang", isTypescript ? "ts" : "js") as any,
216
+ codeScheme: getDefaultAnswer(
217
+ "codeScheme",
218
+ DEFAULT_CONFIG.code.scheme
219
+ ) as any,
220
+ styleScheme: getDefaultAnswer(
221
+ "styleScheme",
222
+ DEFAULT_CONFIG.style.scheme
223
+ ) as any,
224
+ imagesScheme: getDefaultAnswer(
225
+ "imagesScheme",
226
+ DEFAULT_CONFIG.images.scheme
227
+ ) as any,
228
+ imagesPublicDir: getDefaultAnswer(
229
+ "imagesPublicDir",
230
+ ensure(DEFAULT_PUBLIC_FILES_CONFIG.publicDir)
231
+ ) as any,
232
+ imagesPublicUrlPrefix: getDefaultAnswer(
233
+ "imagesPublicUrlPrefix",
234
+ ensure(DEFAULT_PUBLIC_FILES_CONFIG.publicUrlPrefix)
235
+ ) as any,
236
+ srcDir: getDefaultAnswer("srcDir", DEFAULT_CONFIG.srcDir) as any,
237
+ plasmicDir: getDefaultAnswer(
238
+ "plasmicDir",
239
+ DEFAULT_CONFIG.defaultPlasmicDir
240
+ ) as any,
241
+ pagesDir: getDefaultAnswer("pagesDir", undefined) as any,
242
+ reactRuntime: getDefaultAnswer("reactRuntime", "classic") as any,
243
+ };
244
+ const prominentAnswers = L.omit(answers, "codeScheme");
245
+
246
+ if (process.env.QUIET) {
247
+ return answers;
248
+ }
249
+
250
+ logger.info(
251
+ chalk.bold(
252
+ "Plasmic Express Setup -- Here are the default settings we recommend:\n"
253
+ )
254
+ );
255
+
256
+ await performAsks(true);
257
+
258
+ // Allow a user to short-circuit
259
+ const useExpressQuestion: SimpleQuestion = {
260
+ name: "continue",
261
+ message: `Would you like to accept these defaults?`,
262
+ type: "list",
263
+ choices: () => [
264
+ {
265
+ value: "yes",
266
+ name: "Accept these defaults",
267
+ },
268
+ {
269
+ value: "no",
270
+ name: "Customize the choices",
271
+ },
272
+ ],
273
+ };
274
+ logger.info("");
275
+
276
+ if (opts.yes) {
277
+ simulatePrompt(useExpressQuestion, "yes", true);
278
+ return answers;
279
+ } else {
280
+ const useExpress = await inquirer.prompt([useExpressQuestion]);
281
+ if (useExpress.continue === "yes") {
282
+ return answers;
283
+ }
284
+ }
285
+
286
+ /**
287
+ * @param express When true, we pretty-print the question along with the default answer, as if that was the choice
288
+ * being made. This is for displaying the default choices in the express setup.
289
+ */
290
+ async function performAsks(express: boolean) {
291
+ // Proceed with platform-specific prompts
292
+ async function maybePrompt(question: SimpleQuestion) {
293
+ const name = ensure(question.name) as keyof Omit<InitArgs, "baseDir">;
294
+ const message = ensure(question.message) as string;
295
+ if (opts[name]) {
296
+ logger.info(message + answers[name] + "(specified in CLI arg)");
297
+ } else if (express) {
298
+ const defaultAnswer = answers[name];
299
+ simulatePrompt(question, defaultAnswer);
300
+ } else if (!opts.yes && !deriver.alwaysDerived.includes(name)) {
301
+ const ans = await inquirer.prompt({
302
+ ...question,
303
+ default: answers[name],
304
+ });
305
+ // Not sure why TS complains here without this cast.
306
+ (answers as any)[name] = ans[name];
307
+ }
308
+ // Other questions are silently skipped
309
+ }
310
+
311
+ await maybePrompt({
312
+ name: "srcDir",
313
+ message: `${getInitArgsQuestion("srcDir")}\n>`,
314
+ });
315
+
316
+ await maybePrompt({
317
+ name: "plasmicDir",
318
+ message: `${getInitArgsQuestion("plasmicDir")} (This is relative to "${
319
+ answers.srcDir
320
+ }")\n>`,
321
+ });
322
+
323
+ if (isPageAwarePlatform(platform)) {
324
+ await maybePrompt({
325
+ name: "pagesDir",
326
+ message: `${getInitArgsQuestion("pagesDir")} (This is relative to "${
327
+ answers.srcDir
328
+ }")\n>`,
329
+ });
330
+ }
331
+
332
+ await maybePrompt({
333
+ name: "codeLang",
334
+ message: `${getInitArgsQuestion("codeLang")}\n`,
335
+ type: "list",
336
+ choices: () => [
337
+ {
338
+ name: `Typescript${isTypescript ? " (tsconfig.json detected)" : ""}`,
339
+ value: "ts",
340
+ },
341
+ {
342
+ name: `Javascript${
343
+ !isTypescript ? " (no tsconfig.json detected)" : ""
344
+ }`,
345
+ value: "js",
346
+ },
347
+ ],
348
+ });
349
+
350
+ await maybePrompt({
351
+ name: "styleScheme",
352
+ message: `${getInitArgsQuestion("styleScheme")}\n`,
353
+ type: "list",
354
+ choices: () => [
355
+ {
356
+ name: `CSS modules, imported as "import sty from './plasmic.module.css'"`,
357
+ value: "css-modules",
358
+ },
359
+ {
360
+ name: `Plain CSS stylesheets, imported as "import './plasmic.css'"`,
361
+ value: "css",
362
+ },
363
+ ],
364
+ });
365
+
366
+ await maybePrompt({
367
+ name: "imagesScheme",
368
+ message: `${getInitArgsQuestion("imagesScheme")}\n`,
369
+ type: "list",
370
+ choices: () => [
371
+ {
372
+ name: `Imported as files, like "import img from './image.png'". ${
373
+ isGeneric ? "Not all bundlers support this." : ""
374
+ }`,
375
+ value: "files",
376
+ },
377
+ {
378
+ name: `Images stored in a public folder, referenced like <img src="/static/image.png"/>`,
379
+ value: "public-files",
380
+ },
381
+ {
382
+ name: `Inlined as base64-encoded data URIs`,
383
+ value: "inlined",
384
+ },
385
+ ],
386
+ });
387
+
388
+ if (answers.imagesScheme === "public-files") {
389
+ await maybePrompt({
390
+ name: "imagesPublicDir",
391
+ message: `${getInitArgsQuestion(
392
+ "imagesPublicDir"
393
+ )} (This is relative to "${answers.srcDir}")\n>`,
394
+ });
395
+
396
+ await maybePrompt({
397
+ name: "imagesPublicUrlPrefix",
398
+ message: `${getInitArgsQuestion("imagesPublicUrlPrefix")} ${
399
+ isNext ? `(for Next.js, this is usually "/")` : ""
400
+ }\n>`,
401
+ });
402
+ }
403
+ }
404
+
405
+ await performAsks(false);
406
+
407
+ return answers as InitArgs;
408
+ }
409
+
410
+ function getNextDefaults(plasmicRootDir: string): DefaultDeriver {
411
+ const projectRootDir = findPackageJsonDir(plasmicRootDir) ?? plasmicRootDir;
412
+ return {
413
+ srcDir: path.relative(
414
+ plasmicRootDir,
415
+ path.join(projectRootDir, "components")
416
+ ),
417
+ pagesDir: (srcDir: string) =>
418
+ path.relative(
419
+ path.join(plasmicRootDir, srcDir),
420
+ path.join(projectRootDir, "pages")
421
+ ),
422
+ styleScheme: "css-modules",
423
+ imagesScheme: "public-files",
424
+ imagesPublicDir: (srcDir: string) =>
425
+ path.relative(
426
+ path.join(plasmicRootDir, srcDir),
427
+ path.join(projectRootDir, "public")
428
+ ),
429
+ imagesPublicUrlPrefix: "/",
430
+ alwaysDerived: [
431
+ "styleScheme",
432
+ "imagesScheme",
433
+ "imagesPublicDir",
434
+ "pagesDir",
435
+ ],
436
+ };
437
+ }
438
+
439
+ function getGatsbyDefaults(plasmicRootDir: string): DefaultDeriver {
440
+ const projectRootDir = findPackageJsonDir(plasmicRootDir) ?? plasmicRootDir;
441
+ return {
442
+ srcDir: path.relative(
443
+ plasmicRootDir,
444
+ path.join(projectRootDir, "src", "components")
445
+ ),
446
+ pagesDir: (srcDir: string) => {
447
+ const absSrcDir = path.join(plasmicRootDir, srcDir);
448
+ const absPagesDir = path.join(projectRootDir, "src", "pages");
449
+ const relDir = path.relative(absSrcDir, absPagesDir);
450
+ return relDir;
451
+ },
452
+ styleScheme: "css-modules",
453
+ imagesScheme: "files",
454
+ imagesPublicDir: (srcDir: string) =>
455
+ path.relative(
456
+ path.join(plasmicRootDir, srcDir),
457
+ path.join(projectRootDir, "static")
458
+ ),
459
+ imagesPublicUrlPrefix: "/",
460
+ alwaysDerived: ["imagesScheme", "pagesDir"],
461
+ };
462
+ }
463
+
464
+ function getCraDefaults(plasmicRootDir: string): DefaultDeriver {
465
+ const projectRootDir = findPackageJsonDir(plasmicRootDir) ?? plasmicRootDir;
466
+ return {
467
+ srcDir: path.relative(
468
+ plasmicRootDir,
469
+ path.join(projectRootDir, "src", "components")
470
+ ),
471
+ styleScheme: "css-modules",
472
+ imagesScheme: "files",
473
+ imagesPublicDir: (srcDir: string) =>
474
+ path.relative(
475
+ path.join(plasmicRootDir, srcDir),
476
+ path.join(projectRootDir, "public")
477
+ ),
478
+ alwaysDerived: [],
479
+ };
480
+ }
481
+
482
+ function getGenericDefaults(plasmicRootDir: string): DefaultDeriver {
483
+ const projectRootDir = findPackageJsonDir(plasmicRootDir) ?? plasmicRootDir;
484
+ const srcDir = existsBuffered(path.join(projectRootDir, "src"))
485
+ ? path.join(projectRootDir, "src", "components")
486
+ : path.join(projectRootDir, "components");
487
+ return {
488
+ srcDir: path.relative(plasmicRootDir, srcDir),
489
+ alwaysDerived: [],
490
+ };
491
+ }
492
+
493
+ /**
494
+ * Consolidating where we are specifying the descriptions of InitArgs
495
+ */
496
+ const INIT_ARGS_DESCRIPTION: {
497
+ [T in keyof Omit<InitArgs, "baseDir">]: {
498
+ shortDescription: string;
499
+ longDescription?: string;
500
+ question?: string;
501
+ choices?: string[];
502
+ };
503
+ } = {
504
+ host: {
505
+ shortDescription: "Plasmic host to use",
506
+ },
507
+ platform: {
508
+ shortDescription: "Target platform",
509
+ longDescription: "Target platform to generate code for",
510
+ choices: ["react", "nextjs", "gatsby"],
511
+ },
512
+ codeLang: {
513
+ shortDescription: "Target language",
514
+ longDescription: "Target language to generate code for",
515
+ question: `What target language should Plasmic generate code in?`,
516
+ choices: ["js", "ts"],
517
+ },
518
+ codeScheme: {
519
+ shortDescription: "Code generation scheme",
520
+ longDescription: "Code generation scheme to use",
521
+ choices: ["blackbox", "direct"],
522
+ },
523
+ styleScheme: {
524
+ shortDescription: "Styling framework",
525
+ longDescription: "Styling framework to use",
526
+ question: "How should we generate css for Plasmic components?",
527
+ choices: ["css", "css-modules"],
528
+ },
529
+ imagesScheme: {
530
+ shortDescription: "Image scheme",
531
+ longDescription: "How to reference used image files",
532
+ question: "How should we reference image files used in Plasmic components?",
533
+ choices: ["inlined", "files", "public-files"],
534
+ },
535
+ imagesPublicDir: {
536
+ shortDescription: "Directory of public static files",
537
+ longDescription: "Default directory to put public static files",
538
+ question: "What directory should static image files be put into?",
539
+ },
540
+ imagesPublicUrlPrefix: {
541
+ shortDescription: "URL prefix for static files",
542
+ longDescription: "URL prefix from which the app will serve static files",
543
+ question:
544
+ "What's the URL prefix from which the app will serve static files?",
545
+ },
546
+ srcDir: {
547
+ shortDescription: "Source directory",
548
+ longDescription:
549
+ "Default directory to put React component files (that you edit) into",
550
+ question:
551
+ "What directory should React component files (that you edit) be put into?",
552
+ },
553
+ plasmicDir: {
554
+ shortDescription: "Plasmic-managed directory",
555
+ longDescription:
556
+ "Default directory to put Plasmic-managed files into; relative to src-dir",
557
+ question:
558
+ "What directory should Plasmic-managed files (that you should not edit) be put into?",
559
+ },
560
+ pagesDir: {
561
+ shortDescription: "Pages directory",
562
+ longDescription: "Default directory to put page files (that you edit) into",
563
+ question: "What directory should pages be put into?",
564
+ },
565
+ };
566
+
567
+ /**
568
+ * Get the short description, which exists for all args
569
+ * @param key
570
+ * @returns
571
+ */
572
+ export function getInitArgsShortDescription(
573
+ key: keyof Omit<InitArgs, "baseDir">
574
+ ) {
575
+ return INIT_ARGS_DESCRIPTION[key]?.shortDescription;
576
+ }
577
+
578
+ /**
579
+ * Try to get a long description, falling back to the short description
580
+ * @param key
581
+ * @returns
582
+ */
583
+ export function getInitArgsLongDescription(
584
+ key: keyof Omit<InitArgs, "baseDir">
585
+ ) {
586
+ return (
587
+ INIT_ARGS_DESCRIPTION[key]?.longDescription ??
588
+ INIT_ARGS_DESCRIPTION[key]?.shortDescription
589
+ );
590
+ }
591
+
592
+ /**
593
+ * Try to get a question form, falling back to the description
594
+ * @param key
595
+ * @returns
596
+ */
597
+ export function getInitArgsQuestion(key: keyof Omit<InitArgs, "baseDir">) {
598
+ return (
599
+ INIT_ARGS_DESCRIPTION[key]?.question ??
600
+ INIT_ARGS_DESCRIPTION[key]?.longDescription ??
601
+ INIT_ARGS_DESCRIPTION[key]?.shortDescription
602
+ );
603
+ }
604
+
605
+ /**
606
+ * Get the possible choices for an arg
607
+ * @param key
608
+ * @returns
609
+ */
610
+ export function getInitArgsChoices(key: keyof Omit<InitArgs, "baseDir">) {
611
+ return INIT_ARGS_DESCRIPTION[key]?.choices;
612
+ }
613
+
614
+ /**
615
+ * Get a `opt` object for use with the `yargs` library.
616
+ * If no choices are specified, assume it's freeform string input
617
+ * All options use "" as the default, unless overridden
618
+ * @param key
619
+ * @param defaultOverride
620
+ * @returns
621
+ */
622
+ export function getYargsOption(
623
+ key: keyof Omit<InitArgs, "baseDir">,
624
+ defaultOverride?: string
625
+ ) {
626
+ const arg = ensure(INIT_ARGS_DESCRIPTION[key]);
627
+ return !arg.choices
628
+ ? {
629
+ describe: ensure(getInitArgsLongDescription(key)),
630
+ string: true,
631
+ default: defaultOverride ?? "",
632
+ }
633
+ : {
634
+ describe: ensure(getInitArgsLongDescription(key)),
635
+ choices: ["", ...ensure(getInitArgsChoices(key))],
636
+ default: defaultOverride ?? "",
637
+ };
638
+ }
@@ -0,0 +1,36 @@
1
+ import chalk from "chalk";
2
+ import { PlasmicApi } from "../api";
3
+ import { logger } from "../deps";
4
+ import { getOrStartAuth } from "../utils/auth-utils";
5
+ import { DEFAULT_HOST } from "../utils/config-utils";
6
+
7
+ export interface ProjectTokenArgs {
8
+ projectId: string;
9
+ host: string;
10
+ }
11
+
12
+ export const getProjectApiToken = async (projectId: string, host?: string) => {
13
+ const auth = await getOrStartAuth({
14
+ host: host || DEFAULT_HOST,
15
+ baseDir: "",
16
+ });
17
+
18
+ if (auth) {
19
+ const api = new PlasmicApi(auth);
20
+ const versionResolution = await api.resolveSync([
21
+ { projectId, componentIdOrNames: undefined },
22
+ ]);
23
+ return versionResolution.projects[0]?.projectApiToken;
24
+ }
25
+ return undefined;
26
+ };
27
+
28
+ export const projectToken = async (args: ProjectTokenArgs) => {
29
+ const { projectId, host } = args;
30
+ const projectApiToken = await getProjectApiToken(projectId, host);
31
+ logger.info(`Generated projectApiToken for ${chalk.bold(projectId)}:`);
32
+ logger.info(chalk.bold(projectApiToken));
33
+ logger.warn(
34
+ `Be careful with this token, anyone can have access to your project with it`
35
+ );
36
+ };