symlx 0.1.0 → 0.1.1
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 +15 -15
- package/dist/cli.js +3 -3
- package/dist/commands/serve.js +3 -3
- package/dist/core/paths.js +4 -4
- package/dist/services/lifecycle.js +2 -2
- package/dist/services/session-store.js +2 -2
- package/dist/ui/logger.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# symlx
|
|
2
2
|
|
|
3
3
|
Temporary CLI bin linker for local development.
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
`
|
|
7
|
+
`symlx serve` reads the current project's `package.json` `bin` entries and symlinks them into:
|
|
8
8
|
|
|
9
|
-
`~/.
|
|
9
|
+
`~/.symlx/bin`
|
|
10
10
|
|
|
11
|
-
While `
|
|
11
|
+
While `symlx serve` is running, those commands can be used from anywhere (if `~/.symlx/bin` is on your `PATH`).
|
|
12
12
|
|
|
13
13
|
When the process exits, it removes only the links it created.
|
|
14
14
|
|
|
15
15
|
## Command framework and structure
|
|
16
16
|
|
|
17
|
-
`
|
|
17
|
+
`symlx` uses:
|
|
18
18
|
|
|
19
19
|
- `commander` for command orchestration and typed options.
|
|
20
20
|
- `prompts` for interactive/TUI collision handling.
|
|
@@ -29,30 +29,30 @@ Project layout:
|
|
|
29
29
|
## Usage
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
npx
|
|
32
|
+
npx symlx serve
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
or if installed globally:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
|
|
38
|
+
symlx serve
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
### Serve options
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
symlx serve --collision prompt
|
|
45
|
+
symlx serve --collision skip
|
|
46
|
+
symlx serve --collision fail
|
|
47
|
+
symlx serve --collision overwrite
|
|
48
|
+
symlx serve --non-interactive
|
|
49
|
+
symlx serve --bin-dir /custom/bin
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
If your shell does not already include `~/.
|
|
52
|
+
If your shell does not already include `~/.symlx/bin`, add:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
export PATH="$HOME/.
|
|
55
|
+
export PATH="$HOME/.symlx/bin:$PATH"
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
## Notes
|
package/dist/cli.js
CHANGED
|
@@ -50,13 +50,13 @@ async function main() {
|
|
|
50
50
|
// Commander orchestrates top-level commands/options and help output.
|
|
51
51
|
const program = new commander_1.Command();
|
|
52
52
|
program
|
|
53
|
-
.name("
|
|
53
|
+
.name("symlx")
|
|
54
54
|
.description("Temporary CLI bin linker with lifecycle cleanup")
|
|
55
55
|
.showHelpAfterError();
|
|
56
56
|
program
|
|
57
57
|
.command("serve")
|
|
58
|
-
.description("Link this project's package.json bins until
|
|
59
|
-
.option("--bin-dir <dir>", "target bin directory (default: ~/.
|
|
58
|
+
.description("Link this project's package.json bins until symlx exits")
|
|
59
|
+
.option("--bin-dir <dir>", "target bin directory (default: ~/.symlx/bin)")
|
|
60
60
|
.option("--collision <policy>", "collision mode: prompt|skip|fail|overwrite", "prompt")
|
|
61
61
|
.option("--non-interactive", "disable interactive prompts", false)
|
|
62
62
|
.action(async (options) => {
|
package/dist/commands/serve.js
CHANGED
|
@@ -45,16 +45,16 @@ const log = __importStar(require("../ui/logger"));
|
|
|
45
45
|
function isInteractiveSession() {
|
|
46
46
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
47
47
|
}
|
|
48
|
-
// Main
|
|
48
|
+
// Main symlx behavior:
|
|
49
49
|
// 1) resolve bins from package.json
|
|
50
50
|
// 2) create links
|
|
51
51
|
// 3) persist session
|
|
52
52
|
// 4) keep process alive and cleanup on exit
|
|
53
53
|
async function runServe(options) {
|
|
54
54
|
const cwd = process.cwd();
|
|
55
|
-
const paths = (0, paths_1.
|
|
55
|
+
const paths = (0, paths_1.getSymlxPaths)(options.binDir);
|
|
56
56
|
// Prepare runtime directories and recover stale sessions from previous abnormal exits.
|
|
57
|
-
(0, session_store_1.
|
|
57
|
+
(0, session_store_1.ensureSymlxDirectories)(paths.binDir, paths.sessionDir);
|
|
58
58
|
(0, session_store_1.cleanupStaleSessions)(paths.sessionDir);
|
|
59
59
|
const bins = (0, package_bins_1.readBins)(cwd);
|
|
60
60
|
// Prompt policy only works when we can interact with a TTY.
|
package/dist/core/paths.js
CHANGED
|
@@ -3,14 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.getSymlxPaths = getSymlxPaths;
|
|
7
7
|
exports.pathContainsDir = pathContainsDir;
|
|
8
8
|
const node_os_1 = __importDefault(require("node:os"));
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
// Central place for runtime paths so every command/service resolves locations consistently.
|
|
11
|
-
function
|
|
12
|
-
//
|
|
13
|
-
const rootDir = node_path_1.default.join(node_os_1.default.homedir(), ".
|
|
11
|
+
function getSymlxPaths(customBinDir) {
|
|
12
|
+
// symlx keeps mutable runtime state under the user's home directory.
|
|
13
|
+
const rootDir = node_path_1.default.join(node_os_1.default.homedir(), ".symlx");
|
|
14
14
|
// Commands are linked here unless the caller overrides with --bin-dir.
|
|
15
15
|
const binDir = customBinDir ? node_path_1.default.resolve(customBinDir) : node_path_1.default.join(rootDir, "bin");
|
|
16
16
|
// Session files live separately from bins and are used for stale cleanup.
|
|
@@ -24,12 +24,12 @@ function registerLifecycleCleanup(cleanup) {
|
|
|
24
24
|
process.on("SIGHUP", onSignal);
|
|
25
25
|
// Fatal process events still attempt cleanup before exiting with failure.
|
|
26
26
|
process.on("uncaughtException", (error) => {
|
|
27
|
-
process.stderr.write(`[
|
|
27
|
+
process.stderr.write(`[symlx] uncaught exception: ${String(error)}\n`);
|
|
28
28
|
runCleanup();
|
|
29
29
|
process.exit(1);
|
|
30
30
|
});
|
|
31
31
|
process.on("unhandledRejection", (reason) => {
|
|
32
|
-
process.stderr.write(`[
|
|
32
|
+
process.stderr.write(`[symlx] unhandled rejection: ${String(reason)}\n`);
|
|
33
33
|
runCleanup();
|
|
34
34
|
process.exit(1);
|
|
35
35
|
});
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.ensureSymlxDirectories = ensureSymlxDirectories;
|
|
7
7
|
exports.cleanupStaleSessions = cleanupStaleSessions;
|
|
8
8
|
exports.persistSession = persistSession;
|
|
9
9
|
exports.createSessionFilePath = createSessionFilePath;
|
|
@@ -68,7 +68,7 @@ function cleanupLinks(links) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
// Ensures runtime directories exist before linking/saving sessions.
|
|
71
|
-
function
|
|
71
|
+
function ensureSymlxDirectories(binDir, sessionDir) {
|
|
72
72
|
node_fs_1.default.mkdirSync(binDir, { recursive: true });
|
|
73
73
|
node_fs_1.default.mkdirSync(sessionDir, { recursive: true });
|
|
74
74
|
}
|
package/dist/ui/logger.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.info = info;
|
|
4
4
|
exports.warn = warn;
|
|
5
5
|
exports.error = error;
|
|
6
|
-
const PREFIX = "[
|
|
6
|
+
const PREFIX = "[symlx]";
|
|
7
7
|
// Thin logging wrappers keep formatting centralized and easy to swap later.
|
|
8
8
|
function info(message) {
|
|
9
9
|
process.stdout.write(`${PREFIX} ${message}\n`);
|