@synsci/openscience 1.2.0

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.
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ const childProcess = require("child_process")
4
+ const fs = require("fs")
5
+ const path = require("path")
6
+ const os = require("os")
7
+
8
+ function run(target) {
9
+ // Clean up files that confuse Bun compiled binaries.
10
+ // Install dir stays as ~/.openscience/ until the path-migration follow-up PR.
11
+ const openscienceDir = path.join(os.homedir(), ".openscience")
12
+ for (const poison of ["package.json", ".gitignore", "bun.lockb", "bunfig.toml"]) {
13
+ try { fs.unlinkSync(path.join(openscienceDir, poison)) } catch {}
14
+ }
15
+ try { fs.rmSync(path.join(openscienceDir, "node_modules"), { recursive: true }) } catch {}
16
+ // Clear macOS extended attributes that cause Bun binaries to hang
17
+ if (os.platform() === "darwin") {
18
+ try { childProcess.spawnSync("xattr", ["-rc", openscienceDir], { stdio: "ignore" }) } catch {}
19
+ }
20
+
21
+ const result = childProcess.spawnSync(target, process.argv.slice(2), {
22
+ stdio: "inherit",
23
+ })
24
+ if (result.error) {
25
+ console.error(result.error.message)
26
+ process.exit(1)
27
+ }
28
+ const code = typeof result.status === "number" ? result.status : 0
29
+ process.exit(code)
30
+ }
31
+
32
+ // Helper: check if a path points to a real binary (not this wrapper script)
33
+ function isBinary(p) {
34
+ try {
35
+ if (!fs.existsSync(p)) return false
36
+ const real = fs.realpathSync(p)
37
+ // Skip if it resolves to this script (self-reference via symlink)
38
+ if (real === fs.realpathSync(__filename)) return false
39
+ // Skip if it's a .js file (another wrapper)
40
+ if (real.endsWith(".js")) return false
41
+ return true
42
+ } catch {
43
+ return false
44
+ }
45
+ }
46
+
47
+ // 1. Check OPENSCIENCE_BIN_PATH env var
48
+ const envPath = process.env.OPENSCIENCE_BIN_PATH
49
+ if (envPath && isBinary(envPath)) {
50
+ run(envPath)
51
+ }
52
+
53
+ const binary = os.platform() === "win32" ? "openscience.exe" : "openscience"
54
+ const scriptPath = fs.realpathSync(__filename)
55
+ const scriptDir = path.dirname(scriptPath)
56
+
57
+ const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" }
58
+ const archMap = { x64: "x64", arm64: "arm64", arm: "arm" }
59
+ const platform = platformMap[os.platform()] || os.platform()
60
+ const arch = archMap[os.arch()] || os.arch()
61
+ const base = "openscience-" + platform + "-" + arch
62
+ const scopedBase = "cli-" + platform + "-" + arch
63
+
64
+ // 2. Search this install's node_modules for the matching platform package.
65
+ // This must come before ~/.openscience or Homebrew fallbacks; otherwise an npm
66
+ // install can accidentally launch an older globally-installed binary.
67
+ let current = scriptDir
68
+ while (true) {
69
+ const modules = path.join(current, "node_modules")
70
+ if (fs.existsSync(modules)) {
71
+ try {
72
+ const entries = fs.readdirSync(modules)
73
+ for (const entry of entries) {
74
+ if (entry.startsWith(base)) {
75
+ const candidate = path.join(modules, entry, "bin", binary)
76
+ if (isBinary(candidate)) run(candidate)
77
+ }
78
+ }
79
+ // Check scoped packages (@synsci/openscience-darwin-arm64)
80
+ const scoped = path.join(modules, "@openscience")
81
+ if (fs.existsSync(scoped)) {
82
+ const scopedEntries = fs.readdirSync(scoped)
83
+ for (const entry of scopedEntries) {
84
+ if (entry.startsWith(scopedBase)) {
85
+ const candidate = path.join(scoped, entry, "bin", binary)
86
+ if (isBinary(candidate)) run(candidate)
87
+ }
88
+ }
89
+ }
90
+ } catch {}
91
+ }
92
+ const parent = path.dirname(current)
93
+ if (parent === current) break
94
+ current = parent
95
+ }
96
+
97
+ // 3. Check ~/.openscience/bin (curl installer fallback; dir renamed later)
98
+ const homeBin = path.join(os.homedir(), ".openscience", "bin", binary)
99
+ if (isBinary(homeBin)) {
100
+ run(homeBin)
101
+ }
102
+
103
+ // 4. Check /opt/homebrew/bin (macOS)
104
+ if (os.platform() === "darwin" && isBinary("/opt/homebrew/bin/openscience")) {
105
+ run("/opt/homebrew/bin/openscience")
106
+ }
107
+
108
+ // 5. Check /usr/local/bin
109
+ if (isBinary("/usr/local/bin/openscience")) {
110
+ run("/usr/local/bin/openscience")
111
+ }
112
+
113
+ console.error("openscience binary not found.")
114
+ console.error("Install with: curl -fsSL https://syntheticsciences.ai/install | bash")
115
+ console.error("Or set OPENSCIENCE_BIN_PATH environment variable.")
116
+ process.exit(1)
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ const childProcess = require("child_process")
4
+ const fs = require("fs")
5
+ const path = require("path")
6
+ const os = require("os")
7
+
8
+ function run(target) {
9
+ // Clean up files that confuse Bun compiled binaries.
10
+ // Install dir stays as ~/.openscience/ until the path-migration follow-up PR.
11
+ const openscienceDir = path.join(os.homedir(), ".openscience")
12
+ for (const poison of ["package.json", ".gitignore", "bun.lockb", "bunfig.toml"]) {
13
+ try { fs.unlinkSync(path.join(openscienceDir, poison)) } catch {}
14
+ }
15
+ try { fs.rmSync(path.join(openscienceDir, "node_modules"), { recursive: true }) } catch {}
16
+ // Clear macOS extended attributes that cause Bun binaries to hang
17
+ if (os.platform() === "darwin") {
18
+ try { childProcess.spawnSync("xattr", ["-rc", openscienceDir], { stdio: "ignore" }) } catch {}
19
+ }
20
+
21
+ const result = childProcess.spawnSync(target, process.argv.slice(2), {
22
+ stdio: "inherit",
23
+ })
24
+ if (result.error) {
25
+ console.error(result.error.message)
26
+ process.exit(1)
27
+ }
28
+ const code = typeof result.status === "number" ? result.status : 0
29
+ process.exit(code)
30
+ }
31
+
32
+ // Helper: check if a path points to a real binary (not this wrapper script)
33
+ function isBinary(p) {
34
+ try {
35
+ if (!fs.existsSync(p)) return false
36
+ const real = fs.realpathSync(p)
37
+ // Skip if it resolves to this script (self-reference via symlink)
38
+ if (real === fs.realpathSync(__filename)) return false
39
+ // Skip if it's a .js file (another wrapper)
40
+ if (real.endsWith(".js")) return false
41
+ return true
42
+ } catch {
43
+ return false
44
+ }
45
+ }
46
+
47
+ // 1. Check OPENSCIENCE_BIN_PATH env var
48
+ const envPath = process.env.OPENSCIENCE_BIN_PATH
49
+ if (envPath && isBinary(envPath)) {
50
+ run(envPath)
51
+ }
52
+
53
+ const binary = os.platform() === "win32" ? "openscience.exe" : "openscience"
54
+ const scriptPath = fs.realpathSync(__filename)
55
+ const scriptDir = path.dirname(scriptPath)
56
+
57
+ const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" }
58
+ const archMap = { x64: "x64", arm64: "arm64", arm: "arm" }
59
+ const platform = platformMap[os.platform()] || os.platform()
60
+ const arch = archMap[os.arch()] || os.arch()
61
+ const base = "openscience-" + platform + "-" + arch
62
+ const scopedBase = "cli-" + platform + "-" + arch
63
+
64
+ // 2. Search this install's node_modules for the matching platform package.
65
+ // This must come before ~/.openscience or Homebrew fallbacks; otherwise an npm
66
+ // install can accidentally launch an older globally-installed binary.
67
+ let current = scriptDir
68
+ while (true) {
69
+ const modules = path.join(current, "node_modules")
70
+ if (fs.existsSync(modules)) {
71
+ try {
72
+ const entries = fs.readdirSync(modules)
73
+ for (const entry of entries) {
74
+ if (entry.startsWith(base)) {
75
+ const candidate = path.join(modules, entry, "bin", binary)
76
+ if (isBinary(candidate)) run(candidate)
77
+ }
78
+ }
79
+ // Check scoped packages (@synsci/openscience-darwin-arm64)
80
+ const scoped = path.join(modules, "@openscience")
81
+ if (fs.existsSync(scoped)) {
82
+ const scopedEntries = fs.readdirSync(scoped)
83
+ for (const entry of scopedEntries) {
84
+ if (entry.startsWith(scopedBase)) {
85
+ const candidate = path.join(scoped, entry, "bin", binary)
86
+ if (isBinary(candidate)) run(candidate)
87
+ }
88
+ }
89
+ }
90
+ } catch {}
91
+ }
92
+ const parent = path.dirname(current)
93
+ if (parent === current) break
94
+ current = parent
95
+ }
96
+
97
+ // 3. Check ~/.openscience/bin (curl installer fallback; dir renamed later)
98
+ const homeBin = path.join(os.homedir(), ".openscience", "bin", binary)
99
+ if (isBinary(homeBin)) {
100
+ run(homeBin)
101
+ }
102
+
103
+ // 4. Check /opt/homebrew/bin (macOS)
104
+ if (os.platform() === "darwin" && isBinary("/opt/homebrew/bin/openscience")) {
105
+ run("/opt/homebrew/bin/openscience")
106
+ }
107
+
108
+ // 5. Check /usr/local/bin
109
+ if (isBinary("/usr/local/bin/openscience")) {
110
+ run("/usr/local/bin/openscience")
111
+ }
112
+
113
+ console.error("openscience binary not found.")
114
+ console.error("Install with: curl -fsSL https://syntheticsciences.ai/install | bash")
115
+ console.error("Or set OPENSCIENCE_BIN_PATH environment variable.")
116
+ process.exit(1)
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@synsci/openscience",
3
+ "bin": {
4
+ "openscience": "./bin/openscience"
5
+ },
6
+ "scripts": {
7
+ "postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
8
+ },
9
+ "version": "1.2.0",
10
+ "optionalDependencies": {
11
+ "@synsci/openscience-linux-x64-baseline-musl": "1.2.0",
12
+ "@synsci/openscience-windows-x64-baseline": "1.2.0",
13
+ "@synsci/openscience-linux-x64-baseline": "1.2.0",
14
+ "@synsci/openscience-darwin-x64": "1.2.0",
15
+ "@synsci/openscience-linux-arm64-musl": "1.2.0",
16
+ "@synsci/openscience-darwin-x64-baseline": "1.2.0",
17
+ "@synsci/openscience": "1.2.0",
18
+ "@synsci/openscience-linux-x64-musl": "1.2.0",
19
+ "@synsci/openscience-darwin-arm64": "1.2.0",
20
+ "@synsci/openscience-linux-arm64": "1.2.0",
21
+ "@synsci/openscience-windows-x64": "1.2.0",
22
+ "@synsci/openscience-linux-x64": "1.2.0"
23
+ }
24
+ }
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs"
4
+ import path from "path"
5
+ import os from "os"
6
+ import { fileURLToPath } from "url"
7
+ import { createRequire } from "module"
8
+
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
10
+ const require = createRequire(import.meta.url)
11
+
12
+ function detectPlatformAndArch() {
13
+ // Map platform names
14
+ let platform
15
+ switch (os.platform()) {
16
+ case "darwin":
17
+ platform = "darwin"
18
+ break
19
+ case "linux":
20
+ platform = "linux"
21
+ break
22
+ case "win32":
23
+ platform = "windows"
24
+ break
25
+ default:
26
+ platform = os.platform()
27
+ break
28
+ }
29
+
30
+ // Map architecture names
31
+ let arch
32
+ switch (os.arch()) {
33
+ case "x64":
34
+ arch = "x64"
35
+ break
36
+ case "arm64":
37
+ arch = "arm64"
38
+ break
39
+ case "arm":
40
+ arch = "arm"
41
+ break
42
+ default:
43
+ arch = os.arch()
44
+ break
45
+ }
46
+
47
+ return { platform, arch }
48
+ }
49
+
50
+ function findBinary() {
51
+ const { platform, arch } = detectPlatformAndArch()
52
+ const binaryName = platform === "windows" ? "openscience.exe" : "openscience"
53
+
54
+ // Try scoped package first (@synsci/openscience-darwin-arm64), then unscoped (openscience-darwin-arm64)
55
+ const packageNames = [
56
+ `@synsci/openscience-${platform}-${arch}`,
57
+ `openscience-${platform}-${arch}`,
58
+ ]
59
+
60
+ for (const packageName of packageNames) {
61
+ try {
62
+ const packageJsonPath = require.resolve(`${packageName}/package.json`)
63
+ const packageDir = path.dirname(packageJsonPath)
64
+ const binaryPath = path.join(packageDir, "bin", binaryName)
65
+
66
+ if (!fs.existsSync(binaryPath)) {
67
+ continue
68
+ }
69
+
70
+ return { binaryPath, binaryName }
71
+ } catch {
72
+ continue
73
+ }
74
+ }
75
+
76
+ throw new Error(`Could not find platform binary package for ${platform}-${arch}`)
77
+ }
78
+
79
+ function prepareBinDirectory(binaryName) {
80
+ const binDir = path.join(__dirname, "bin")
81
+ const targetPath = path.join(binDir, binaryName)
82
+
83
+ // Ensure bin directory exists
84
+ if (!fs.existsSync(binDir)) {
85
+ fs.mkdirSync(binDir, { recursive: true })
86
+ }
87
+
88
+ // Remove existing binary/symlink if it exists
89
+ if (fs.existsSync(targetPath)) {
90
+ fs.unlinkSync(targetPath)
91
+ }
92
+
93
+ return { binDir, targetPath }
94
+ }
95
+
96
+ function symlinkBinary(sourcePath, binaryName) {
97
+ const { targetPath } = prepareBinDirectory(binaryName)
98
+
99
+ fs.symlinkSync(sourcePath, targetPath)
100
+ console.log(`openscience binary symlinked: ${targetPath} -> ${sourcePath}`)
101
+
102
+ // Verify the file exists after operation
103
+ if (!fs.existsSync(targetPath)) {
104
+ throw new Error(`Failed to symlink binary to ${targetPath}`)
105
+ }
106
+ }
107
+
108
+ async function main() {
109
+ try {
110
+ if (os.platform() === "win32") {
111
+ // On Windows, the .exe is already included in the package and bin field points to it
112
+ // No postinstall setup needed
113
+ console.log("Windows detected: binary setup not needed (using packaged .exe)")
114
+ return
115
+ }
116
+
117
+ // On non-Windows platforms, just verify the binary package exists
118
+ // Don't replace the wrapper script - it handles binary execution
119
+ const { binaryPath } = findBinary()
120
+ console.log(`Platform binary verified at: ${binaryPath}`)
121
+ console.log("Wrapper script will handle binary execution")
122
+ } catch (error) {
123
+ console.error("Failed to setup openscience binary:", error.message)
124
+ process.exit(1)
125
+ }
126
+ }
127
+
128
+ try {
129
+ main()
130
+ } catch (error) {
131
+ console.error("Postinstall script error:", error.message)
132
+ process.exit(0)
133
+ }