@hooklink/cli 0.1.68 → 0.1.70

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.
Files changed (109) hide show
  1. package/dist/__tests__/agent/lease.test.d.ts +2 -0
  2. package/dist/__tests__/agent/lease.test.d.ts.map +1 -0
  3. package/dist/__tests__/agent/lease.test.js +31 -0
  4. package/dist/__tests__/agent/lease.test.js.map +1 -0
  5. package/dist/__tests__/agent/local-server.test.d.ts +9 -0
  6. package/dist/__tests__/agent/local-server.test.d.ts.map +1 -0
  7. package/dist/__tests__/agent/local-server.test.js +218 -0
  8. package/dist/__tests__/agent/local-server.test.js.map +1 -0
  9. package/dist/__tests__/agent/local-token.test.d.ts +2 -0
  10. package/dist/__tests__/agent/local-token.test.d.ts.map +1 -0
  11. package/dist/__tests__/agent/local-token.test.js +42 -0
  12. package/dist/__tests__/agent/local-token.test.js.map +1 -0
  13. package/dist/__tests__/agent/state.test.d.ts +2 -0
  14. package/dist/__tests__/agent/state.test.d.ts.map +1 -0
  15. package/dist/__tests__/agent/state.test.js +63 -0
  16. package/dist/__tests__/agent/state.test.js.map +1 -0
  17. package/dist/__tests__/agent/supervisor.test.d.ts +2 -0
  18. package/dist/__tests__/agent/supervisor.test.d.ts.map +1 -0
  19. package/dist/__tests__/agent/supervisor.test.js +126 -0
  20. package/dist/__tests__/agent/supervisor.test.js.map +1 -0
  21. package/dist/__tests__/json-events.test.d.ts +2 -0
  22. package/dist/__tests__/json-events.test.d.ts.map +1 -0
  23. package/dist/__tests__/json-events.test.js +101 -0
  24. package/dist/__tests__/json-events.test.js.map +1 -0
  25. package/dist/agent/endpoint-resolver.d.ts +35 -0
  26. package/dist/agent/endpoint-resolver.d.ts.map +1 -0
  27. package/dist/agent/endpoint-resolver.js +181 -0
  28. package/dist/agent/endpoint-resolver.js.map +1 -0
  29. package/dist/agent/lease.d.ts +18 -0
  30. package/dist/agent/lease.d.ts.map +1 -0
  31. package/dist/agent/lease.js +40 -0
  32. package/dist/agent/lease.js.map +1 -0
  33. package/dist/agent/local-server.d.ts +69 -0
  34. package/dist/agent/local-server.d.ts.map +1 -0
  35. package/dist/agent/local-server.js +426 -0
  36. package/dist/agent/local-server.js.map +1 -0
  37. package/dist/agent/local-token.d.ts +18 -0
  38. package/dist/agent/local-token.d.ts.map +1 -0
  39. package/dist/agent/local-token.js +65 -0
  40. package/dist/agent/local-token.js.map +1 -0
  41. package/dist/agent/paths.d.ts +12 -0
  42. package/dist/agent/paths.d.ts.map +1 -0
  43. package/dist/agent/paths.js +37 -0
  44. package/dist/agent/paths.js.map +1 -0
  45. package/dist/agent/preflight.d.ts +18 -0
  46. package/dist/agent/preflight.d.ts.map +1 -0
  47. package/dist/agent/preflight.js +87 -0
  48. package/dist/agent/preflight.js.map +1 -0
  49. package/dist/agent/resolve-bin.d.ts +26 -0
  50. package/dist/agent/resolve-bin.d.ts.map +1 -0
  51. package/dist/agent/resolve-bin.js +55 -0
  52. package/dist/agent/resolve-bin.js.map +1 -0
  53. package/dist/agent/service/darwin.d.ts +9 -0
  54. package/dist/agent/service/darwin.d.ts.map +1 -0
  55. package/dist/agent/service/darwin.js +85 -0
  56. package/dist/agent/service/darwin.js.map +1 -0
  57. package/dist/agent/service/index.d.ts +24 -0
  58. package/dist/agent/service/index.d.ts.map +1 -0
  59. package/dist/agent/service/index.js +71 -0
  60. package/dist/agent/service/index.js.map +1 -0
  61. package/dist/agent/service/linux.d.ts +10 -0
  62. package/dist/agent/service/linux.d.ts.map +1 -0
  63. package/dist/agent/service/linux.js +75 -0
  64. package/dist/agent/service/linux.js.map +1 -0
  65. package/dist/agent/service/win32.d.ts +9 -0
  66. package/dist/agent/service/win32.d.ts.map +1 -0
  67. package/dist/agent/service/win32.js +109 -0
  68. package/dist/agent/service/win32.js.map +1 -0
  69. package/dist/agent/state.d.ts +25 -0
  70. package/dist/agent/state.d.ts.map +1 -0
  71. package/dist/agent/state.js +63 -0
  72. package/dist/agent/state.js.map +1 -0
  73. package/dist/agent/supervisor.d.ts +116 -0
  74. package/dist/agent/supervisor.d.ts.map +1 -0
  75. package/dist/agent/supervisor.js +353 -0
  76. package/dist/agent/supervisor.js.map +1 -0
  77. package/dist/agent/zombie-cleanup.d.ts +20 -0
  78. package/dist/agent/zombie-cleanup.d.ts.map +1 -0
  79. package/dist/agent/zombie-cleanup.js +124 -0
  80. package/dist/agent/zombie-cleanup.js.map +1 -0
  81. package/dist/commands/agent.d.ts +12 -0
  82. package/dist/commands/agent.d.ts.map +1 -0
  83. package/dist/commands/agent.js +173 -0
  84. package/dist/commands/agent.js.map +1 -0
  85. package/dist/commands/connect.d.ts.map +1 -1
  86. package/dist/commands/connect.js +106 -8
  87. package/dist/commands/connect.js.map +1 -1
  88. package/dist/commands/tunnel.d.ts.map +1 -1
  89. package/dist/commands/tunnel.js +103 -4
  90. package/dist/commands/tunnel.js.map +1 -1
  91. package/dist/core/websocket-client.d.ts +2 -0
  92. package/dist/core/websocket-client.d.ts.map +1 -1
  93. package/dist/core/websocket-client.js +6 -0
  94. package/dist/core/websocket-client.js.map +1 -1
  95. package/dist/core/websocket-pool.d.ts +1 -0
  96. package/dist/core/websocket-pool.d.ts.map +1 -1
  97. package/dist/core/websocket-pool.js +3 -0
  98. package/dist/core/websocket-pool.js.map +1 -1
  99. package/dist/index.js +7 -1
  100. package/dist/index.js.map +1 -1
  101. package/dist/utils/json-events.d.ts +32 -0
  102. package/dist/utils/json-events.d.ts.map +1 -0
  103. package/dist/utils/json-events.js +71 -0
  104. package/dist/utils/json-events.js.map +1 -0
  105. package/dist/utils/logger.d.ts +6 -0
  106. package/dist/utils/logger.d.ts.map +1 -1
  107. package/dist/utils/logger.js +30 -0
  108. package/dist/utils/logger.js.map +1 -1
  109. package/package.json +17 -13
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /**
3
+ * HEAD/GET reachability check for a prospective tunnel target.
4
+ *
5
+ * Accepts any HTTP status (including 4xx/5xx) as proof the target
6
+ * is alive. A WP login page returning 302 or 401 still counts as
7
+ * reachable. ECONNREFUSED / DNS / timeout all produce
8
+ * `target_unreachable`.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.preflight = preflight;
15
+ const http_1 = __importDefault(require("http"));
16
+ const https_1 = __importDefault(require("https"));
17
+ async function preflight(target, options = {}) {
18
+ let url;
19
+ try {
20
+ url = new URL(target);
21
+ }
22
+ catch {
23
+ return { ok: false, code: 'invalid_url', detail: 'Could not parse URL' };
24
+ }
25
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
26
+ return {
27
+ ok: false,
28
+ code: 'invalid_url',
29
+ detail: `Unsupported protocol: ${url.protocol}`,
30
+ };
31
+ }
32
+ const timeoutMs = options.timeoutMs ?? 2000;
33
+ // Try HEAD first; if the server refuses HEAD (some dev servers do),
34
+ // fall back to GET.
35
+ const head = await attempt(url, 'HEAD', timeoutMs);
36
+ if (head.ok)
37
+ return { ok: true };
38
+ if (head.code === 'target_unreachable') {
39
+ // Target clearly down (connection refused / DNS / timeout); don't retry.
40
+ return head;
41
+ }
42
+ // HEAD returned a non-network error (e.g. 405 Method Not Allowed).
43
+ const get = await attempt(url, 'GET', timeoutMs);
44
+ return get;
45
+ }
46
+ async function attempt(url, method, timeoutMs) {
47
+ return new Promise((resolve) => {
48
+ const client = url.protocol === 'https:' ? https_1.default : http_1.default;
49
+ const req = client.request({
50
+ method,
51
+ hostname: url.hostname,
52
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
53
+ path: `${url.pathname}${url.search}` || '/',
54
+ timeout: timeoutMs,
55
+ // Self-signed local certs are common (localhost HTTPS, .test domains).
56
+ rejectUnauthorized: false,
57
+ }, (res) => {
58
+ // Any status is success: the target is serving HTTP.
59
+ res.resume();
60
+ if (res.statusCode &&
61
+ res.statusCode === 405 &&
62
+ method === 'HEAD') {
63
+ resolve({ ok: false, code: undefined, detail: 'HEAD not allowed' });
64
+ }
65
+ else {
66
+ resolve({ ok: true });
67
+ }
68
+ });
69
+ req.on('timeout', () => {
70
+ req.destroy();
71
+ resolve({
72
+ ok: false,
73
+ code: 'target_unreachable',
74
+ detail: `${method} timed out after ${timeoutMs}ms`,
75
+ });
76
+ });
77
+ req.on('error', (err) => {
78
+ resolve({
79
+ ok: false,
80
+ code: 'target_unreachable',
81
+ detail: err.code || err.message,
82
+ });
83
+ });
84
+ req.end();
85
+ });
86
+ }
87
+ //# sourceMappingURL=preflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/agent/preflight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Resolve a stable absolute path to the `hooklink` binary for the
3
+ * agent to invoke. `process.argv[0]` points at node, `process.argv[1]`
4
+ * at the CLI entry script; neither is directly invokable across
5
+ * restarts when nvm/pnpm/Volta shims are in play. We also want the
6
+ * service unit to survive shell-version changes.
7
+ *
8
+ * Strategy:
9
+ * 1. Follow symlinks from `process.argv[1]` via realpathSync.
10
+ * 2. If it lives inside a nvm/pnpm/Volta shim dir, warn the
11
+ * caller (they should pass `--absolute` and pin a path).
12
+ * 3. Pair it with `process.execPath` (a real node binary) so the
13
+ * service can `ExecStart=<node> <cli-entry>`.
14
+ */
15
+ export interface ResolvedBinary {
16
+ /** The node binary to invoke (always process.execPath.realpath). */
17
+ node: string;
18
+ /** The hooklink entry script (dist/index.js), as a canonical abs path. */
19
+ entry: string;
20
+ /** Whether the resolver thinks the path is safely stable. */
21
+ stable: boolean;
22
+ /** Reason stable=false, for user-facing warnings. */
23
+ warning?: string;
24
+ }
25
+ export declare function resolveBinary(): ResolvedBinary;
26
+ //# sourceMappingURL=resolve-bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-bin.d.ts","sourceRoot":"","sources":["../../src/agent/resolve-bin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,wBAAgB,aAAa,IAAI,cAAc,CAyB9C"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ /**
3
+ * Resolve a stable absolute path to the `hooklink` binary for the
4
+ * agent to invoke. `process.argv[0]` points at node, `process.argv[1]`
5
+ * at the CLI entry script; neither is directly invokable across
6
+ * restarts when nvm/pnpm/Volta shims are in play. We also want the
7
+ * service unit to survive shell-version changes.
8
+ *
9
+ * Strategy:
10
+ * 1. Follow symlinks from `process.argv[1]` via realpathSync.
11
+ * 2. If it lives inside a nvm/pnpm/Volta shim dir, warn the
12
+ * caller (they should pass `--absolute` and pin a path).
13
+ * 3. Pair it with `process.execPath` (a real node binary) so the
14
+ * service can `ExecStart=<node> <cli-entry>`.
15
+ */
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.resolveBinary = resolveBinary;
21
+ const fs_1 = __importDefault(require("fs"));
22
+ const path_1 = __importDefault(require("path"));
23
+ const UNSTABLE_SEGMENTS = ['/.nvm/', '/.pnpm/', '/.volta/', '/n/versions/'];
24
+ function resolveBinary() {
25
+ const nodeBin = safeRealpath(process.execPath);
26
+ const entry = safeRealpath(process.argv[1] ?? '');
27
+ if (!entry) {
28
+ return {
29
+ node: nodeBin,
30
+ entry: process.argv[1] ?? '',
31
+ stable: false,
32
+ warning: 'Could not resolve CLI entry path.',
33
+ };
34
+ }
35
+ for (const segment of UNSTABLE_SEGMENTS) {
36
+ if (entry.includes(segment) || nodeBin.includes(segment)) {
37
+ return {
38
+ node: nodeBin,
39
+ entry,
40
+ stable: false,
41
+ warning: `Hooklink CLI resolves under ${segment.trim()}. Node/CLI version changes will break the service. Consider reinstalling via \`curl ...hooklink.net/install.sh | bash\`.`,
42
+ };
43
+ }
44
+ }
45
+ return { node: nodeBin, entry, stable: true };
46
+ }
47
+ function safeRealpath(p) {
48
+ try {
49
+ return fs_1.default.realpathSync(p);
50
+ }
51
+ catch {
52
+ return path_1.default.resolve(p);
53
+ }
54
+ }
55
+ //# sourceMappingURL=resolve-bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-bin.js","sourceRoot":"","sources":["../../src/agent/resolve-bin.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;AAkBH,sCAyBC;AAzCD,4CAAoB;AACpB,gDAAwB;AAaxB,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;AAE5E,SAAgB,aAAa;IAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAElD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;YAC5B,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,mCAAmC;SAC7C,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,OAAO;gBACL,IAAI,EAAE,OAAO;gBACb,KAAK;gBACL,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,+BAA+B,OAAO,CAAC,IAAI,EAAE,0HAA0H;aACjL,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,OAAO,YAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * macOS user launchd agent. Writes ~/Library/LaunchAgents/net.hooklink.agent.plist
3
+ * and loads it via `launchctl`.
4
+ */
5
+ import { ServiceInstallOptions, ServiceInstallResult, ServiceStatus, ServiceUninstallOptions } from './index';
6
+ export declare function install(opts: ServiceInstallOptions): Promise<ServiceInstallResult>;
7
+ export declare function uninstall(_opts: ServiceUninstallOptions): Promise<void>;
8
+ export declare function status(_opts: ServiceUninstallOptions): Promise<ServiceStatus>;
9
+ //# sourceMappingURL=darwin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin.d.ts","sourceRoot":"","sources":["../../../src/agent/service/darwin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAqCjB,wBAAsB,OAAO,CAC3B,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAc/B;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E;AAED,wBAAsB,MAAM,CAC1B,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,aAAa,CAAC,CASxB"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * macOS user launchd agent. Writes ~/Library/LaunchAgents/net.hooklink.agent.plist
4
+ * and loads it via `launchctl`.
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.install = install;
11
+ exports.uninstall = uninstall;
12
+ exports.status = status;
13
+ const child_process_1 = require("child_process");
14
+ const fs_1 = __importDefault(require("fs"));
15
+ const os_1 = __importDefault(require("os"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const LABEL = 'net.hooklink.agent';
18
+ function plistPath() {
19
+ return path_1.default.join(os_1.default.homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`);
20
+ }
21
+ function renderPlist(opts) {
22
+ const logDir = path_1.default.join(opts.home, 'service');
23
+ return `<?xml version="1.0" encoding="UTF-8"?>
24
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
25
+ <plist version="1.0">
26
+ <dict>
27
+ <key>Label</key><string>${LABEL}</string>
28
+ <key>ProgramArguments</key>
29
+ <array>
30
+ <string>${opts.nodePath}</string>
31
+ <string>${opts.entryPath}</string>
32
+ <string>agent</string>
33
+ </array>
34
+ <key>RunAtLoad</key><true/>
35
+ <key>KeepAlive</key>
36
+ <dict>
37
+ <key>SuccessfulExit</key><false/>
38
+ </dict>
39
+ <key>StandardOutPath</key><string>${path_1.default.join(logDir, 'stdout.log')}</string>
40
+ <key>StandardErrorPath</key><string>${path_1.default.join(logDir, 'stderr.log')}</string>
41
+ <key>EnvironmentVariables</key>
42
+ <dict>
43
+ <key>HOOKLINK_HOME</key><string>${opts.home}</string>
44
+ </dict>
45
+ </dict>
46
+ </plist>
47
+ `;
48
+ }
49
+ async function install(opts) {
50
+ const target = plistPath();
51
+ fs_1.default.mkdirSync(path_1.default.dirname(target), { recursive: true });
52
+ fs_1.default.mkdirSync(path_1.default.join(opts.home, 'service'), { recursive: true, mode: 0o700 });
53
+ fs_1.default.writeFileSync(target, renderPlist(opts), { mode: 0o644 });
54
+ // Unload first in case an older version is running.
55
+ try {
56
+ (0, child_process_1.execFileSync)('launchctl', ['unload', target], { stdio: 'ignore' });
57
+ }
58
+ catch {
59
+ // Fine if it wasn't loaded.
60
+ }
61
+ (0, child_process_1.execFileSync)('launchctl', ['load', target], { stdio: 'ignore' });
62
+ return {};
63
+ }
64
+ async function uninstall(_opts) {
65
+ const target = plistPath();
66
+ try {
67
+ (0, child_process_1.execFileSync)('launchctl', ['unload', target], { stdio: 'ignore' });
68
+ }
69
+ catch {
70
+ // Best effort.
71
+ }
72
+ if (fs_1.default.existsSync(target))
73
+ fs_1.default.unlinkSync(target);
74
+ }
75
+ async function status(_opts) {
76
+ const installed = fs_1.default.existsSync(plistPath());
77
+ return {
78
+ platform: 'darwin',
79
+ installed,
80
+ description: installed
81
+ ? `launchd agent is installed at ${plistPath()}`
82
+ : `launchd agent is not installed`,
83
+ };
84
+ }
85
+ //# sourceMappingURL=darwin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin.js","sourceRoot":"","sources":["../../../src/agent/service/darwin.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAgDH,0BAgBC;AAED,8BAQC;AAED,wBAWC;AArFD,iDAA6C;AAC7C,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AAQxB,MAAM,KAAK,GAAG,oBAAoB,CAAC;AAEnC,SAAS,SAAS;IAChB,OAAO,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,IAA2B;IAC9C,MAAM,MAAM,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/C,OAAO;;;;4BAImB,KAAK;;;cAGnB,IAAI,CAAC,QAAQ;cACb,IAAI,CAAC,SAAS;;;;;;;;sCAQU,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;wCAC7B,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;;;sCAGjC,IAAI,CAAC,IAAI;;;;CAI9C,CAAC;AACF,CAAC;AAEM,KAAK,UAAU,OAAO,CAC3B,IAA2B;IAE3B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChF,YAAE,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAE7D,oDAAoD;IACpD,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,4BAA4B;IAC9B,CAAC;IACD,IAAA,4BAAY,EAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC;AACZ,CAAC;AAEM,KAAK,UAAU,SAAS,CAAC,KAA8B;IAC5D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IACD,IAAI,YAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,YAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC;AAEM,KAAK,UAAU,MAAM,CAC1B,KAA8B;IAE9B,MAAM,SAAS,GAAG,YAAE,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7C,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,SAAS;QACT,WAAW,EAAE,SAAS;YACpB,CAAC,CAAC,iCAAiC,SAAS,EAAE,EAAE;YAChD,CAAC,CAAC,gCAAgC;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Thin adapter that dispatches install/uninstall to the right
3
+ * per-platform implementation.
4
+ */
5
+ export interface ServiceInstallOptions {
6
+ nodePath: string;
7
+ entryPath: string;
8
+ home: string;
9
+ }
10
+ export interface ServiceUninstallOptions {
11
+ home: string;
12
+ }
13
+ export interface ServiceInstallResult {
14
+ manualFallback?: string;
15
+ }
16
+ export interface ServiceStatus {
17
+ platform: NodeJS.Platform;
18
+ installed: boolean;
19
+ description: string;
20
+ }
21
+ export declare function installService(opts: ServiceInstallOptions): Promise<ServiceInstallResult>;
22
+ export declare function uninstallService(opts: ServiceUninstallOptions): Promise<void>;
23
+ export declare function serviceStatus(opts: ServiceUninstallOptions): Promise<ServiceStatus>;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/service/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD,wBAAsB,cAAc,CAClC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAExB"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * Thin adapter that dispatches install/uninstall to the right
4
+ * per-platform implementation.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ var __importDefault = (this && this.__importDefault) || function (mod) {
40
+ return (mod && mod.__esModule) ? mod : { "default": mod };
41
+ };
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.installService = installService;
44
+ exports.uninstallService = uninstallService;
45
+ exports.serviceStatus = serviceStatus;
46
+ const os_1 = __importDefault(require("os"));
47
+ const darwin = __importStar(require("./darwin"));
48
+ const linux = __importStar(require("./linux"));
49
+ const win32 = __importStar(require("./win32"));
50
+ function impl() {
51
+ switch (os_1.default.platform()) {
52
+ case 'darwin':
53
+ return darwin;
54
+ case 'linux':
55
+ return linux;
56
+ case 'win32':
57
+ return win32;
58
+ default:
59
+ throw new Error(`Unsupported platform: ${os_1.default.platform()}`);
60
+ }
61
+ }
62
+ async function installService(opts) {
63
+ return impl().install(opts);
64
+ }
65
+ async function uninstallService(opts) {
66
+ return impl().uninstall(opts);
67
+ }
68
+ async function serviceStatus(opts) {
69
+ return impl().status(opts);
70
+ }
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/service/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCH,wCAIC;AAED,4CAIC;AAED,sCAIC;AAtDD,4CAAoB;AACpB,iDAAmC;AACnC,+CAAiC;AACjC,+CAAiC;AAsBjC,SAAS,IAAI;IACX,QAAQ,YAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;QACtB,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,KAAK,CAAC;QACf,KAAK,OAAO;YACV,OAAO,KAAK,CAAC;QACf;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,YAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,IAA2B;IAE3B,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,IAA6B;IAE7B,OAAO,IAAI,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,IAA6B;IAE7B,OAAO,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Linux systemd user unit. Written to
3
+ * `~/.config/systemd/user/hooklink-agent.service` and started via
4
+ * `systemctl --user`.
5
+ */
6
+ import { ServiceInstallOptions, ServiceInstallResult, ServiceStatus, ServiceUninstallOptions } from './index';
7
+ export declare function install(opts: ServiceInstallOptions): Promise<ServiceInstallResult>;
8
+ export declare function uninstall(_opts: ServiceUninstallOptions): Promise<void>;
9
+ export declare function status(_opts: ServiceUninstallOptions): Promise<ServiceStatus>;
10
+ //# sourceMappingURL=linux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux.d.ts","sourceRoot":"","sources":["../../../src/agent/service/linux.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAuCjB,wBAAsB,OAAO,CAC3B,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAa/B;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AAED,wBAAsB,MAAM,CAC1B,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,aAAa,CAAC,CASxB"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /**
3
+ * Linux systemd user unit. Written to
4
+ * `~/.config/systemd/user/hooklink-agent.service` and started via
5
+ * `systemctl --user`.
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.install = install;
12
+ exports.uninstall = uninstall;
13
+ exports.status = status;
14
+ const child_process_1 = require("child_process");
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const os_1 = __importDefault(require("os"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const UNIT_NAME = 'hooklink-agent.service';
19
+ function unitPath() {
20
+ return path_1.default.join(os_1.default.homedir(), '.config', 'systemd', 'user', UNIT_NAME);
21
+ }
22
+ function renderUnit(opts) {
23
+ return `[Unit]
24
+ Description=Hooklink local agent
25
+ After=network-online.target
26
+
27
+ [Service]
28
+ Type=simple
29
+ ExecStart=${opts.nodePath} ${opts.entryPath} agent
30
+ Environment=HOOKLINK_HOME=${opts.home}
31
+ Restart=on-failure
32
+ RestartSec=5
33
+
34
+ [Install]
35
+ WantedBy=default.target
36
+ `;
37
+ }
38
+ function tryRun(cmd, args) {
39
+ try {
40
+ (0, child_process_1.execFileSync)(cmd, args, { stdio: 'ignore' });
41
+ }
42
+ catch {
43
+ // Caller decides if this is fatal.
44
+ }
45
+ }
46
+ async function install(opts) {
47
+ const target = unitPath();
48
+ fs_1.default.mkdirSync(path_1.default.dirname(target), { recursive: true });
49
+ fs_1.default.writeFileSync(target, renderUnit(opts), { mode: 0o644 });
50
+ tryRun('systemctl', ['--user', 'daemon-reload']);
51
+ tryRun('systemctl', ['--user', 'enable', UNIT_NAME]);
52
+ tryRun('systemctl', ['--user', 'restart', UNIT_NAME]);
53
+ return {
54
+ manualFallback: 'If the service did not auto-start, run: `systemctl --user start hooklink-agent`',
55
+ };
56
+ }
57
+ async function uninstall(_opts) {
58
+ tryRun('systemctl', ['--user', 'stop', UNIT_NAME]);
59
+ tryRun('systemctl', ['--user', 'disable', UNIT_NAME]);
60
+ const target = unitPath();
61
+ if (fs_1.default.existsSync(target))
62
+ fs_1.default.unlinkSync(target);
63
+ tryRun('systemctl', ['--user', 'daemon-reload']);
64
+ }
65
+ async function status(_opts) {
66
+ const installed = fs_1.default.existsSync(unitPath());
67
+ return {
68
+ platform: 'linux',
69
+ installed,
70
+ description: installed
71
+ ? `systemd user unit is installed at ${unitPath()}`
72
+ : `systemd user unit is not installed`,
73
+ };
74
+ }
75
+ //# sourceMappingURL=linux.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux.js","sourceRoot":"","sources":["../../../src/agent/service/linux.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;AAkDH,0BAeC;AAED,8BAMC;AAED,wBAWC;AApFD,iDAA6C;AAC7C,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AAQxB,MAAM,SAAS,GAAG,wBAAwB,CAAC;AAE3C,SAAS,QAAQ;IACf,OAAO,cAAI,CAAC,IAAI,CACd,YAAE,CAAC,OAAO,EAAE,EACZ,SAAS,EACT,SAAS,EACT,MAAM,EACN,SAAS,CACV,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAA2B;IAC7C,OAAO;;;;;;YAMG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS;4BACf,IAAI,CAAC,IAAI;;;;;;CAMpC,CAAC;AACF,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,IAAc;IACzC,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,OAAO,CAC3B,IAA2B;IAE3B,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,YAAE,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAE5D,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAEtD,OAAO;QACL,cAAc,EACZ,iFAAiF;KACpF,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,SAAS,CAAC,KAA8B;IAC5D,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACnD,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,IAAI,YAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,YAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;AACnD,CAAC;AAEM,KAAK,UAAU,MAAM,CAC1B,KAA8B;IAE9B,MAAM,SAAS,GAAG,YAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5C,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,SAAS;QACT,WAAW,EAAE,SAAS;YACpB,CAAC,CAAC,qCAAqC,QAAQ,EAAE,EAAE;YACnD,CAAC,CAAC,oCAAoC;KACzC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Windows Scheduled Task. We register via `schtasks` with
3
+ * ONLOGON trigger + restart-on-failure semantics.
4
+ */
5
+ import { ServiceInstallOptions, ServiceInstallResult, ServiceStatus, ServiceUninstallOptions } from './index';
6
+ export declare function install(opts: ServiceInstallOptions): Promise<ServiceInstallResult>;
7
+ export declare function uninstall(_opts: ServiceUninstallOptions): Promise<void>;
8
+ export declare function status(_opts: ServiceUninstallOptions): Promise<ServiceStatus>;
9
+ //# sourceMappingURL=win32.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"win32.d.ts","sourceRoot":"","sources":["../../../src/agent/service/win32.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACxB,MAAM,SAAS,CAAC;AA8CjB,wBAAsB,OAAO,CAC3B,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAgB/B;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa7E;AAED,wBAAsB,MAAM,CAC1B,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,aAAa,CAAC,CAexB"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ /**
3
+ * Windows Scheduled Task. We register via `schtasks` with
4
+ * ONLOGON trigger + restart-on-failure semantics.
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.install = install;
11
+ exports.uninstall = uninstall;
12
+ exports.status = status;
13
+ const child_process_1 = require("child_process");
14
+ const fs_1 = __importDefault(require("fs"));
15
+ const os_1 = __importDefault(require("os"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const TASK_NAME = 'HooklinkAgent';
18
+ function taskXmlPath(home) {
19
+ return path_1.default.join(home, 'service', 'task.xml');
20
+ }
21
+ function renderTaskXml(opts) {
22
+ return `<?xml version="1.0" encoding="UTF-16"?>
23
+ <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
24
+ <RegistrationInfo>
25
+ <Description>Hooklink local agent</Description>
26
+ </RegistrationInfo>
27
+ <Triggers>
28
+ <LogonTrigger>
29
+ <Enabled>true</Enabled>
30
+ <UserId>${process.env.USERDOMAIN ?? ''}\\${os_1.default.userInfo().username}</UserId>
31
+ </LogonTrigger>
32
+ </Triggers>
33
+ <Principals>
34
+ <Principal id="Author">
35
+ <UserId>${process.env.USERDOMAIN ?? ''}\\${os_1.default.userInfo().username}</UserId>
36
+ <LogonType>InteractiveToken</LogonType>
37
+ <RunLevel>LeastPrivilege</RunLevel>
38
+ </Principal>
39
+ </Principals>
40
+ <Settings>
41
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
42
+ <RestartOnFailure>
43
+ <Interval>PT1M</Interval>
44
+ <Count>5</Count>
45
+ </RestartOnFailure>
46
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
47
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
48
+ </Settings>
49
+ <Actions Context="Author">
50
+ <Exec>
51
+ <Command>${opts.nodePath}</Command>
52
+ <Arguments>"${opts.entryPath}" agent</Arguments>
53
+ </Exec>
54
+ </Actions>
55
+ </Task>
56
+ `;
57
+ }
58
+ async function install(opts) {
59
+ fs_1.default.mkdirSync(path_1.default.join(opts.home, 'service'), { recursive: true });
60
+ const xml = taskXmlPath(opts.home);
61
+ fs_1.default.writeFileSync(xml, renderTaskXml(opts), { encoding: 'utf16le' });
62
+ try {
63
+ (0, child_process_1.execFileSync)('schtasks', ['/Delete', '/F', '/TN', TASK_NAME], {
64
+ stdio: 'ignore',
65
+ });
66
+ }
67
+ catch {
68
+ // Not previously installed.
69
+ }
70
+ (0, child_process_1.execFileSync)('schtasks', ['/Create', '/TN', TASK_NAME, '/XML', xml, '/F'], {
71
+ stdio: 'ignore',
72
+ });
73
+ (0, child_process_1.execFileSync)('schtasks', ['/Run', '/TN', TASK_NAME], { stdio: 'ignore' });
74
+ return {};
75
+ }
76
+ async function uninstall(_opts) {
77
+ try {
78
+ (0, child_process_1.execFileSync)('schtasks', ['/End', '/TN', TASK_NAME], { stdio: 'ignore' });
79
+ }
80
+ catch {
81
+ // ignore
82
+ }
83
+ try {
84
+ (0, child_process_1.execFileSync)('schtasks', ['/Delete', '/F', '/TN', TASK_NAME], {
85
+ stdio: 'ignore',
86
+ });
87
+ }
88
+ catch {
89
+ // ignore
90
+ }
91
+ }
92
+ async function status(_opts) {
93
+ let installed;
94
+ try {
95
+ (0, child_process_1.execFileSync)('schtasks', ['/Query', '/TN', TASK_NAME], { stdio: 'ignore' });
96
+ installed = true;
97
+ }
98
+ catch {
99
+ installed = false;
100
+ }
101
+ return {
102
+ platform: 'win32',
103
+ installed,
104
+ description: installed
105
+ ? `Scheduled Task ${TASK_NAME} is installed`
106
+ : `Scheduled Task ${TASK_NAME} is not installed`,
107
+ };
108
+ }
109
+ //# sourceMappingURL=win32.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"win32.js","sourceRoot":"","sources":["../../../src/agent/service/win32.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * On-disk state for zombie cleanup across agent restarts.
3
+ *
4
+ * Stored at `~/.hooklink/agent.state` (0600) with a minimal schema:
5
+ * [{ tunnel_id, pid, api_key_hash, local_target, started_at }]
6
+ *
7
+ * We hash the API key before writing so a stolen state file doesn't
8
+ * leak credentials. `api_key_hash === null` identifies trial tunnels.
9
+ */
10
+ export interface PersistedTunnel {
11
+ tunnel_id: string;
12
+ pid: number;
13
+ api_key_hash: string | null;
14
+ local_target: string;
15
+ started_at: string;
16
+ owner_id: string | null;
17
+ }
18
+ export declare function hashApiKey(apiKey: string): string;
19
+ export declare function readState(): PersistedTunnel[];
20
+ /**
21
+ * Atomic write via tmpfile + rename. Guarantees readers never see a
22
+ * half-written file even if the agent crashes mid-write.
23
+ */
24
+ export declare function writeState(tunnels: PersistedTunnel[]): void;
25
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/agent/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,SAAS,IAAI,eAAe,EAAE,CA0B7C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAM3D"}