thinkncollab-shell 2.0.0-beta.3 → 2.0.0-beta.4

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,3 +1,5 @@
1
+ <p align="center"><img src="native/brand/thinkncollab-logo.png" alt="ThinkNCollab" width="320"></p>
2
+
1
3
  # ThinkNCollab Shell V2 (`thinknsh`)
2
4
 
3
5
  > **The Native-First Collaborative Developer OS: Lightweight MicroVM Sandbox & Zero-Daemon Dev Runner with Live Database Snapshots, P2P Terminal Multiplexing, and OCI Compatibility.**
Binary file
Binary file
@@ -25,6 +25,10 @@ for arch in arm64 x86_64; do
25
25
  xcrun swiftc -O -target "$arch-apple-macos13" -o "$WORK/tray-$arch" "$HERE/main.swift"
26
26
  done
27
27
  lipo -create -output "$APP/Contents/MacOS/thinknsh-tray" "$WORK/tray-arm64" "$WORK/tray-x86_64"
28
+ # ThinkNCollab icons (native/brand, made by make-icons.py): the app icon and the menu bar template
29
+ for f in AppIcon.icns menubar.png menubar@2x.png; do
30
+ cp "$HERE/../brand/$f" "$APP/Contents/Resources/$f"
31
+ done
28
32
 
29
33
  cat > "$APP/Contents/Info.plist" <<PLIST
30
34
  <?xml version="1.0" encoding="UTF-8"?>
@@ -36,6 +40,7 @@ cat > "$APP/Contents/Info.plist" <<PLIST
36
40
  <key>CFBundleIdentifier</key><string>com.thinkncollab.thinknsh</string>
37
41
  <key>CFBundleExecutable</key><string>thinknsh-tray</string>
38
42
  <key>CFBundlePackageType</key><string>APPL</string>
43
+ <key>CFBundleIconFile</key><string>AppIcon</string>
39
44
  <key>CFBundleShortVersionString</key><string>${VERSION}</string>
40
45
  <key>CFBundleVersion</key><string>${VERSION}</string>
41
46
  <key>LSMinimumSystemVersion</key><string>13.0</string>
@@ -121,10 +121,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
121
121
 
122
122
  // MARK: menu
123
123
 
124
+ // The TNC mark (Resources/menubar.png + @2x, a template macOS tints for light and dark),
125
+ // dimmed while dock is not running; a system symbol when the bundle has no icon.
124
126
  private func setIcon(_ status: String) {
125
- let name = status == "running" ? "shippingbox.fill" : "shippingbox"
126
- let img = NSImage(systemSymbolName: name, accessibilityDescription: "thinknsh dock \(status)")
127
+ let img = Bundle.main.image(forResource: "menubar")
128
+ ?? NSImage(systemSymbolName: status == "running" ? "shippingbox.fill" : "shippingbox", accessibilityDescription: nil)
127
129
  img?.isTemplate = true
130
+ img?.accessibilityDescription = "thinknsh dock \(status)"
128
131
  statusItem.button?.image = img
129
132
  statusItem.button?.appearsDisabled = status != "running"
130
133
  }
