@plasmicapp/cli 0.1.178 → 0.1.179

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.
@@ -74,17 +74,47 @@ function watchProjects(opts, metadataDefaults, onProjectUpdate) {
74
74
  socket.on("error", (data) => {
75
75
  reject(new error_1.HandledError(data));
76
76
  });
77
- socket.on("update", (data) => __awaiter(this, void 0, void 0, function* () {
77
+ socket.on("update", asyncOneAtATime((data) => __awaiter(this, void 0, void 0, function* () {
78
78
  // Just run syncProjects() for now when any project has been updated
79
79
  // Note on the 'updated to revision' part: this is parsed by the
80
80
  // loader package to know that we finished updating the components.
81
81
  yield sync_1.sync(syncOpts, syncMetadata);
82
82
  deps_1.logger.info(`[${moment_1.default().format("HH:mm:ss")}] Project ${data.projectId} updated to revision ${data.revisionNum}`);
83
83
  onProjectUpdate === null || onProjectUpdate === void 0 ? void 0 : onProjectUpdate();
84
- }));
84
+ }), true));
85
85
  });
86
86
  deps_1.logger.info(`Watching projects ${latestProjects} ...`);
87
87
  return promise;
88
88
  });
89
89
  }
90
90
  exports.watchProjects = watchProjects;
91
+ function asyncOneAtATime(f, bounceValue) {
92
+ let waitingCall = undefined, currentPromise = undefined;
93
+ function invoke({ args, resolve, reject }) {
94
+ const onCompletion = () => {
95
+ currentPromise = undefined;
96
+ if (waitingCall) {
97
+ invoke(waitingCall);
98
+ waitingCall = undefined;
99
+ }
100
+ };
101
+ currentPromise = f(...args);
102
+ currentPromise.then(onCompletion, onCompletion);
103
+ currentPromise.then(resolve, reject);
104
+ }
105
+ return (...args) => {
106
+ return new Promise((resolve, reject) => {
107
+ if (!currentPromise) {
108
+ // Free to proceed.
109
+ invoke({ args, resolve, reject });
110
+ }
111
+ else {
112
+ // Evict current waiter, and enqueue self.
113
+ if (waitingCall) {
114
+ waitingCall.resolve(bounceValue);
115
+ }
116
+ waitingCall = { args, resolve, reject };
117
+ }
118
+ });
119
+ };
120
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasmicapp/cli",
3
- "version": "0.1.178",
3
+ "version": "0.1.179",
4
4
  "description": "plasmic cli for syncing local code with Plasmic designs",
5
5
  "engines": {
6
6
  "node": ">=12"
@@ -75,21 +75,72 @@ export async function watchProjects(
75
75
  socket.on("error", (data: any) => {
76
76
  reject(new HandledError(data));
77
77
  });
78
- socket.on("update", async (data: any) => {
79
- // Just run syncProjects() for now when any project has been updated
80
- // Note on the 'updated to revision' part: this is parsed by the
81
- // loader package to know that we finished updating the components.
82
- await sync(syncOpts, syncMetadata);
83
- logger.info(
84
- `[${moment().format("HH:mm:ss")}] Project ${
85
- data.projectId
86
- } updated to revision ${data.revisionNum}`
87
- );
78
+ socket.on(
79
+ "update",
80
+ asyncOneAtATime(async (data: any) => {
81
+ // Just run syncProjects() for now when any project has been updated
82
+ // Note on the 'updated to revision' part: this is parsed by the
83
+ // loader package to know that we finished updating the components.
84
+ await sync(syncOpts, syncMetadata);
85
+ logger.info(
86
+ `[${moment().format("HH:mm:ss")}] Project ${
87
+ data.projectId
88
+ } updated to revision ${data.revisionNum}`
89
+ );
88
90
 
89
- onProjectUpdate?.();
90
- });
91
+ onProjectUpdate?.();
92
+ }, true)
93
+ );
91
94
  });
92
95
 
93
96
  logger.info(`Watching projects ${latestProjects} ...`);
94
97
  return promise;
95
98
  }
99
+
100
+ /**
101
+ * Throttle invocations of a function to allow a single outstanding invocation
102
+ * at a time.
103
+ *
104
+ * But, has a buffer of size one, so that after the current invocation
105
+ * completes, it calls the last attempted invocation.
106
+ *
107
+ * Other invocations that get evicted from the buffer get returned bounceValue
108
+ * upon eviction.
109
+ */
110
+ type AsyncCallable = (...args: any[]) => Promise<any>;
111
+
112
+ function asyncOneAtATime(f: AsyncCallable, bounceValue: any): AsyncCallable {
113
+ interface CallInfo {
114
+ args: any[];
115
+ resolve: any;
116
+ reject: any;
117
+ }
118
+ let waitingCall: CallInfo | undefined = undefined,
119
+ currentPromise: Promise<any> | undefined = undefined;
120
+ function invoke({ args, resolve, reject }: CallInfo) {
121
+ const onCompletion = () => {
122
+ currentPromise = undefined;
123
+ if (waitingCall) {
124
+ invoke(waitingCall);
125
+ waitingCall = undefined;
126
+ }
127
+ };
128
+ currentPromise = f(...args);
129
+ currentPromise.then(onCompletion, onCompletion);
130
+ currentPromise.then(resolve, reject);
131
+ }
132
+ return (...args: any[]) => {
133
+ return new Promise((resolve, reject) => {
134
+ if (!currentPromise) {
135
+ // Free to proceed.
136
+ invoke({ args, resolve, reject });
137
+ } else {
138
+ // Evict current waiter, and enqueue self.
139
+ if (waitingCall) {
140
+ waitingCall.resolve(bounceValue);
141
+ }
142
+ waitingCall = { args, resolve, reject };
143
+ }
144
+ });
145
+ };
146
+ }