@plasmicapp/cli 0.1.342 → 0.1.343

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasmicapp/cli",
3
- "version": "0.1.342",
3
+ "version": "0.1.343",
4
4
  "description": "plasmic cli for syncing local code with Plasmic designs",
5
5
  "engines": {
6
6
  "node": ">=12"
@@ -83,5 +83,5 @@
83
83
  "wrap-ansi": "^7.0.0",
84
84
  "yargs": "^15.4.1"
85
85
  },
86
- "gitHead": "354b30e84489d6a01d96855a04c844aa4fa80f3a"
86
+ "gitHead": "809dc071d1574484fc1d2da06f6ba9f380a1b19c"
87
87
  }
@@ -0,0 +1,173 @@
1
+ import chalk from "chalk";
2
+ import { CommonArgs } from "..";
3
+ import { logger } from "../deps";
4
+ import { getContext, readLock } from "../utils/get-context";
5
+ import * as semver from "../utils/semver";
6
+
7
+ const PROJECT_ID_WIDTH = 23;
8
+ const PROJECT_NAME_WIDTH = 30;
9
+ const BRANCH_NAME_WIDTH = 15;
10
+ const VERSION_WIDTH = 15;
11
+ const STATUS_WIDTH = 23;
12
+ const TOTAL_WIDTH =
13
+ PROJECT_ID_WIDTH +
14
+ PROJECT_NAME_WIDTH +
15
+ BRANCH_NAME_WIDTH +
16
+ VERSION_WIDTH * 3 +
17
+ STATUS_WIDTH;
18
+
19
+ export interface StatusArgs extends CommonArgs {
20
+ json?: boolean;
21
+ }
22
+
23
+ export async function showProjectStatus(opts: StatusArgs): Promise<void> {
24
+ const context = await getContext(opts, { skipInit: true });
25
+
26
+ const projects = context.config.projects;
27
+ if (projects.length === 0) {
28
+ logger.info("No projects found in plasmic.json");
29
+ return;
30
+ }
31
+
32
+ // Read lock file if it exists
33
+ const lockData = readLock(context.lockFile);
34
+
35
+ // Fetch latest versions from the server for all projects at once
36
+ let serverVersions: Record<string, string | null> = {};
37
+ try {
38
+ const resolution = await context.api.resolveSync(
39
+ projects.map((project) => ({
40
+ projectId: project.projectId,
41
+ branchName: project.projectBranchName || "main",
42
+ // We want to use ">=0.0.0" to get the latest published version.
43
+ // However, due to PLA-11698, this results in an error if the project
44
+ // has never been published. This is much more likely if the synced
45
+ // version is "latest".
46
+ versionRange: project.version === "latest" ? "latest" : ">=0.0.0",
47
+ componentIdOrNames: undefined,
48
+ projectApiToken: project.projectApiToken,
49
+ }))
50
+ );
51
+
52
+ resolution.projects?.forEach((resolvedProject) => {
53
+ serverVersions[resolvedProject.projectId] = resolvedProject.version;
54
+ });
55
+ } catch (error) {
56
+ // If we can't reach the server, we'll just show local information
57
+ logger.debug(`Could not fetch latest versions from server: ${error}`);
58
+ }
59
+
60
+ const projectData = projects.map((project) => {
61
+ // Find the corresponding lock entry
62
+ const lockEntry = lockData.projects?.find(
63
+ (p) => p.projectId === project.projectId
64
+ );
65
+
66
+ return {
67
+ projectId: project.projectId,
68
+ projectName: project.projectName,
69
+ branchName: project.projectBranchName,
70
+ plasmicJsonVersion: project.version,
71
+ plasmicLockVersion: lockEntry?.version || null,
72
+ serverVersion: serverVersions[project.projectId] || "unpublished",
73
+ };
74
+ });
75
+
76
+ if (opts.json) {
77
+ // Output as JSON
78
+ logger.info(JSON.stringify(projectData, null, 2));
79
+ } else {
80
+ // Output as formatted table
81
+ logger.info(chalk.bold("\nPlasmic Project Sync Status\n"));
82
+ logger.info(chalk.gray("─".repeat(TOTAL_WIDTH)));
83
+
84
+ // Header
85
+ logger.info(
86
+ chalk.bold(padRight("Project ID", PROJECT_ID_WIDTH)) +
87
+ chalk.bold(padRight("Project", PROJECT_NAME_WIDTH)) +
88
+ chalk.bold(padRight("Branch", BRANCH_NAME_WIDTH)) +
89
+ chalk.bold(padRight("plasmic.json", VERSION_WIDTH)) +
90
+ chalk.bold(padRight("plasmic.lock", VERSION_WIDTH)) +
91
+ chalk.bold(padRight("server", VERSION_WIDTH)) +
92
+ chalk.bold("Status")
93
+ );
94
+ logger.info(chalk.gray("─".repeat(TOTAL_WIDTH)));
95
+
96
+ let notSynced = 0;
97
+ let updateAvailable = 0;
98
+ let updateStatusUnknown = 0;
99
+ for (const status of projectData) {
100
+ const projectIdDisplay = padRight(status.projectId, 23);
101
+ const projectNameDisplay = padRight(
102
+ status.projectName.substring(0, 29),
103
+ 30
104
+ );
105
+ const branchDisplay = padRight(status.branchName || "main", 15);
106
+ const targetDisplay = padRight(status.plasmicJsonVersion, 15);
107
+ const syncedDisplay = padRight(
108
+ status.plasmicLockVersion || "not synced",
109
+ 15
110
+ );
111
+ const latestDisplay = padRight(status.serverVersion || "unknown", 15);
112
+
113
+ let statusDisplay = "";
114
+ if (!status.plasmicLockVersion) {
115
+ statusDisplay = chalk.gray("! Not synced");
116
+ ++notSynced;
117
+ } else if (
118
+ !status.serverVersion ||
119
+ !semver.valid(status.serverVersion) ||
120
+ semver.isLatest(status.serverVersion)
121
+ ) {
122
+ // Can't compare if the server version is unknown or latest
123
+ statusDisplay = chalk.yellow("? Update status unknown");
124
+ ++updateStatusUnknown;
125
+ } else if (semver.lt(status.plasmicLockVersion, status.serverVersion)) {
126
+ statusDisplay = chalk.blue("↑ Update available");
127
+ ++updateAvailable;
128
+ } else {
129
+ statusDisplay = chalk.green("✓ Up-to-date");
130
+ }
131
+
132
+ logger.info(
133
+ projectIdDisplay +
134
+ projectNameDisplay +
135
+ branchDisplay +
136
+ targetDisplay +
137
+ syncedDisplay +
138
+ latestDisplay +
139
+ statusDisplay
140
+ );
141
+ }
142
+
143
+ logger.info(chalk.gray("─".repeat(TOTAL_WIDTH)));
144
+ logger.info("");
145
+
146
+ if (notSynced > 0) {
147
+ logger.info(chalk.yellow(`! ${notSynced} project(s) not synced`));
148
+ }
149
+ if (updateAvailable > 0) {
150
+ logger.info(chalk.blue(`↑ ${updateAvailable} project(s) can be updated`));
151
+ }
152
+ if (updateStatusUnknown > 0) {
153
+ logger.info(
154
+ chalk.yellow(
155
+ `? ${updateStatusUnknown} project(s) have unknown update status due to "latest" version in plasmic.json`
156
+ )
157
+ );
158
+ }
159
+ if (notSynced === 0 && updateAvailable === 0 && updateStatusUnknown === 0) {
160
+ logger.info(chalk.green("✓ All projects are up to date"));
161
+ }
162
+
163
+ logger.info("");
164
+ logger.info(chalk.gray("Run 'plasmic sync' to sync your projects"));
165
+ }
166
+ }
167
+
168
+ function padRight(str: string, length: number): string {
169
+ if (str.length >= length) {
170
+ return str.substring(0, length - 1) + " ";
171
+ }
172
+ return str + " ".repeat(length - str.length);
173
+ }
package/src/api.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import axios, { AxiosError } from "axios";
2
2
  import socketio from "socket.io-client";
