@plasmicapp/cli 0.1.166 → 0.1.167

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.
@@ -250,6 +250,8 @@ class PlasmicApi {
250
250
  globalVariantChecksums: [],
251
251
  projectCssChecksum: "",
252
252
  },
253
+ usedNpmPackages: [],
254
+ externalCssImports: [],
253
255
  };
254
256
  return result;
255
257
  });
@@ -51,20 +51,20 @@ describe("Project API tokens", () => {
51
51
  fixtures_1.tmpRepo.writePlasmicJson(Object.assign(Object.assign({}, fixtures_1.defaultPlasmicJson), { projects: [Object.assign(Object.assign({}, fixtures_1.project1Config), { projectApiToken: "blah" })] }));
52
52
  yield expect(sync_1.sync(fixtures_1.opts)).resolves.toBeUndefined();
53
53
  fixtures_1.expectProject1Components();
54
- fixtures_1.expectProject1PlasmicJson();
54
+ fixtures_1.expectProject1PlasmicJson({ projectApiToken: true });
55
55
  // Re-run, this time with no auth.
56
56
  removeAuth();
57
- yield expect(sync_1.sync(fixtures_1.opts)).resolves.toBeUndefined();
57
+ yield expect(sync_1.sync(fixtures_1.opts)).rejects.toThrow("No user+token, and project API tokens don't match");
58
58
  }));
59
59
  test("is filled in by auth'd user if project exists but token was initially missing", () => __awaiter(void 0, void 0, void 0, function* () {
60
60
  fixtures_1.opts.projects = ["projectId1"];
61
61
  fixtures_1.tmpRepo.writePlasmicJson(Object.assign(Object.assign({}, fixtures_1.defaultPlasmicJson), { projects: [fixtures_1.project1Config] }));
62
62
  yield expect(sync_1.sync(fixtures_1.opts)).resolves.toBeUndefined();
63
63
  fixtures_1.expectProject1Components();
64
- fixtures_1.expectProject1PlasmicJson();
64
+ fixtures_1.expectProject1PlasmicJson({ projectApiToken: true });
65
65
  // Re-run, this time with no auth.
66
66
  removeAuth();
67
- yield expect(sync_1.sync(fixtures_1.opts)).resolves.toBeUndefined();
67
+ yield expect(sync_1.sync(fixtures_1.opts)).rejects.toThrow("Unable to authenticate Plasmic. Please run 'plasmic auth' or check the projectApiTokens in your plasmic.json, and try again.");
68
68
  }));
