@ozyman42/ozy-cli 0.4.8-linux-x64.0 → 0.4.8

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 (207) hide show
  1. package/bin/ozy +191 -0
  2. package/bin/ozy-signing-agent +191 -0
  3. package/bin/ozy-ssh-keygen +191 -0
  4. package/bin/ozy-virtual-security-key +191 -0
  5. package/dist/commands/git/hosts.js +18 -0
  6. package/dist/commands/git/hosts.js.map +1 -0
  7. package/dist/commands/git/index.js +8 -0
  8. package/dist/commands/git/index.js.map +1 -0
  9. package/dist/commands/git/setup.js +145 -0
  10. package/dist/commands/git/setup.js.map +1 -0
  11. package/dist/commands/index.js +13 -0
  12. package/dist/commands/index.js.map +1 -0
  13. package/dist/commands/npm/index.js +7 -0
  14. package/dist/commands/npm/index.js.map +1 -0
  15. package/dist/commands/npm/setup/git-remote.js +66 -0
  16. package/dist/commands/npm/setup/git-remote.js.map +1 -0
  17. package/dist/commands/npm/setup/index.js +168 -0
  18. package/dist/commands/npm/setup/index.js.map +1 -0
  19. package/dist/commands/npm/setup/npm-auth.js +62 -0
  20. package/dist/commands/npm/setup/npm-auth.js.map +1 -0
  21. package/dist/commands/npm/setup/package-json-validate.js +47 -0
  22. package/dist/commands/npm/setup/package-json-validate.js.map +1 -0
  23. package/dist/commands/npm/setup/package-registry.js +20 -0
  24. package/dist/commands/npm/setup/package-registry.js.map +1 -0
  25. package/dist/commands/npm/setup/setup.test.js +95 -0
  26. package/dist/commands/npm/setup/setup.test.js.map +1 -0
  27. package/dist/commands/npm/setup/trusted-publishing.js +84 -0
  28. package/dist/commands/npm/setup/trusted-publishing.js.map +1 -0
  29. package/dist/commands/npm/setup/workflow.js +19 -0
  30. package/dist/commands/npm/setup/workflow.js.map +1 -0
  31. package/dist/commands/ssh/get-sk-credential.js +104 -0
  32. package/dist/commands/ssh/get-sk-credential.js.map +1 -0
  33. package/dist/commands/ssh/index.js +7 -0
  34. package/dist/commands/ssh/index.js.map +1 -0
  35. package/dist/commands/upgrade.js +199 -0
  36. package/dist/commands/upgrade.js.map +1 -0
  37. package/dist/common/command.js +15 -0
  38. package/dist/common/command.js.map +1 -0
  39. package/dist/common/constants.js +25 -0
  40. package/dist/common/constants.js.map +1 -0
  41. package/dist/common/effective-modules-extensions.js +13 -0
  42. package/dist/common/effective-modules-extensions.js.map +1 -0
  43. package/dist/common/log.js +4 -0
  44. package/dist/common/log.js.map +1 -0
  45. package/dist/common/render-caller-tree.js +20 -0
  46. package/dist/common/render-caller-tree.js.map +1 -0
  47. package/dist/entrypoints/ozy-signing-agent.js +48 -0
  48. package/dist/entrypoints/ozy-signing-agent.js.map +1 -0
  49. package/dist/entrypoints/ozy-ssh-keygen.js +9 -0
  50. package/dist/entrypoints/ozy-ssh-keygen.js.map +1 -0
  51. package/dist/entrypoints/ozy-virtual-security-key.js +18 -0
  52. package/dist/entrypoints/ozy-virtual-security-key.js.map +1 -0
  53. package/dist/entrypoints/ozy.js +3 -0
  54. package/dist/entrypoints/ozy.js.map +1 -0
  55. package/dist/index.js +2 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/internal/thing.js +4 -0
  58. package/dist/internal/thing.js.map +1 -0
  59. package/dist/modules/cli/agent-client/impl.js +109 -0
  60. package/dist/modules/cli/agent-client/impl.js.map +1 -0
  61. package/dist/modules/cli/agent-client/interface.js +11 -0
  62. package/dist/modules/cli/agent-client/interface.js.map +1 -0
  63. package/dist/modules/cli/git/impl.js +124 -0
  64. package/dist/modules/cli/git/impl.js.map +1 -0
  65. package/dist/modules/cli/git/interface.js +3 -0
  66. package/dist/modules/cli/git/interface.js.map +1 -0
  67. package/dist/modules/cli/git/submodule/fix.js +257 -0
  68. package/dist/modules/cli/git/submodule/fix.js.map +1 -0
  69. package/dist/modules/cli/git/submodule/git-state.js +154 -0
  70. package/dist/modules/cli/git/submodule/git-state.js.map +1 -0
  71. package/dist/modules/cli/git/submodule/gitmodules.js +113 -0
  72. package/dist/modules/cli/git/submodule/gitmodules.js.map +1 -0
  73. package/dist/modules/cli/git/submodule/printer.js +232 -0
  74. package/dist/modules/cli/git/submodule/printer.js.map +1 -0
  75. package/dist/modules/cli/git/submodule/resolve-git-dir.js +16 -0
  76. package/dist/modules/cli/git/submodule/resolve-git-dir.js.map +1 -0
  77. package/dist/modules/cli/github/impl.js +137 -0
  78. package/dist/modules/cli/github/impl.js.map +1 -0
  79. package/dist/modules/cli/github/interface.js +2 -0
  80. package/dist/modules/cli/github/interface.js.map +1 -0
  81. package/dist/modules/cli/index.js +9 -0
  82. package/dist/modules/cli/index.js.map +1 -0
  83. package/dist/modules/common/crypto/impl.js +133 -0
  84. package/dist/modules/common/crypto/impl.js.map +1 -0
  85. package/dist/modules/common/crypto/interface.js +2 -0
  86. package/dist/modules/common/crypto/interface.js.map +1 -0
  87. package/dist/modules/common/index.js +10 -0
  88. package/dist/modules/common/index.js.map +1 -0
  89. package/dist/modules/common/kep-map-store/impl.js +42 -0
  90. package/dist/modules/common/kep-map-store/impl.js.map +1 -0
  91. package/dist/modules/common/kep-map-store/interface.js +2 -0
  92. package/dist/modules/common/kep-map-store/interface.js.map +1 -0
  93. package/dist/modules/common/os-platform/caller-info.js +132 -0
  94. package/dist/modules/common/os-platform/caller-info.js.map +1 -0
  95. package/dist/modules/common/os-platform/impl.js +95 -0
  96. package/dist/modules/common/os-platform/impl.js.map +1 -0
  97. package/dist/modules/common/os-platform/interface.js +2 -0
  98. package/dist/modules/common/os-platform/interface.js.map +1 -0
  99. package/dist/modules/common/os-platform/virtual-hid/index.js +12 -0
  100. package/dist/modules/common/os-platform/virtual-hid/index.js.map +1 -0
  101. package/dist/modules/common/os-platform/virtual-hid/linux.js +5 -0
  102. package/dist/modules/common/os-platform/virtual-hid/linux.js.map +1 -0
  103. package/dist/modules/common/os-platform/virtual-hid/mac.js +119 -0
  104. package/dist/modules/common/os-platform/virtual-hid/mac.js.map +1 -0
  105. package/dist/modules/common/os-platform/virtual-hid/windows.js +5 -0
  106. package/dist/modules/common/os-platform/virtual-hid/windows.js.map +1 -0
  107. package/dist/modules/common/ssh-config/impl.js +116 -0
  108. package/dist/modules/common/ssh-config/impl.js.map +1 -0
  109. package/dist/modules/common/ssh-config/interface.js +10 -0
  110. package/dist/modules/common/ssh-config/interface.js.map +1 -0
  111. package/dist/modules/ssh-agent/index.js +8 -0
  112. package/dist/modules/ssh-agent/index.js.map +1 -0
  113. package/dist/modules/ssh-agent/session/impl.js +265 -0
  114. package/dist/modules/ssh-agent/session/impl.js.map +1 -0
  115. package/dist/modules/ssh-agent/session/interface-rpc.js +20 -0
  116. package/dist/modules/ssh-agent/session/interface-rpc.js.map +1 -0
  117. package/dist/modules/ssh-agent/session/interface.js +32 -0
  118. package/dist/modules/ssh-agent/session/interface.js.map +1 -0
  119. package/dist/modules/ssh-agent/session/passkey-prf-page.js +204 -0
  120. package/dist/modules/ssh-agent/session/passkey-prf-page.js.map +1 -0
  121. package/dist/modules/ssh-agent/session/prf-flow.js +103 -0
  122. package/dist/modules/ssh-agent/session/prf-flow.js.map +1 -0
  123. package/dist/modules/ssh-agent/ssh-agent/impl.js +117 -0
  124. package/dist/modules/ssh-agent/ssh-agent/impl.js.map +1 -0
  125. package/dist/modules/ssh-agent/ssh-agent/interface.js +2 -0
  126. package/dist/modules/ssh-agent/ssh-agent/interface.js.map +1 -0
  127. package/dist/scripts/build.js +410 -0
  128. package/dist/scripts/build.js.map +1 -0
  129. package/dist/scripts/check-npm-version.js +8 -0
  130. package/dist/scripts/check-npm-version.js.map +1 -0
  131. package/dist/scripts/kill-existing-agent.js +21 -0
  132. package/dist/scripts/kill-existing-agent.js.map +1 -0
  133. package/dist/scripts/publish.js +46 -0
  134. package/dist/scripts/publish.js.map +1 -0
  135. package/package.json +52 -11
  136. package/src/commands/git/hosts.ts +20 -0
  137. package/src/commands/git/index.ts +9 -0
  138. package/src/commands/git/setup.ts +182 -0
  139. package/src/commands/index.ts +15 -0
  140. package/src/commands/npm/index.ts +8 -0
  141. package/src/commands/npm/setup/git-remote.ts +78 -0
  142. package/src/commands/npm/setup/index.ts +189 -0
  143. package/src/commands/npm/setup/npm-auth.ts +58 -0
  144. package/src/commands/npm/setup/package-json-validate.ts +68 -0
  145. package/src/commands/npm/setup/package-registry.ts +24 -0
  146. package/src/commands/npm/setup/publish-workflow.yml +35 -0
  147. package/src/commands/npm/setup/setup.test.ts +117 -0
  148. package/src/commands/npm/setup/trusted-publishing.ts +106 -0
  149. package/src/commands/npm/setup/workflow.ts +20 -0
  150. package/src/commands/ssh/get-sk-credential.ts +110 -0
  151. package/src/commands/ssh/index.ts +8 -0
  152. package/src/commands/upgrade.ts +220 -0
  153. package/src/common/command.ts +16 -0
  154. package/src/common/constants.ts +26 -0
  155. package/src/common/effective-modules-extensions.ts +24 -0
  156. package/src/common/log.ts +3 -0
  157. package/src/common/render-caller-tree.ts +22 -0
  158. package/src/entrypoints/ozy-signing-agent.ts +48 -0
  159. package/src/entrypoints/ozy-ssh-keygen.ts +10 -0
  160. package/src/entrypoints/ozy-virtual-security-key.ts +21 -0
  161. package/src/entrypoints/ozy.ts +2 -0
  162. package/src/index.ts +1 -0
  163. package/src/internal/thing.ts +3 -0
  164. package/src/modules/cli/agent-client/impl.ts +152 -0
  165. package/src/modules/cli/agent-client/interface.ts +17 -0
  166. package/src/modules/cli/git/impl.ts +133 -0
  167. package/src/modules/cli/git/interface.ts +23 -0
  168. package/src/modules/cli/git/submodule/fix.ts +298 -0
  169. package/src/modules/cli/git/submodule/git-state.ts +217 -0
  170. package/src/modules/cli/git/submodule/gitmodules.ts +126 -0
  171. package/src/modules/cli/git/submodule/printer.ts +256 -0
  172. package/src/modules/cli/git/submodule/resolve-git-dir.ts +14 -0
  173. package/src/modules/cli/github/impl.ts +169 -0
  174. package/src/modules/cli/github/interface.ts +29 -0
  175. package/src/modules/cli/index.ts +16 -0
  176. package/src/modules/common/crypto/impl.ts +173 -0
  177. package/src/modules/common/crypto/interface.ts +20 -0
  178. package/src/modules/common/index.ts +19 -0
  179. package/src/modules/common/kep-map-store/impl.ts +47 -0
  180. package/src/modules/common/kep-map-store/interface.ts +9 -0
  181. package/src/modules/common/os-platform/caller-info.ts +152 -0
  182. package/src/modules/common/os-platform/impl.ts +91 -0
  183. package/src/modules/common/os-platform/interface.ts +16 -0
  184. package/src/modules/common/os-platform/virtual-hid/index.ts +12 -0
  185. package/src/modules/common/os-platform/virtual-hid/linux.ts +7 -0
  186. package/src/modules/common/os-platform/virtual-hid/mac.ts +150 -0
  187. package/src/modules/common/os-platform/virtual-hid/windows.ts +7 -0
  188. package/src/modules/common/ssh-config/impl.ts +130 -0
  189. package/src/modules/common/ssh-config/interface.ts +33 -0
  190. package/src/modules/ssh-agent/index.ts +13 -0
  191. package/src/modules/ssh-agent/session/agent-notes.md +210 -0
  192. package/src/modules/ssh-agent/session/design.md +2 -0
  193. package/src/modules/ssh-agent/session/html-refactor.md +23 -0
  194. package/src/modules/ssh-agent/session/impl.ts +328 -0
  195. package/src/modules/ssh-agent/session/interface-rpc.ts +24 -0
  196. package/src/modules/ssh-agent/session/interface.ts +62 -0
  197. package/src/modules/ssh-agent/session/passkey-prf-page.ts +224 -0
  198. package/src/modules/ssh-agent/session/prf-flow.ts +152 -0
  199. package/src/modules/ssh-agent/ssh-agent/impl.ts +136 -0
  200. package/src/modules/ssh-agent/ssh-agent/interface.ts +9 -0
  201. package/src/scripts/build.ts +504 -0
  202. package/src/scripts/check-npm-version.ts +7 -0
  203. package/src/scripts/command-launcher.js.ejs +168 -0
  204. package/src/scripts/kill-existing-agent.ts +22 -0
  205. package/src/scripts/publish.ts +47 -0
  206. package/src/scripts/windows-bin-shims.md +1104 -0
  207. package/multi-call-binary +0 -0