@@ -33,7 +33,7 @@ public static class TncTray {
33
33
  static readonly ConcurrentQueue<string> lines = new ConcurrentQueue<string>();
34
34
  static readonly JavaScriptSerializer json = new JavaScriptSerializer();
35
35
 
36
- public static void Run(string node, string cli) {
36
+ public static void Run(string node, string cli, string dir) {
37
37
  var psi = new ProcessStartInfo(node, "\"" + cli + "\" dock tray");
38
38
  psi.UseShellExecute = false;
39
39
  psi.RedirectStandardInput = true;
@@ -55,7 +55,8 @@ public static class TncTray {
55
55
  errors.Start();
56
56
 
57
57
  icon = new NotifyIcon();
58
- icon.Icon = SystemIcons.Application;
58
+ var ico = System.IO.Path.Combine(dir ?? "", "tnc.ico"); // the TNC icon, next to this script
59
+ icon.Icon = System.IO.File.Exists(ico) ? new Icon(ico) : SystemIcons.Application;
59
60
  icon.Text = "thinknsh dock";
60
61
  icon.Visible = true;
61
62
  icon.ContextMenuStrip = new ContextMenuStrip();
@@ -133,4 +134,4 @@ public static class TncTray {
133
134
  if ($CompileOnly) { Write-Output 'tray compiled'; exit 0 }
134
135
  if (-not $Node -or -not $Cli) { throw 'usage: tray.ps1 -Node <node.exe> -Cli <thinknsh.js>' }
135
136
  [System.Windows.Forms.Application]::EnableVisualStyles()
136
- [TncTray]::Run($Node, $Cli)
137
+ [TncTray]::Run($Node, $Cli, $PSScriptRoot)
@@ -4,4 +4,4 @@
4
4
  * PROPRIETARY INTELLECTUAL PROPERTY & TRADE SECRETS.
5
5
  * UNAUTHORIZED REVERSE ENGINEERING, DECOMPILATION, OR RE-DISTRIBUTION IS STRICTLY PROHIBITED.
6
6
  */
7
- "use strict";const fs=require("fs"),os=require("os"),path=require("path"),{spawnSync,spawn}=require("child_process"),ROOT=path.join(__dirname,"..","..",".."),CLI=path.join(ROOT,"bin","thinknsh.js"),SOURCE=path.join(ROOT,"native","tnc-tray"),macTarget=()=>process.env.TNC_APP_DIR||path.join(os.homedir(),"Applications","Thinknsh.app"),winDir=()=>process.env.TNC_APP_DIR||path.join(process.env.LOCALAPPDATA||path.join(os.homedir(),"AppData","Local"),"Thinknsh"),winMenuEntry=()=>path.join(process.env.APPDATA||path.join(os.homedir(),"AppData","Roaming"),"Microsoft","Windows","Start Menu","Programs","Thinknsh.vbs");function agentConfig(){return JSON.stringify({node:process.execPath,cli:CLI},null,2)+"\n"}function findMacApp(n){const t=path.join(os.homedir(),".tnc","bin","Thinknsh.app");if(fs.existsSync(path.join(t,"Contents","MacOS","thinknsh-tray")))return t;const s=path.join(SOURCE,"build-macos.sh");if(fs.existsSync(s)&&0===spawnSync("xcrun",["--find","swiftc"],{stdio:"ignore"}).status){const t=fs.mkdtempSync(path.join(os.tmpdir(),"tnc-tray-"));n?.("building the menu-bar app from source (swiftc)");const e=spawnSync("bash",[s,t],{encoding:"utf8"});if(0!==e.status)throw new Error(`building the app failed: ${(e.stderr||e.stdout).trim().split("\n").slice(-3).join(" ")}`);return path.join(t,"Thinknsh.app")}throw new Error("the menu-bar app is not in this runtime: run thinknsh dock setup again, or install Xcode command line tools to build it")}function winLauncher(n){const t=n=>n.replace(/"/g,'""');return`' thinknsh dock tray (written by thinknsh dock app install)\r\nSet sh = CreateObject("WScript.Shell")\r\nsh.Run "powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ""${t(path.join(n,"tray.ps1"))}"" -Node ""${t(process.execPath)}"" -Cli ""${t(CLI)}""", 0, False\r\n`}function removeEarlierApp(n){const t=path.join(os.homedir(),"Applications","TNC Dock.app"),s=path.join(os.homedir(),"Library","LaunchAgents","com.thinkncollab.dock.menubar.plist");fs.existsSync(s)&&(spawnSync("launchctl",["bootout",`gui/${process.getuid()}/com.thinkncollab.dock.menubar`],{stdio:"ignore"}),fs.rmSync(s,{force:!0})),fs.existsSync(t)&&(spawnSync("pkill",["-f",`${t}/Contents/MacOS/`],{stdio:"ignore"}),fs.rmSync(t,{recursive:!0,force:!0}),n.push(`removed the earlier menu bar app (${t})`))}function install({log:n}={}){const t=[];if("darwin"===process.platform){removeEarlierApp(t);const s=findMacApp(n),e=macTarget();fs.mkdirSync(path.dirname(e),{recursive:!0}),spawnSync("pkill",["-f",`${e}/Contents/MacOS/thinknsh-tray`],{stdio:"ignore"}),fs.rmSync(e,{recursive:!0,force:!0});const i=spawnSync("ditto",[s,e],{encoding:"utf8"});if(0!==i.status)throw new Error(`copying the app: ${i.stderr.trim()}`);fs.writeFileSync(path.join(e,"Contents","Resources","agent.json"),agentConfig()),t.push(`menu-bar app: ${e}`)}else{if("win32"!==process.platform)throw new Error("there is no tray app on Linux; the dashboard is thinknsh dock ui");{const n=winDir();fs.mkdirSync(n,{recursive:!0}),fs.copyFileSync(path.join(SOURCE,"tray.ps1"),path.join(n,"tray.ps1")),fs.writeFileSync(path.join(n,"Thinknsh.vbs"),winLauncher(n)),fs.mkdirSync(path.dirname(winMenuEntry()),{recursive:!0}),fs.copyFileSync(path.join(n,"Thinknsh.vbs"),winMenuEntry()),t.push(`tray app: ${n} (Start menu: Thinknsh)`)}}const s=require("../setup/autostart");return s.status().enabled&&t.push(...s.enable().filter(n=>/app/.test(n))),open(),t}function installedPath(){if("darwin"===process.platform)return fs.existsSync(macTarget())?macTarget():require("../setup/autostart").appBundle();if("win32"===process.platform){const n=path.join(winDir(),"Thinknsh.vbs");return fs.existsSync(n)?n:null}return null}function open(){const n=installedPath();if(!n)throw new Error("the tray app is not installed: thinknsh dock app install");"darwin"===process.platform?spawn("open",[n],{stdio:"ignore",detached:!0}).unref():spawn("wscript.exe",[n],{stdio:"ignore",detached:!0}).unref()}function uninstall(){const n=[];if("darwin"===process.platform){const t=macTarget();spawnSync("pkill",["-f",`${t}/Contents/MacOS/thinknsh-tray`],{stdio:"ignore"}),fs.existsSync(t)&&(fs.rmSync(t,{recursive:!0,force:!0}),n.push(`removed ${t}`))}else if("win32"===process.platform)for(const t of[winDir(),winMenuEntry()])fs.existsSync(t)&&(fs.rmSync(t,{recursive:!0,force:!0}),n.push(`removed ${t}`));const t=require("../setup/autostart");return t.status().app&&(fs.rmSync(path.join(path.dirname(t.status().file),`${t.APP_LABEL}.plist`),{force:!0}),n.push("removed the login item of the app")),n.length||n.push("the tray app was not installed"),n}module.exports={install,uninstall,open,installedPath,winLauncher};
7
+ "use strict";const fs=require("fs"),os=require("os"),path=require("path"),{spawnSync,spawn}=require("child_process"),ROOT=path.join(__dirname,"..","..",".."),CLI=path.join(ROOT,"bin","thinknsh.js"),SOURCE=path.join(ROOT,"native","tnc-tray"),macTarget=()=>process.env.TNC_APP_DIR||path.join(os.homedir(),"Applications","Thinknsh.app"),winDir=()=>process.env.TNC_APP_DIR||path.join(process.env.LOCALAPPDATA||path.join(os.homedir(),"AppData","Local"),"Thinknsh"),winMenuEntry=()=>path.join(process.env.APPDATA||path.join(os.homedir(),"AppData","Roaming"),"Microsoft","Windows","Start Menu","Programs","Thinknsh.vbs");function agentConfig(){return JSON.stringify({node:process.execPath,cli:CLI},null,2)+"\n"}function findMacApp(n){const t=path.join(os.homedir(),".tnc","bin","Thinknsh.app");if(fs.existsSync(path.join(t,"Contents","MacOS","thinknsh-tray")))return t;const s=path.join(SOURCE,"build-macos.sh");if(fs.existsSync(s)&&0===spawnSync("xcrun",["--find","swiftc"],{stdio:"ignore"}).status){const t=fs.mkdtempSync(path.join(os.tmpdir(),"tnc-tray-"));n?.("building the menu-bar app from source (swiftc)");const e=spawnSync("bash",[s,t],{encoding:"utf8"});if(0!==e.status)throw new Error(`building the app failed: ${(e.stderr||e.stdout).trim().split("\n").slice(-3).join(" ")}`);return path.join(t,"Thinknsh.app")}throw new Error("the menu-bar app is not in this runtime: run thinknsh dock setup again, or install Xcode command line tools to build it")}function winLauncher(n){const t=n=>n.replace(/"/g,'""');return`' thinknsh dock tray (written by thinknsh dock app install)\r\nSet sh = CreateObject("WScript.Shell")\r\nsh.Run "powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ""${t(path.join(n,"tray.ps1"))}"" -Node ""${t(process.execPath)}"" -Cli ""${t(CLI)}""", 0, False\r\n`}function removeEarlierApp(n){const t=path.join(os.homedir(),"Applications","TNC Dock.app"),s=path.join(os.homedir(),"Library","LaunchAgents","com.thinkncollab.dock.menubar.plist");fs.existsSync(s)&&(spawnSync("launchctl",["bootout",`gui/${process.getuid()}/com.thinkncollab.dock.menubar`],{stdio:"ignore"}),fs.rmSync(s,{force:!0})),fs.existsSync(t)&&(spawnSync("pkill",["-f",`${t}/Contents/MacOS/`],{stdio:"ignore"}),fs.rmSync(t,{recursive:!0,force:!0}),n.push(`removed the earlier menu bar app (${t})`))}function install({log:n}={}){const t=[];if("darwin"===process.platform){removeEarlierApp(t);const s=findMacApp(n),e=macTarget();fs.mkdirSync(path.dirname(e),{recursive:!0}),spawnSync("pkill",["-f",`${e}/Contents/MacOS/thinknsh-tray`],{stdio:"ignore"}),fs.rmSync(e,{recursive:!0,force:!0});const i=spawnSync("ditto",[s,e],{encoding:"utf8"});if(0!==i.status)throw new Error(`copying the app: ${i.stderr.trim()}`);fs.writeFileSync(path.join(e,"Contents","Resources","agent.json"),agentConfig()),t.push(`menu-bar app: ${e}`)}else{if("win32"!==process.platform)throw new Error("there is no tray app on Linux; the dashboard is thinknsh dock ui");{const n=winDir();fs.mkdirSync(n,{recursive:!0}),fs.copyFileSync(path.join(SOURCE,"tray.ps1"),path.join(n,"tray.ps1"));const s=path.join(ROOT,"native","brand","tnc.ico");fs.existsSync(s)&&fs.copyFileSync(s,path.join(n,"tnc.ico")),fs.writeFileSync(path.join(n,"Thinknsh.vbs"),winLauncher(n)),fs.mkdirSync(path.dirname(winMenuEntry()),{recursive:!0}),fs.copyFileSync(path.join(n,"Thinknsh.vbs"),winMenuEntry()),t.push(`tray app: ${n} (Start menu: Thinknsh)`)}}const s=require("../setup/autostart");return s.status().enabled&&t.push(...s.enable().filter(n=>/app/.test(n))),open(),t}function installedPath(){if("darwin"===process.platform)return fs.existsSync(macTarget())?macTarget():require("../setup/autostart").appBundle();if("win32"===process.platform){const n=path.join(winDir(),"Thinknsh.vbs");return fs.existsSync(n)?n:null}return null}function open(){const n=installedPath();if(!n)throw new Error("the tray app is not installed: thinknsh dock app install");"darwin"===process.platform?spawn("open",[n],{stdio:"ignore",detached:!0}).unref():spawn("wscript.exe",[n],{stdio:"ignore",detached:!0}).unref()}function uninstall(){const n=[];if("darwin"===process.platform){const t=macTarget();spawnSync("pkill",["-f",`${t}/Contents/MacOS/thinknsh-tray`],{stdio:"ignore"}),fs.existsSync(t)&&(fs.rmSync(t,{recursive:!0,force:!0}),n.push(`removed ${t}`))}else if("win32"===process.platform)for(const t of[winDir(),winMenuEntry()])fs.existsSync(t)&&(fs.rmSync(t,{recursive:!0,force:!0}),n.push(`removed ${t}`));const t=require("../setup/autostart");return t.status().app&&(fs.rmSync(path.join(path.dirname(t.status().file),`${t.APP_LABEL}.plist`),{force:!0}),n.push("removed the login item of the app")),n.length||n.push("the tray app was not installed"),n}module.exports={install,uninstall,open,installedPath,winLauncher};
@@ -4,12 +4,13 @@
4
4
  * PROPRIETARY INTELLECTUAL PROPERTY & TRADE SECRETS.
5
5
  * UNAUTHORIZED REVERSE ENGINEERING, DECOMPILATION, OR RE-DISTRIBUTION IS STRICTLY PROHIBITED.
6
6
  */
7
- "use strict";const PAGE=String.raw`<!doctype html>
7
+ "use strict";const fs=require("fs"),path=require("path");function brandImage(e){try{return`data:image/png;base64,${fs.readFileSync(path.join(__dirname,"..","..","..","native","brand",e)).toString("base64")}`}catch(e){return""}}const FAVICON=brandImage("favicon-64.png"),LOGO=brandImage("favicon-64.png"),PAGE=String.raw`<!doctype html>
8
8
  <html lang="en">
9
9
  <head>
10
10
  <meta charset="utf-8">
11
11
  <meta name="viewport" content="width=device-width, initial-scale=1">
12
12
  <title>dock dashboard</title>
13
+ ${FAVICON?`<link rel="icon" type="image/png" href="${FAVICON}">`:""}
13
14
  <style>
14
15
  :root {
15
16
  --bg: #f6f7f9; --panel: #ffffff; --text: #18202b; --muted: #5d6878; --line: #e3e7ed;
@@ -29,6 +30,7 @@
29
30
  body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
30
31
  header { display: flex; align-items: center; gap: 12px; padding: 12px 20px; background: var(--panel); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 2; }
31
32
  header h1 { font-size: 16px; margin: 0; letter-spacing: .2px; }
33
+ header .logo { width: 24px; height: 24px; border-radius: 6px; }
32
34
  header .meta { color: var(--muted); font-size: 12px; }
33
35
  .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); display: inline-block; }
34
36
  .dot.on { background: var(--ok); }
@@ -89,6 +91,7 @@ pre.term:focus { box-shadow: 0 0 0 2px var(--accent); }
89
91
  </head>
90
92
  <body>
91
93
  <header>
94
+ ${LOGO?`<img class="logo" src="${LOGO}" alt="ThinkNCollab" width="24" height="24">`:""}
92
95
  <span class="dot" id="dot"></span>
93
96
  <h1>dock</h1>
94
97
  <span class="meta" id="meta">connecting…</span>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkncollab-shell",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.4",
4
4
  "description": "Lightweight MicroVM Sandbox & Zero-Daemon Dev Runner: Fast MicroVM Containers, Native Microservices, Live Database Snapshots, and End-to-End Encrypted State Sync",
5
5
  "main": "dist/src/core/shell.js",
6
6
  "bin": {