69
69
  test("when not available, should prompt for auth", () => __awaiter(void 0, void 0, void 0, function* () {
70
70
  fixtures_1.opts.projects = ["projectId1"];
@@ -208,13 +208,15 @@ function sync(opts, metadataDefaults) {
208
208
  ...versionResolution.dependencies,
209
209
  ].map((p) => lodash_1.default.pick(p, "projectId", "projectApiToken"));
210
210
  context.api.attachProjectIdsAndTokens(projectIdsAndTokens);
211
+ const externalNpmPackages = new Set();
212
+ const externalCssImports = new Set();
211
213
  // Perform the actual sync
212
214
  yield file_utils_1.withBufferedFs(() => __awaiter(this, void 0, void 0, function* () {
213
215
  var _b;
214
216
  // Sync in sequence (no parallelism)
215
217
  // going in reverse to get leaves of the dependency tree first
216
218
  for (const projectMeta of projectsToSync) {
217
- yield syncProject(context, opts, projectIdsAndTokens, projectMeta.projectId, projectMeta.componentIds, projectMeta.version, projectMeta.dependencies, summary, pendingMerge, projectMeta.indirect, metadataDefaults);
219
+ yield syncProject(context, opts, projectIdsAndTokens, projectMeta.projectId, projectMeta.componentIds, projectMeta.version, projectMeta.dependencies, summary, pendingMerge, projectMeta.indirect, externalNpmPackages, externalCssImports, metadataDefaults);
218
220
  }
219
221
  // Materialize scheme into each component config.
220
222
  context.config.projects.forEach((p) => p.components.forEach((c) => {
@@ -258,6 +260,13 @@ function sync(opts, metadataDefaults) {
258
260
  // Write the new ComponentConfigs to disk
259
261
  yield config_utils_1.updateConfig(context, context.config, baseDir);
260
262
  }));
263
+ yield checkExternalPkgs(context, baseDir, opts, Array.from(externalNpmPackages.keys()));
264
+ if (!opts.quiet && externalCssImports.size > 0) {
265
+ deps_1.logger.info(`This project uses external packages and styles. Make sure to import the following global CSS: ` +
266
+ Array.from(externalCssImports.keys())
267
+ .map((stmt) => `"${stmt}"`)
268
+ .join(", "));
269
+ }
261
270
  // Post-sync commands
262
271
  if (!opts.ignorePostSync) {
263
272
  for (const cmd of context.config.postSyncCommands || []) {
@@ -272,6 +281,20 @@ function sync(opts, metadataDefaults) {
272
281
  });
273
282
  }
274
283
  exports.sync = sync;
284
+ function checkExternalPkgs(context, baseDir, opts, pkgs) {
285
+ return __awaiter(this, void 0, void 0, function* () {
286
+ const missingPkgs = pkgs.filter((pkg) => {
287
+ const installedPkg = npm_utils_1.findInstalledVersion(context, baseDir, pkg);
288
+ return !installedPkg;
289
+ });
290
+ if (missingPkgs.length > 0) {
291
+ const upgrade = yield user_utils_1.confirmWithUser(`The following packages aren't installed but are required by some projects, would you like to install them? ${missingPkgs.join(", ")}`, opts.yes);
292
+ if (upgrade) {
293
+ npm_utils_1.installUpgrade(missingPkgs.join(" "), baseDir);
294
+ }
295
+ }
296
+ });
297
+ }
275
298
  function maybeRenamePathExt(context, path, ext) {
276
299
  if (!path) {
277
300
  return path;
@@ -292,7 +315,7 @@ function fixFileExtension(context) {
292
315
  });
293
316
  });
294
317
  }
295
- function syncProject(context, opts, projectIdsAndTokens, projectId, componentIds, projectVersion, dependencies, summary, pendingMerge, indirect, metadataDefaults) {
318
+ function syncProject(context, opts, projectIdsAndTokens, projectId, componentIds, projectVersion, dependencies, summary, pendingMerge, indirect, externalNpmPackages, externalCssImports, metadataDefaults) {
296
319
  var _a;
297
320
  return __awaiter(this, void 0, void 0, function* () {
298
321
  const newComponentScheme = opts.newComponentScheme || context.config.code.scheme;
@@ -336,6 +359,8 @@ function syncProject(context, opts, projectIdsAndTokens, projectId, componentIds
336
359
  yield sync_styles_1.upsertStyleTokens(context, projectBundle.usedTokens);
337
360
  yield sync_icons_1.syncProjectIconAssets(context, projectId, projectVersion, projectBundle.iconAssets, projectBundle.checksums, opts.baseDir);
338
361
  yield sync_images_1.syncProjectImageAssets(context, projectId, projectVersion, projectBundle.imageAssets, projectBundle.checksums);
362
+ (projectBundle.usedNpmPackages || []).forEach((pkg) => externalNpmPackages.add(pkg));
363
+ (projectBundle.externalCssImports || []).forEach((css) => externalCssImports.add(css));
339
364
  });
340
365
  }
341
366
  function syncStyleConfig(context, response) {
@@ -365,7 +390,6 @@ function syncProjectConfig(context, projectBundle, projectApiToken, version, dep
365
390
  if (!projectConfig.cssFilePath) {
366
391
  projectConfig.cssFilePath = defaultCssFilePath;
367
392
  }
368
- projectConfig.projectApiToken = projectApiToken;
369
393
  // plasmic.lock
370
394
  const projectLock = config_utils_1.getOrAddProjectLock(context, projectConfig.projectId);
371
395
  projectLock.version = version;
package/dist/api.d.ts CHANGED
@@ -80,6 +80,8 @@ export interface ProjectBundle {
80
80
  iconAssets: IconBundle[];
81
81
  imageAssets: ImageBundle[];
82
82
  checksums: ChecksumBundle;
83
+ usedNpmPackages: string[];
84
+ externalCssImports: string[];
83
85
  }
84
86
  export declare type ProjectMeta = Omit<ProjectBundle, "projectConfig">;
85
87
  export interface StyleConfigResponse {
package/dist/index.js CHANGED
File without changes
@@ -9,5 +9,7 @@ export declare function standardTestSetup(includeDep?: boolean): void;
9
9
  export declare function standardTestTeardown(): void;
10
10
  export declare function expectProject1Components(): void;
11
11
  export declare const project1Config: ProjectConfig;
12
- export declare function expectProject1PlasmicJson(): void;
12
+ export declare function expectProject1PlasmicJson(optional?: {
13
+ [k in keyof ProjectConfig]?: boolean;
14
+ }): void;
13
15
  export declare function expectProjectAndDepPlasmicJson(): void;
@@ -140,11 +140,13 @@ exports.project1Config = {
140
140
  jsBundleThemes: [],
141
141
  indirect: false,
142
142
  };
143
- function expectProject1PlasmicJson() {
143
+ function expectProject1PlasmicJson(optional) {
144
144
  const plasmicJson = exports.tmpRepo.readPlasmicJson();
145
145
  expect(plasmicJson.projects.length).toEqual(1);
146
146
  const projectConfig = plasmicJson.projects[0];
147
- expect(projectConfig.projectApiToken).toBe("abc");
147
+ if (!(optional === null || optional === void 0 ? void 0 : optional.projectApiToken)) {
148
+ expect(projectConfig.projectApiToken).toBe("abc");
149
+ }
148
150
  expect(projectConfig.components.length).toEqual(2);
149
151
  const componentNames = projectConfig.components.map((c) => c.name);
150
152
  expect(componentNames).toContain("Button");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasmicapp/cli",
3
- "version": "0.1.166",
3
+ "version": "0.1.167",
4
4
  "description": "plasmic cli for syncing local code with Plasmic designs",
5
5
  "engines": {
6
6
  "node": ">=12"
@@ -340,6 +340,8 @@ class PlasmicApi {
340
340
  globalVariantChecksums: [],
341
341
  projectCssChecksum: "",
342
342
  } as ChecksumBundle,
343
+ usedNpmPackages: [],
344
+ externalCssImports: [],
343
345
  };
344
346
  return result;
345
347
  }
@@ -71,11 +71,13 @@ describe("Project API tokens", () => {
71
71
 
72
72
  expectProject1Components();
73
73
 
74
- expectProject1PlasmicJson();
74
+ expectProject1PlasmicJson({ projectApiToken: true });
75
75
 
76
76
  // Re-run, this time with no auth.
77
77
  removeAuth();
78
- await expect(sync(opts)).resolves.toBeUndefined();
78
+ await expect(sync(opts)).rejects.toThrow(
79
+ "No user+token, and project API tokens don't match"
80
+ );
79
81
  });
80
82
 
81
83
  test("is filled in by auth'd user if project exists but token was initially missing", async () => {
@@ -88,11 +90,13 @@ describe("Project API tokens", () => {
88
90
 
89
91
  expectProject1Components();
90
92
 
91
- expectProject1PlasmicJson();
93
+ expectProject1PlasmicJson({ projectApiToken: true });
92
94
 
93
95
  // Re-run, this time with no auth.
94
96
  removeAuth();
95
- await expect(sync(opts)).resolves.toBeUndefined();
97
+ await expect(sync(opts)).rejects.toThrow(
98
+ "Unable to authenticate Plasmic. Please run 'plasmic auth' or check the projectApiTokens in your plasmic.json, and try again."
99
+ );
96
100
  });
97
101
 
98
102
  test("when not available, should prompt for auth", async () => {
@@ -315,6 +315,8 @@ export async function sync(
315
315
  ].map((p) => L.pick(p, "projectId", "projectApiToken"));
316
316
 
317
317
  context.api.attachProjectIdsAndTokens(projectIdsAndTokens);
318
+ const externalNpmPackages = new Set<string>();
319
+ const externalCssImports = new Set<string>();
318
320
 
319
321
  // Perform the actual sync
320
322
  await withBufferedFs(async () => {
@@ -332,6 +334,8 @@ export async function sync(
332
334
  summary,
333
335
  pendingMerge,
334
336
  projectMeta.indirect,
337
+ externalNpmPackages,
338
+ externalCssImports,
335
339
  metadataDefaults
336
340
  );
337
341
  }
@@ -416,6 +420,22 @@ export async function sync(
416
420
  await updateConfig(context, context.config, baseDir);
417
421
  });
418
422
 
423
+ await checkExternalPkgs(
424
+ context,
425
+ baseDir,
426
+ opts,
427
+ Array.from(externalNpmPackages.keys())
428
+ );
429
+
430
+ if (!opts.quiet && externalCssImports.size > 0) {
431
+ logger.info(
432
+ `This project uses external packages and styles. Make sure to import the following global CSS: ` +
433
+ Array.from(externalCssImports.keys())
434
+ .map((stmt) => `"${stmt}"`)
435
+ .join(", ")
436
+ );
437
+ }
438
+
419
439
  // Post-sync commands
420
440
  if (!opts.ignorePostSync) {
421
441
  for (const cmd of context.config.postSyncCommands || []) {
@@ -430,6 +450,30 @@ export async function sync(
430
450
  }
431
451
  }
432
452
 
453
+ async function checkExternalPkgs(
454
+ context: PlasmicContext,
455
+ baseDir: string,
456
+ opts: SyncArgs,
457
+ pkgs: string[]
458
+ ) {
459
+ const missingPkgs = pkgs.filter((pkg) => {
460
+ const installedPkg = findInstalledVersion(context, baseDir, pkg);
461
+ return !installedPkg;
462
+ });
463
+ if (missingPkgs.length > 0) {
464
+ const upgrade = await confirmWithUser(
465
+ `The following packages aren't installed but are required by some projects, would you like to install them? ${missingPkgs.join(
466
+ ", "
467
+ )}`,
468
+ opts.yes
469
+ );
470
+
471
+ if (upgrade) {
472
+ installUpgrade(missingPkgs.join(" "), baseDir);
473
+ }
474
+ }
475
+ }
476
+
433
477
  function maybeRenamePathExt(
434
478
  context: PlasmicContext,
435
479
  path: string,
@@ -480,6 +524,8 @@ async function syncProject(
480
524
  summary: Map<string, ComponentUpdateSummary>,
481
525
  pendingMerge: ComponentPendingMerge[],
482
526
  indirect: boolean,
527
+ externalNpmPackages: Set<string>,
528
+ externalCssImports: Set<string>,
483
529
  metadataDefaults?: Metadata
484
530
  ): Promise<void> {
485
531
  const newComponentScheme =
@@ -602,6 +648,12 @@ async function syncProject(
602
648
  projectBundle.imageAssets,
603
649
  projectBundle.checksums
604
650
  );
651
+ (projectBundle.usedNpmPackages || []).forEach((pkg) =>
652
+ externalNpmPackages.add(pkg)
653
+ );
654
+ (projectBundle.externalCssImports || []).forEach((css) =>
655
+ externalCssImports.add(css)
656
+ );
605
657
  }
606
658
 
607
659
  async function syncStyleConfig(
@@ -662,7 +714,6 @@ async function syncProjectConfig(
662
714
  if (!projectConfig.cssFilePath) {
663
715
  projectConfig.cssFilePath = defaultCssFilePath;
664
716
  }
665
- projectConfig.projectApiToken = projectApiToken;
666
717
 
667
718
  // plasmic.lock
668
719
  const projectLock = getOrAddProjectLock(context, projectConfig.projectId);
package/src/api.ts CHANGED
@@ -101,6 +101,8 @@ export interface ProjectBundle {
101
101
  iconAssets: IconBundle[];
102
102
  imageAssets: ImageBundle[];
103
103
  checksums: ChecksumBundle;
104
+ usedNpmPackages: string[];
105
+ externalCssImports: string[];
104
106
  }
105
107
 
106
108
  export type ProjectMeta = Omit<ProjectBundle, "projectConfig">;
@@ -150,11 +150,15 @@ export const project1Config: ProjectConfig = {
150
150
  indirect: false,
151
151
  };
152
152
 
153
- export function expectProject1PlasmicJson() {
153
+ export function expectProject1PlasmicJson(
154
+ optional?: { [k in keyof ProjectConfig]?: boolean }
155
+ ) {
154
156
  const plasmicJson = tmpRepo.readPlasmicJson();
155
157
  expect(plasmicJson.projects.length).toEqual(1);
156
158
  const projectConfig = plasmicJson.projects[0];
157
- expect(projectConfig.projectApiToken).toBe("abc");
159
+ if (!optional?.projectApiToken) {
160
+ expect(projectConfig.projectApiToken).toBe("abc");
161
+ }
158
162
  expect(projectConfig.components.length).toEqual(2);
159
163
  const componentNames = projectConfig.components.map((c) => c.name);
160
164
  expect(componentNames).toContain("Button");