package/bin/ozy ADDED
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
+ import { spawnSync } from "node:child_process";
4
+ import {
5
+ chmodSync,
6
+ copyFileSync,
7
+ existsSync,
8
+ linkSync,
9
+ mkdirSync,
10
+ readFileSync,
11
+ renameSync,
12
+ rmSync,
13
+ writeFileSync,
14
+ } from "node:fs";
15
+ import { basename, dirname, join } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+
18
+ const PLATFORM_MAP = {
19
+ "darwin-arm64": "darwin-arm64",
20
+ "darwin-x64": "darwin-x64",
21
+ "linux-arm64": "linux-arm64",
22
+ "linux-x64": "linux-x64",
23
+ "win32-x64": "windows-x64"
24
+ };
25
+ const PLATFORM_PACKAGES = {
26
+ "darwin-arm64": "@ozyman42/ozy-cli-darwin-arm64",
27
+ "darwin-x64": "@ozyman42/ozy-cli-darwin-x64",
28
+ "linux-arm64": "@ozyman42/ozy-cli-linux-arm64",
29
+ "linux-x64": "@ozyman42/ozy-cli-linux-x64",
30
+ "windows-x64": "@ozyman42/ozy-cli-windows-x64"
31
+ };
32
+ const PLATFORM_BINARIES = {
33
+ "darwin-arm64": "multi-call-binary",
34
+ "darwin-x64": "multi-call-binary",
35
+ "linux-arm64": "multi-call-binary",
36
+ "linux-x64": "multi-call-binary",
37
+ "windows-x64": "multi-call-binary.exe"
38
+ };
39
+ const COMMANDS = [
40
+ "ozy",
41
+ "ozy-signing-agent",
42
+ "ozy-ssh-keygen",
43
+ "ozy-virtual-security-key"
44
+ ];
45
+ const WINDOWS_EXECUTABLE_SUFFIX = ".exe";
46
+ const INSTALLED_JSON = "installed.json";
47
+
48
+ const require = createRequire(import.meta.url);
49
+ const launcherPath = fileURLToPath(import.meta.url);
50
+ const launcherDir = dirname(launcherPath);
51
+ const commandName = basename(launcherPath);
52
+
53
+ function fail(message) {
54
+ console.error(message);
55
+ process.exit(1);
56
+ }
57
+
58
+ function currentPlatformKey() {
59
+ const platformKey = PLATFORM_MAP[`${process.platform}-${process.arch}`];
60
+ if (!platformKey) {
61
+ fail(`Unsupported platform: ${process.platform}-${process.arch}`);
62
+ }
63
+ return platformKey;
64
+ }
65
+
66
+ function currentPlatformPackageName() {
67
+ const platformKey = currentPlatformKey();
68
+ const packageName = PLATFORM_PACKAGES[platformKey];
69
+ if (!packageName) {
70
+ fail(`No platform package is configured for ${platformKey}`);
71
+ }
72
+ return packageName;
73
+ }
74
+
75
+ /**
76
+ * When a Jive library contains any number of CLIs (entrypoints or agents), then the base package
77
+ * will have an optional dependency for each possible architecture, with those platform-specific
78
+ * packages containing a platform build of the CLI.
79
+ * @returns the path to the platform binary and the exact version of the platform package.
80
+ */
81
+ function currentPlatformPackage() {
82
+ const platformKey = currentPlatformKey();
83
+ const binaryFile = PLATFORM_BINARIES[platformKey];
84
+ if (!binaryFile) {
85
+ fail(`No platform binary is configured for ${platformKey}`);
86
+ }
87
+
88
+ const packageName = currentPlatformPackageName();
89
+ try {
90
+ const packageJsonPath = require.resolve(`${packageName}/package.json`);
91
+ const packageDir = dirname(packageJsonPath);
92
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
93
+ return {
94
+ binaryPath: join(packageDir, binaryFile),
95
+ version: packageJson.version,
96
+ };
97
+ } catch (error) {
98
+ fail(`Could not resolve optional platform package ${packageName}. Reinstall dependencies for ${process.platform}-${process.arch}.`);
99
+ }
100
+ }
101
+
102
+ function targetPathFor(command) {
103
+ const suffix = process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : "";
104
+ return join(launcherDir, `${command}${suffix}`);
105
+ }
106
+
107
+ function installedJsonPath() {
108
+ return join(launcherDir, INSTALLED_JSON);
109
+ }
110
+
111
+ function windowsTargetsAreCurrent(version) {
112
+ if (process.platform !== "win32") return false;
113
+ if (!COMMANDS.every((command) => existsSync(targetPathFor(command)))) return false;
114
+
115
+ try {
116
+ const installed = JSON.parse(readFileSync(installedJsonPath(), "utf-8"));
117
+ return installed.version === version;
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ function linkOrCopyFirstExecutable(sourcePath, targetPath) {
124
+ mkdirSync(dirname(targetPath), { recursive: true });
125
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp${process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : ""}`;
126
+ rmSync(tempPath, { force: true });
127
+
128
+ try {
129
+ try {
130
+ linkSync(sourcePath, tempPath);
131
+ } catch {
132
+ copyFileSync(sourcePath, tempPath);
133
+ }
134
+
135
+ chmodSync(tempPath, 0o755);
136
+ rmSync(targetPath, { force: true });
137
+ renameSync(tempPath, targetPath);
138
+ } finally {
139
+ rmSync(tempPath, { force: true });
140
+ }
141
+ }
142
+
143
+ function hardLinkCommandTarget(sourcePath, targetPath) {
144
+ if (sourcePath === targetPath) return;
145
+
146
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp${process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : ""}`;
147
+ rmSync(tempPath, { force: true });
148
+
149
+ try {
150
+ linkSync(sourcePath, tempPath);
151
+ chmodSync(tempPath, 0o755);
152
+ rmSync(targetPath, { force: true });
153
+ renameSync(tempPath, targetPath);
154
+ } finally {
155
+ rmSync(tempPath, { force: true });
156
+ }
157
+ }
158
+
159
+ function repairCommandTargets() {
160
+ const platformPackage = currentPlatformPackage();
161
+
162
+ if (windowsTargetsAreCurrent(platformPackage.version)) {
163
+ return targetPathFor(commandName);
164
+ }
165
+
166
+ const firstTargetPath = targetPathFor(COMMANDS[0]);
167
+ linkOrCopyFirstExecutable(platformPackage.binaryPath, firstTargetPath);
168
+
169
+ for (const command of COMMANDS.slice(1)) {
170
+ hardLinkCommandTarget(firstTargetPath, targetPathFor(command));
171
+ }
172
+
173
+ if (process.platform === "win32") {
174
+ writeFileSync(installedJsonPath(), `${JSON.stringify({ version: platformPackage.version }, null, 2)}\n`);
175
+ }
176
+
177
+ return targetPathFor(commandName);
178
+ }
179
+
180
+ function runExecutable(executablePath) {
181
+ const result = spawnSync(executablePath, process.argv.slice(2), { stdio: "inherit" });
182
+
183
+ if (result.error) {
184
+ fail(result.error.message);
185
+ }
186
+ if (result.status !== 0) {
187
+ process.exit(result.status ?? 1);
188
+ }
189
+ }
190
+
191
+ runExecutable(repairCommandTargets());
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
+ import { spawnSync } from "node:child_process";
4
+ import {
5
+ chmodSync,
6
+ copyFileSync,
7
+ existsSync,
8
+ linkSync,
9
+ mkdirSync,
10
+ readFileSync,
11
+ renameSync,
12
+ rmSync,
13
+ writeFileSync,
14
+ } from "node:fs";
15
+ import { basename, dirname, join } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+
18
+ const PLATFORM_MAP = {
19
+ "darwin-arm64": "darwin-arm64",
20
+ "darwin-x64": "darwin-x64",
21
+ "linux-arm64": "linux-arm64",
22
+ "linux-x64": "linux-x64",
23
+ "win32-x64": "windows-x64"
24
+ };
25
+ const PLATFORM_PACKAGES = {
26
+ "darwin-arm64": "@ozyman42/ozy-cli-darwin-arm64",
27
+ "darwin-x64": "@ozyman42/ozy-cli-darwin-x64",
28
+ "linux-arm64": "@ozyman42/ozy-cli-linux-arm64",
29
+ "linux-x64": "@ozyman42/ozy-cli-linux-x64",
30
+ "windows-x64": "@ozyman42/ozy-cli-windows-x64"
31
+ };
32
+ const PLATFORM_BINARIES = {
33
+ "darwin-arm64": "multi-call-binary",
34
+ "darwin-x64": "multi-call-binary",
35
+ "linux-arm64": "multi-call-binary",
36
+ "linux-x64": "multi-call-binary",
37
+ "windows-x64": "multi-call-binary.exe"
38
+ };
39
+ const COMMANDS = [
40
+ "ozy",
41
+ "ozy-signing-agent",
42
+ "ozy-ssh-keygen",
43
+ "ozy-virtual-security-key"
44
+ ];
45
+ const WINDOWS_EXECUTABLE_SUFFIX = ".exe";
46
+ const INSTALLED_JSON = "installed.json";
47
+
48
+ const require = createRequire(import.meta.url);
49
+ const launcherPath = fileURLToPath(import.meta.url);
50
+ const launcherDir = dirname(launcherPath);
51
+ const commandName = basename(launcherPath);
52
+
53
+ function fail(message) {
54
+ console.error(message);
55
+ process.exit(1);
56
+ }
57
+
58
+ function currentPlatformKey() {
59
+ const platformKey = PLATFORM_MAP[`${process.platform}-${process.arch}`];
60
+ if (!platformKey) {
61
+ fail(`Unsupported platform: ${process.platform}-${process.arch}`);
62
+ }
63
+ return platformKey;
64
+ }
65
+
66
+ function currentPlatformPackageName() {
67
+ const platformKey = currentPlatformKey();
68
+ const packageName = PLATFORM_PACKAGES[platformKey];
69
+ if (!packageName) {
70
+ fail(`No platform package is configured for ${platformKey}`);
71
+ }
72
+ return packageName;
73
+ }
74
+
75
+ /**
76
+ * When a Jive library contains any number of CLIs (entrypoints or agents), then the base package
77
+ * will have an optional dependency for each possible architecture, with those platform-specific
78
+ * packages containing a platform build of the CLI.
79
+ * @returns the path to the platform binary and the exact version of the platform package.
80
+ */
81
+ function currentPlatformPackage() {
82
+ const platformKey = currentPlatformKey();
83
+ const binaryFile = PLATFORM_BINARIES[platformKey];
84
+ if (!binaryFile) {
85
+ fail(`No platform binary is configured for ${platformKey}`);
86
+ }
87
+
88
+ const packageName = currentPlatformPackageName();
89
+ try {
90
+ const packageJsonPath = require.resolve(`${packageName}/package.json`);
91
+ const packageDir = dirname(packageJsonPath);
92
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
93
+ return {
94
+ binaryPath: join(packageDir, binaryFile),
95
+ version: packageJson.version,
96
+ };
97
+ } catch (error) {
98
+ fail(`Could not resolve optional platform package ${packageName}. Reinstall dependencies for ${process.platform}-${process.arch}.`);
99
+ }
100
+ }
101
+
102
+ function targetPathFor(command) {
103
+ const suffix = process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : "";
104
+ return join(launcherDir, `${command}${suffix}`);
105
+ }
106
+
107
+ function installedJsonPath() {
108
+ return join(launcherDir, INSTALLED_JSON);
109
+ }
110
+
111
+ function windowsTargetsAreCurrent(version) {
112
+ if (process.platform !== "win32") return false;
113
+ if (!COMMANDS.every((command) => existsSync(targetPathFor(command)))) return false;
114
+
115
+ try {
116
+ const installed = JSON.parse(readFileSync(installedJsonPath(), "utf-8"));
117
+ return installed.version === version;
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ function linkOrCopyFirstExecutable(sourcePath, targetPath) {
124
+ mkdirSync(dirname(targetPath), { recursive: true });
125
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp${process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : ""}`;
126
+ rmSync(tempPath, { force: true });
127
+
128
+ try {
129
+ try {
130
+ linkSync(sourcePath, tempPath);
131
+ } catch {
132
+ copyFileSync(sourcePath, tempPath);
133
+ }
134
+
135
+ chmodSync(tempPath, 0o755);
136
+ rmSync(targetPath, { force: true });
137
+ renameSync(tempPath, targetPath);
138
+ } finally {
139
+ rmSync(tempPath, { force: true });
140
+ }
141
+ }
142
+
143
+ function hardLinkCommandTarget(sourcePath, targetPath) {
144
+ if (sourcePath === targetPath) return;
145
+
146
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp${process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : ""}`;
147
+ rmSync(tempPath, { force: true });
148
+
149
+ try {
150
+ linkSync(sourcePath, tempPath);
151
+ chmodSync(tempPath, 0o755);
152
+ rmSync(targetPath, { force: true });
153
+ renameSync(tempPath, targetPath);
154
+ } finally {
155
+ rmSync(tempPath, { force: true });
156
+ }
157
+ }
158
+
159
+ function repairCommandTargets() {
160
+ const platformPackage = currentPlatformPackage();
161
+
162
+ if (windowsTargetsAreCurrent(platformPackage.version)) {
163
+ return targetPathFor(commandName);
164
+ }
165
+
166
+ const firstTargetPath = targetPathFor(COMMANDS[0]);
167
+ linkOrCopyFirstExecutable(platformPackage.binaryPath, firstTargetPath);
168
+
169
+ for (const command of COMMANDS.slice(1)) {
170
+ hardLinkCommandTarget(firstTargetPath, targetPathFor(command));
171
+ }
172
+
173
+ if (process.platform === "win32") {
174
+ writeFileSync(installedJsonPath(), `${JSON.stringify({ version: platformPackage.version }, null, 2)}\n`);
175
+ }
176
+
177
+ return targetPathFor(commandName);
178
+ }
179
+
180
+ function runExecutable(executablePath) {
181
+ const result = spawnSync(executablePath, process.argv.slice(2), { stdio: "inherit" });
182
+
183
+ if (result.error) {
184
+ fail(result.error.message);
185
+ }
186
+ if (result.status !== 0) {
187
+ process.exit(result.status ?? 1);
188
+ }
189
+ }
190
+
191
+ runExecutable(repairCommandTargets());
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
+ import { spawnSync } from "node:child_process";
4
+ import {
5
+ chmodSync,
6
+ copyFileSync,
7
+ existsSync,
8
+ linkSync,
9
+ mkdirSync,
10
+ readFileSync,
11
+ renameSync,
12
+ rmSync,
13
+ writeFileSync,
14
+ } from "node:fs";
15
+ import { basename, dirname, join } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+
18
+ const PLATFORM_MAP = {
19
+ "darwin-arm64": "darwin-arm64",
20
+ "darwin-x64": "darwin-x64",
21
+ "linux-arm64": "linux-arm64",
22
+ "linux-x64": "linux-x64",
23
+ "win32-x64": "windows-x64"
24
+ };
25
+ const PLATFORM_PACKAGES = {
26
+ "darwin-arm64": "@ozyman42/ozy-cli-darwin-arm64",
27
+ "darwin-x64": "@ozyman42/ozy-cli-darwin-x64",
28
+ "linux-arm64": "@ozyman42/ozy-cli-linux-arm64",
29
+ "linux-x64": "@ozyman42/ozy-cli-linux-x64",
30
+ "windows-x64": "@ozyman42/ozy-cli-windows-x64"
31
+ };
32
+ const PLATFORM_BINARIES = {
33
+ "darwin-arm64": "multi-call-binary",
34
+ "darwin-x64": "multi-call-binary",
35
+ "linux-arm64": "multi-call-binary",
36
+ "linux-x64": "multi-call-binary",
37
+ "windows-x64": "multi-call-binary.exe"
38
+ };
39
+ const COMMANDS = [
40
+ "ozy",
41
+ "ozy-signing-agent",
42
+ "ozy-ssh-keygen",
43
+ "ozy-virtual-security-key"
44
+ ];
45
+ const WINDOWS_EXECUTABLE_SUFFIX = ".exe";
46
+ const INSTALLED_JSON = "installed.json";
47
+
48
+ const require = createRequire(import.meta.url);
49
+ const launcherPath = fileURLToPath(import.meta.url);
50
+ const launcherDir = dirname(launcherPath);
51
+ const commandName = basename(launcherPath);
52
+
53
+ function fail(message) {
54
+ console.error(message);
55
+ process.exit(1);
56
+ }
57
+
58
+ function currentPlatformKey() {
59
+ const platformKey = PLATFORM_MAP[`${process.platform}-${process.arch}`];
60
+ if (!platformKey) {
61
+ fail(`Unsupported platform: ${process.platform}-${process.arch}`);
62
+ }
63
+ return platformKey;
64
+ }
65
+
66
+ function currentPlatformPackageName() {
67
+ const platformKey = currentPlatformKey();
68
+ const packageName = PLATFORM_PACKAGES[platformKey];
69
+ if (!packageName) {
70
+ fail(`No platform package is configured for ${platformKey}`);
71
+ }
72
+ return packageName;
73
+ }
74
+
75
+ /**
76
+ * When a Jive library contains any number of CLIs (entrypoints or agents), then the base package
77
+ * will have an optional dependency for each possible architecture, with those platform-specific
78
+ * packages containing a platform build of the CLI.
79
+ * @returns the path to the platform binary and the exact version of the platform package.
80
+ */
81
+ function currentPlatformPackage() {
82
+ const platformKey = currentPlatformKey();
83
+ const binaryFile = PLATFORM_BINARIES[platformKey];
84
+ if (!binaryFile) {
85
+ fail(`No platform binary is configured for ${platformKey}`);
86
+ }
87
+
88
+ const packageName = currentPlatformPackageName();
89
+ try {
90
+ const packageJsonPath = require.resolve(`${packageName}/package.json`);
91
+ const packageDir = dirname(packageJsonPath);
92
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
93
+ return {
94
+ binaryPath: join(packageDir, binaryFile),
95
+ version: packageJson.version,
96
+ };
97
+ } catch (error) {
98
+ fail(`Could not resolve optional platform package ${packageName}. Reinstall dependencies for ${process.platform}-${process.arch}.`);
99
+ }
100
+ }
101
+
102
+ function targetPathFor(command) {
103
+ const suffix = process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : "";
104
+ return join(launcherDir, `${command}${suffix}`);
105
+ }
106
+
107
+ function installedJsonPath() {
108
+ return join(launcherDir, INSTALLED_JSON);
109
+ }
110
+
111
+ function windowsTargetsAreCurrent(version) {
112
+ if (process.platform !== "win32") return false;
113
+ if (!COMMANDS.every((command) => existsSync(targetPathFor(command)))) return false;
114
+
115
+ try {
116
+ const installed = JSON.parse(readFileSync(installedJsonPath(), "utf-8"));
117
+ return installed.version === version;
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ function linkOrCopyFirstExecutable(sourcePath, targetPath) {
124
+ mkdirSync(dirname(targetPath), { recursive: true });
125
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp${process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : ""}`;
126
+ rmSync(tempPath, { force: true });
127
+
128
+ try {
129
+ try {
130
+ linkSync(sourcePath, tempPath);
131
+ } catch {
132
+ copyFileSync(sourcePath, tempPath);
133
+ }
134
+
135
+ chmodSync(tempPath, 0o755);
136
+ rmSync(targetPath, { force: true });
137
+ renameSync(tempPath, targetPath);
138
+ } finally {
139
+ rmSync(tempPath, { force: true });
140
+ }
141
+ }
142
+
143
+ function hardLinkCommandTarget(sourcePath, targetPath) {
144
+ if (sourcePath === targetPath) return;
145
+
146
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp${process.platform === "win32" ? WINDOWS_EXECUTABLE_SUFFIX : ""}`;
147
+ rmSync(tempPath, { force: true });
148
+
149
+ try {
150
+ linkSync(sourcePath, tempPath);
151
+ chmodSync(tempPath, 0o755);
152
+ rmSync(targetPath, { force: true });
153
+ renameSync(tempPath, targetPath);
154
+ } finally {
155
+ rmSync(tempPath, { force: true });
156
+ }
157
+ }
158
+
159
+ function repairCommandTargets() {
160
+ const platformPackage = currentPlatformPackage();
161
+
162
+ if (windowsTargetsAreCurrent(platformPackage.version)) {
163
+ return targetPathFor(commandName);
164
+ }
165
+
166
+ const firstTargetPath = targetPathFor(COMMANDS[0]);
167
+ linkOrCopyFirstExecutable(platformPackage.binaryPath, firstTargetPath);
168
+
169
+ for (const command of COMMANDS.slice(1)) {
170
+ hardLinkCommandTarget(firstTargetPath, targetPathFor(command));
171
+ }
172
+
173
+ if (process.platform === "win32") {
174
+ writeFileSync(installedJsonPath(), `${JSON.stringify({ version: platformPackage.version }, null, 2)}\n`);
175
+ }
176
+
177
+ return targetPathFor(commandName);
178
+ }
179
+
180
+ function runExecutable(executablePath) {
181
+ const result = spawnSync(executablePath, process.argv.slice(2), { stdio: "inherit" });
182
+
183
+ if (result.error) {
184
+ fail(result.error.message);
185
+ }
186
+ if (result.status !== 0) {
187
+ process.exit(result.status ?? 1);
188
+ }
189
+ }
190
+
191
+ runExecutable(repairCommandTargets());