@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,551 @@
1
+ import L from "lodash";
2
+ import { DeepPartial } from "utility-types";
3
+ import { PlasmicApi, ProjectIdAndToken } from "../api";
4
+ import { logger } from "../deps";
5
+ import { HandledError } from "../utils/error";
6
+ import { formatAsLocal } from "./code-utils";
7
+ import {
8
+ existsBuffered,
9
+ findFile,
10
+ readFileText,
11
+ writeFileContentRaw,
12
+ } from "./file-utils";
13
+
14
+ export const DEFAULT_HOST =
15
+ process.env.PLASMIC_DEFAULT_HOST || "https://studio.plasmic.app";
16
+
17
+ // Default filenames
18
+ export const AUTH_FILE_NAME = ".plasmic.auth";
19
+ export const CONFIG_FILE_NAME = "plasmic.json";
20
+ export const LOCK_FILE_NAME = "plasmic.lock";
21
+ export const LOADER_CONFIG_FILE_NAME = "plasmic-loader.json";
22
+ export const CONFIG_SCHEMA_FILE_NAME = "plasmic.schema.json";
23
+
24
+ // Default environment variable names
25
+ export const ENV_AUTH_HOST = "PLASMIC_AUTH_HOST";
26
+ export const ENV_AUTH_USER = "PLASMIC_AUTH_USER";
27
+ export const ENV_AUTH_TOKEN = "PLASMIC_AUTH_TOKEN";
28
+
29
+ export interface PlasmicLoaderConfig {
30
+ projects: ProjectIdAndToken[];
31
+ aboutThisFile: string;
32
+ dir: string;
33
+ plasmicDir: string;
34
+ pageDir: string;
35
+ initArgs: Record<string, string>;
36
+ substitutions?: Record<string, any>;
37
+ }
38
+
39
+ export interface PlasmicConfig {
40
+ /** Target platform to generate code for */
41
+ platform: "react" | "nextjs" | "gatsby";
42
+
43
+ /**
44
+ * The folder containing the component source files; this is the default place where
45
+ * all files are generated and stored.
46
+ */
47
+ srcDir: string;
48
+
49
+ /**
50
+ * The default folder where Plasmic-managed files will be stored. These include
51
+ * blackbox component files, svg component files, style files, etc. The path
52
+ * is relative to the srcDir.
53
+ */
54
+ defaultPlasmicDir: string;
55
+
56
+ /**
57
+ * Next.js specific config
58
+ */
59
+ nextjsConfig?: {
60
+ /** The folder containing page components source files. */
61
+ pagesDir?: string;
62
+ };
63
+
64
+ /** Gatsby-specific config */
65
+ gatsbyConfig?: {
66
+ /** The folder containing page components source files. */
67
+ pagesDir?: string;
68
+ };
69
+
70
+ /** Config for code generation */
71
+ code: CodeConfig;
72
+
73
+ /** Config for pictures */
74
+ images: ImagesConfig;
75
+
76
+ /** Config for style generation */
77
+ style: StyleConfig;
78
+
79
+ /** Config for style tokens */
80
+ tokens: TokensConfig;
81
+
82
+ /** Metadata for global variant groups */
83
+ globalVariants: GlobalVariantsConfig;
84
+
85
+ /** Metadata for each project that has been synced */
86
+ projects: ProjectConfig[];
87
+
88
+ /** The version of cli when this file was written */
89
+ cliVersion?: string;
90
+
91
+ /** Arbitrary command to run after `plasmic sync` has run; useful for linting and code formatting synced files */
92
+ postSyncCommands?: string[];
93
+ }
94
+
95
+ export interface CodeConfig {
96
+ /** Language to generate code in */
97
+ lang: "ts" | "js";
98
+
99
+ /** The default code generation scheme. Each component can override the scheme. */
100
+ scheme: "blackbox" | "direct";
101
+
102
+ reactRuntime: "classic" | "automatic";
103
+ }
104
+
105
+ export interface StyleConfig {
106
+ /** Styling framework to use */
107
+ scheme: "css" | "css-modules";
108
+
109
+ /** File location for global css styles shared by all components. Relative to srcDir */
110
+ defaultStyleCssFilePath: string;
111
+ }
112
+
113
+ export interface ImagesConfig {
114
+ /**
115
+ * How image files should be referenced from generated React components. The choices are:
116
+ * * "files" - imported as relative files, like "import img from './image.png'". Not all bundlers support this.
117
+ * * "public-files" - images are stored in a public folder, and referenced from some url prefix, like `<img src="/static/image.png"/>`.
118
+ * * "inlined" - inlined directly into React files and css files as base64-encoded data-URIs.
119
+ * * "cdn" - images are served from Plasmic's CDN. Allows for dynamic resizing of images for
120
+ * serving the optimal file size given browser viewport.
121
+ */
122
+ scheme: "inlined" | "files" | "public-files" | "cdn";
123
+
124
+ /**
125
+ * The folder where "public" static files are stored. Plasmic-managed image files will be stored as "plasmic/project-name/image-name" under this folder. Relative to srcDir; for example, "../public"
126
+ */
127
+ publicDir?: string;
128
+
129
+ /**
130
+ * The url prefix where "public" static files are stored. For example, if publicDir is "public", publicUrlPrefix is "/static", then a file at public/test.png will be served at /static/test.png.
131
+ */
132
+ publicUrlPrefix?: string;
133
+ }
134
+
135
+ export interface JsBundleThemeConfig {
136
+ themeFilePath: string;
137
+ bundleName: string;
138
+ }
139
+
140
+ export interface CodeComponentConfig {
141
+ id: string;
142
+ name: string;
143
+ componentImportPath: string;
144
+ }
145
+
146
+ export interface ProjectConfig {
147
+ /** Project ID */
148
+ projectId: string;
149
+ /** Project API token. Grants read-only sync access to just this specific project and its dependencies. */
150
+ projectApiToken?: string;
151
+ /** Project name synced down from Studio */
152
+ projectName: string;
153
+ /**
154
+ * A version range for syncing this project. Can be:
155
+ * * "latest" - always syncs down whatever has been saved in the project.
156
+ * * ">0" - always syncs down the latest published version of the project.
157
+ * * any other semver string you'd like
158
+ */
159
+ version: string;
160
+ /** File location for the project-wide css styles. Relative to srcDir */
161
+ cssFilePath: string;
162
+
163
+ // Code-component-related fields can be treated as optional not to be shown
164
+ // to the users nor appear to be missing in the documentation.
165
+ jsBundleThemes?: JsBundleThemeConfig[];
166
+ codeComponents?: CodeComponentConfig[];
167
+
168
+ /** Metadata for each synced component in this project. */
169
+ components: ComponentConfig[];
170
+ /** Metadata for each synced icon in this project */
171
+ icons: IconConfig[];
172
+ /** Metadata for each synced image in this project */
173
+ images: ImageConfig[];
174
+ }
175
+
176
+ export function createProjectConfig(base: {
177
+ projectId: string;
178
+ projectApiToken: string;
179
+ projectName: string;
180
+ version: string;
181
+ cssFilePath: string;
182
+ }): ProjectConfig {
183
+ return {
184
+ projectId: base.projectId,
185
+ projectApiToken: base.projectApiToken,
186
+ projectName: base.projectName,
187
+ version: base.version,
188
+ cssFilePath: base.cssFilePath,
189
+ components: [],
190
+ icons: [],
191
+ images: [],
192
+ };
193
+ }
194
+
195
+ export interface TokensConfig {
196
+ scheme: "theo";
197
+ tokensFilePath: string;
198
+ }
199
+
200
+ /**
201
+ * Describes how to import a Component
202
+ */
203
+ export interface ImportSpec {
204
+ /**
205
+ * The import path to use to instantiate this Component. The modulePath can be:
206
+ * * An external npm module, like "antd/lib/button"
207
+ * * A local file, like "components/Button.tsx" (path is relative to srcDir, and file extension is fully specified). If local file is specified, then the module is imported via relative path.
208
+ *
209
+ * For this to be an external npm module, the ComponentConfig.type must be "mapped".
210
+ */
211
+ modulePath: string;
212
+
213
+ /**
214
+ * If the Component is a named export of the module, then this is the name. If the Component
215
+ * is the default export, then this is undefined.
216
+ */
217
+ exportName?: string;
218
+ }
219
+
220
+ export interface ComponentConfig {
221
+ /** Component ID */
222
+ id: string;
223
+
224
+ /** Javascript name of component */
225
+ name: string;
226
+
227
+ /** Plasmic project that this component belongs in */
228
+ projectId: string;
229
+
230
+ /** Whether this component is managed by Plasmic -- with Plasmic* files generated -- or mapped to an external library */
231
+ type: "managed" | "mapped";
232
+
233
+ /** How to import this Component from another component file */
234
+ importSpec: ImportSpec;
235
+
236
+ /** The file path for the blackbox render module, relative to srcDir. */
237
+ renderModuleFilePath: string;
238
+
239
+ /** The file path for the component css file, relative to srcDir. */
240
+ cssFilePath: string;
241
+
242
+ /** Code generation scheme used for this component */
243
+ scheme: "blackbox" | "direct";
244
+
245
+ componentType: "page" | "component";
246
+
247
+ /** Plume type if component is a Plume component */
248
+ plumeType?: string;
249
+ }
250
+
251
+ export interface IconConfig {
252
+ /** ID of icon */
253
+ id: string;
254
+
255
+ /** Javascript name of the React component for this icon */
256
+ name: string;
257
+
258
+ /** The file path for the React component file for this icon, relative to srcDir. */
259
+ moduleFilePath: string;
260
+ }
261
+
262
+ export interface ImageConfig {
263
+ /** ID of image */
264
+ id: string;
265
+ /** name of image */
266
+ name: string;
267
+ /** File path for the image file, relative to srcDir */
268
+ filePath: string;
269
+ }
270
+
271
+ export interface GlobalVariantsConfig {
272
+ variantGroups: GlobalVariantGroupConfig[];
273
+ }
274
+
275
+ export interface GlobalVariantGroupConfig {
276
+ /** ID of the global variant group */
277
+ id: string;
278
+ /** Javascript name of the global variant group */
279
+ name: string;
280
+ /** Plasmic project this global variant group belongs to */
281
+ projectId: string;
282
+ /** File path for the global variant group React context definition, relative to srcDir */
283
+ contextFilePath: string;
284
+ }
285
+
286
+ export interface FileLock {
287
+ // The type of file whose checksum was computed
288
+ type:
289
+ | "renderModule"
290
+ | "cssRules"
291
+ | "icon"
292
+ | "image"
293
+ | "projectCss"
294
+ | "globalVariant";
295
+ // The checksum value for the file
296
+ checksum: string;
297
+ // The component id, or the image asset id
298
+ assetId: string;
299
+ }
300
+
301
+ export interface ProjectLock {
302
+ projectId: string;
303
+ // The exact version that was last synced
304
+ version: string;
305
+ dependencies: {
306
+ // Maps from projectId => exact version
307
+ [projectId: string]: string;
308
+ };
309
+ // The language during last sync
310
+ lang: "ts" | "js";
311
+ // One for each file whose checksum is computed
312
+ fileLocks: FileLock[];
313
+ }
314
+
315
+ export interface PlasmicLock {
316
+ // One for each project that has been synced
317
+ projects: ProjectLock[];
318
+
319
+ // The version of CLI when this file was written
320
+ cliVersion?: string;
321
+ }
322
+
323
+ /**
324
+ * PlasmicContext is the PlasmicConfig plus context in which the PlasmicConfig was
325
+ * created.
326
+ */
327
+ export interface PlasmicContext {
328
+ // Location of the plasmic.json file
329
+ configFile: string;
330
+
331
+ // Location of the plasmic.lock file
332
+ lockFile: string;
333
+
334
+ // Folder where plasmic.json file lives
335
+ rootDir: string;
336
+
337
+ // Absolute path to the source directory
338
+ // If config.srcDir is a relative path, it will be relative to the Plasmic config file
339
+ absoluteSrcDir: string;
340
+
341
+ // The parsed PlasmicConfig
342
+ config: PlasmicConfig;
343
+
344
+ // The parsed PlasmicLock
345
+ lock: PlasmicLock;
346
+
347
+ // The parsed AuthConfig
348
+ auth: AuthConfig;
349
+
350
+ // Api instance to use for talking to Plasmic
351
+ api: PlasmicApi;
352
+
353
+ // args passed to cli
354
+ cliArgs: any;
355
+ }
356
+
357
+ export interface AuthConfig {
358
+ // Plasmic web app host
359
+ host: string;
360
+
361
+ // Plasmic user email
362
+ user: string;
363
+
364
+ // Plasmic API token
365
+ token: string;
366
+
367
+ // If Plasmic instance is gated by basic auth, the basic auth user and password
368
+ basicAuthUser?: string;
369
+ basicAuthPassword?: string;
370
+ }
371
+
372
+ export const DEFAULT_CONFIG: PlasmicConfig = {
373
+ platform: "react",
374
+ code: {
375
+ lang: "ts",
376
+ scheme: "blackbox",
377
+ reactRuntime: "classic",
378
+ },
379
+ style: {
380
+ scheme: "css-modules",
381
+ // We set it to empty to compile. In reality, it will be provided the by
382
+ // the server.
383
+ defaultStyleCssFilePath: "",
384
+ },
385
+ images: {
386
+ scheme: "inlined",
387
+ },
388
+ tokens: {
389
+ scheme: "theo",
390
+ tokensFilePath: "plasmic-tokens.theo.json",
391
+ },
392
+ srcDir: "./src/components",
393
+ defaultPlasmicDir: "./plasmic",
394
+ projects: [],
395
+ globalVariants: {
396
+ variantGroups: [],
397
+ },
398
+ };
399
+
400
+ export const DEFAULT_PUBLIC_FILES_CONFIG: ImagesConfig = {
401
+ scheme: "public-files",
402
+ publicDir: "../public",
403
+ publicUrlPrefix: "/static/",
404
+ };
405
+
406
+ /**
407
+ * Finds the full path to the plasmic.json file in `dir`. If
408
+ * `opts.traverseParents` is set to true, then will also look in ancestor
409
+ * directories until the plasmic.json file is found. If none is found,
410
+ * returns undefined.
411
+ */
412
+ export function findConfigFile(
413
+ dir: string,
414
+ opts: {
415
+ traverseParents?: boolean;
416
+ }
417
+ ): string | undefined {
418
+ return findFile(dir, (f) => f === CONFIG_FILE_NAME, opts);
419
+ }
420
+
421
+ /**
422
+ * Given some partial configs for PlasmicConfig, fills in all required fields
423
+ * with default values.
424
+ */
425
+ export function fillDefaults(
426
+ config: DeepPartial<PlasmicConfig>
427
+ ): PlasmicConfig {
428
+ return L.merge({}, DEFAULT_CONFIG, config);
429
+ }
430
+
431
+ export function readConfig(
432
+ configFile: string,
433
+ autoFillDefaults: boolean
434
+ ): PlasmicConfig {
435
+ if (!existsBuffered(configFile)) {
436
+ const err = new HandledError(
437
+ `No Plasmic config file found at ${configFile}`
438
+ );
439
+ throw err;
440
+ }
441
+ try {
442
+ const result = JSON.parse(readFileText(configFile!)) as PlasmicConfig;
443
+ return autoFillDefaults ? fillDefaults(result) : result;
444
+ } catch (e) {
445
+ logger.error(
446
+ `Error encountered reading ${CONFIG_FILE_NAME} at ${configFile}: ${e}`
447
+ );
448
+ throw e;
449
+ }
450
+ }
451
+
452
+ export async function writeConfig(
453
+ configFile: string,
454
+ config: PlasmicConfig,
455
+ baseDir: string
456
+ ) {
457
+ await writeFileContentRaw(
458
+ configFile,
459
+ formatAsLocal(
460
+ JSON.stringify(
461
+ {
462
+ ...config,
463
+ $schema: `https://unpkg.com/@plasmicapp/cli@${config.cliVersion}/dist/plasmic.schema.json`,
464
+ },
465
+ undefined,
466
+ 2
467
+ ),
468
+ configFile,
469
+ baseDir
470
+ ),
471
+ {
472
+ force: true,
473
+ }
474
+ );
475
+ }
476
+
477
+ export async function writeLock(
478
+ lockFile: string,
479
+ lock: PlasmicLock,
480
+ baseDir: string
481
+ ) {
482
+ await writeFileContentRaw(
483
+ lockFile,
484
+ formatAsLocal(JSON.stringify(lock, undefined, 2), "/tmp/x.json", baseDir),
485
+ {
486
+ force: true,
487
+ }
488
+ );
489
+ }
490
+
491
+ export async function updateConfig(
492
+ context: PlasmicContext,
493
+ newConfig: PlasmicConfig,
494
+ baseDir: string
495
+ ) {
496
+ // plasmic.json
497
+ await writeConfig(context.configFile, newConfig, baseDir);
498
+ context.config = newConfig;
499
+
500
+ // plasmic.lock
501
+ await writeLock(context.lockFile, context.lock, baseDir);
502
+ }
503
+
504
+ export function getOrAddProjectConfig(
505
+ context: PlasmicContext,
506
+ projectId: string,
507
+ base?: ProjectConfig // if one doesn't exist, start with this
508
+ ): ProjectConfig {
509
+ let project = context.config.projects.find((p) => p.projectId === projectId);
510
+ if (!project) {
511
+ project = !!base
512
+ ? L.cloneDeep(base)
513
+ : {
514
+ projectId,
515
+ projectName: "",
516
+ version: "latest",
517
+ cssFilePath: "",
518
+ components: [],
519
+ icons: [],
520
+ images: [],
521
+ jsBundleThemes: [],
522
+ };
523
+ context.config.projects.push(project);
524
+ }
525
+ return project;
526
+ }
527
+
528
+ export function getOrAddProjectLock(
529
+ context: PlasmicContext,
530
+ projectId: string,
531
+ base?: ProjectLock // if one doesn't exist, start with this
532
+ ): ProjectLock {
533
+ let project = context.lock.projects.find((p) => p.projectId === projectId);
534
+ if (!project) {
535
+ project = !!base
536
+ ? L.cloneDeep(base)
537
+ : {
538
+ projectId,
539
+ version: "",
540
+ dependencies: {},
541
+ lang: context.config.code.lang,
542
+ fileLocks: [],
543
+ };
544
+ context.lock.projects.push(project);
545
+ }
546
+ return project;
547
+ }
548
+
549
+ export function isPageAwarePlatform(platform: string): boolean {
550
+ return platform === "nextjs" || platform === "gatsby";
551
+ }
@@ -0,0 +1,39 @@
1
+ import findupSync from "findup-sync";
2
+ import { getParsedPackageJson } from "./npm-utils";
3
+
4
+ export function detectTypescript() {
5
+ return findupSync("tsconfig.json");
6
+ }
7
+
8
+ export function detectNextJs() {
9
+ if (
10
+ findupSync("next.config.js") ||
11
+ findupSync(".next") ||
12
+ findupSync("next-env.d.ts")
13
+ ) {
14
+ return true;
15
+ }
16
+
17
+ try {
18
+ const packageJsonContent = getParsedPackageJson();
19
+ return (
20
+ packageJsonContent.scripts.build === "next build" ||
21
+ "next" in packageJsonContent.dependencies
22
+ );
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
27
+
28
+ export function detectGatsby() {
29
+ return findupSync("gatsby-config.js");
30
+ }
31
+
32
+ export function detectCreateReactApp() {
33
+ try {
34
+ const packageJsonContent = getParsedPackageJson();
35
+ return "react-scripts" in packageJsonContent.dependencies;
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
@@ -0,0 +1,36 @@
1
+ import chalk from "chalk";
2
+ import { logger } from "../deps";
3
+ import { checkEngineStrict } from "./npm-utils";
4
+
5
+ /**
6
+ * Represents an error that doesn't need to be forwarded to Sentry.
7
+ * These are errors that are user-fault, for example:
8
+ * - Using an old version of CLI
9
+ */
10
+ export class HandledError extends Error {}
11
+
12
+ /**
13
+ * Catches HandledErrors and just exits
14
+ * Forwards all other errors along.
15
+ * @param p
16
+ * @returns
17
+ */
18
+ export const handleError = <T>(p: Promise<T>) => {
19
+ return p.catch((e) => {
20
+ if (e.message) {
21
+ logger.error(
22
+ chalk.bold(chalk.redBright("\nPlasmic error: ")) + e.message
23
+ );
24
+ }
25
+ // Check if we satisfy the engine policy first
26
+ if (checkEngineStrict()) {
27
+ // eslint-disable-next-line
28
+ process.exit(1);
29
+ } else if (e instanceof HandledError) {
30
+ // eslint-disable-next-line
31
+ process.exit(1);
32
+ } else {
33
+ throw e;
34
+ }
35
+ });
36
+ };