3
+ import { logger } from "./deps";
3
4
  import {
4
5
  AuthConfig,
5
6
  CodeConfig,
@@ -484,6 +485,7 @@ export class PlasmicApi {
484
485
  // message
485
486
  private async post(url: string, data?: any, rethrowAppError?: boolean) {
486
487
  try {
488
+ logger.debug(`POST ${url}`);
487
489
  return await axios.post(
488
490
  url,
489
491
  { projectIdsAndTokens: this.projectIdsAndTokens, ...data },
@@ -509,6 +511,7 @@ export class PlasmicApi {
509
511
 
510
512
  private async get(url: string, rethrowAppError?: boolean, extraHeaders?: {}) {
511
513
  try {
514
+ logger.debug(`GET ${url}`);
512
515
  return await axios.get(url, {
513
516
  headers: { ...this.makeHeaders(), ...(extraHeaders ?? {}) },
514
517
  });
package/src/deps.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import winston from "winston";
2
2
 
3
3
  export const logger = winston.createLogger({
4
- level: "info",
4
+ level: process.env.LOG_LEVEL ?? "info",
5
5
  format: winston.format.json(),
6
6
  defaultMeta: {},
7
7
  transports: [
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import yargs from "yargs";
3
3
  import * as auth from "./actions/auth";
4
+ import { ExportArgs, exportProjectsCli } from "./actions/export";
4
5
  import { fixImports, FixImportsArgs } from "./actions/fix-imports";
5
6
  import { InfoArgs, printProjectInfo } from "./actions/info";
6
7
  import { getYargsOption, InitArgs, initPlasmic } from "./actions/init";
@@ -10,11 +11,11 @@ import {
10
11
  LocalizationStringsArgs,
11
12
  } from "./actions/localization-strings";
12
13
  import * as projectToken from "./actions/project-token";
14
+ import { showProjectStatus, StatusArgs } from "./actions/status";
13
15
  import { sync, SyncArgs } from "./actions/sync";
14
16
  import { UploadBundleArgs, uploadJsBundle } from "./actions/upload-bundle";
15
17
  import { WatchArgs, watchProjects } from "./actions/watch";
16
18
  import { handleError } from "./utils/error";
17
- import { ExportArgs, exportProjectsCli } from "./actions/export";
18
19
 
19
20
  if (process.env.DEBUG_CHDIR) {
20
21
  process.chdir(process.env.DEBUG_CHDIR);
@@ -106,6 +107,17 @@ yargs
106
107
  handleError(auth.auth(argv));
107
108
  }
108
109
  )
110
+ .command<StatusArgs>(
111
+ "status",
112
+ "Shows the status of local Plasmic projects.",
113
+ (yargs) =>
114
+ yargs.option("json", {
115
+ describe: "Output status in JSON format",
116
+ type: "boolean",
117
+ default: false,
118
+ }),
119
+ (argv) => handleError(showProjectStatus(argv))
120
+ )
109
121
  .command<SyncArgs>(
110
122
  "sync",
111
123
  "Syncs designs from Plasmic to local files.",
@@ -2,8 +2,8 @@ import fs from "fs";
2
2
  import * as path from "path";
3
3
  import * as tmp from "tmp";
4
4
  import {
5
- AuthConfig,
6
5
  AUTH_FILE_NAME,
6
+ AuthConfig,
7
7
  CONFIG_FILE_NAME,
8
8
  PlasmicConfig,
9
9
  } from "../utils/config-utils";