techeduspace 0.0.0-stage → 0.2.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.
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * TechEduSpace CLI Workstation Launcher
5
+ * Supports: npx techeduspace or npm i -g techeduspace
6
+ * Author: Acadure Private Limited
7
+ */
8
+
9
+ const { spawn, execSync } = require("child_process")
10
+ const fs = require("fs")
11
+ const os = require("os")
12
+ const path = require("path")
13
+ const https = require("https")
14
+
15
+ const REPO = "acadure/acadure"
16
+ const RELEASE_TAG = "tes-exam-app-stable"
17
+ const BASE_DOWNLOAD_URL = `https://github.com/${REPO}/releases/download/${RELEASE_TAG}`
18
+
19
+ function log(msg) {
20
+ console.log(`\x1b[36m[TechEduSpace]\x1b[0m ${msg}`)
21
+ }
22
+
23
+ function err(msg) {
24
+ console.error(`\x1b[31m[TechEduSpace Error]\x1b[0m ${msg}`)
25
+ }
26
+
27
+ function findInstalledApp() {
28
+ const platform = os.platform()
29
+ if (platform === "win32") {
30
+ const candidates = [
31
+ path.join(process.env.LOCALAPPDATA || "", "Programs", "TechEduSpace", "TechEduSpace.exe"),
32
+ path.join(process.env.ProgramFiles || "", "TechEduSpace", "TechEduSpace.exe"),
33
+ path.join(process.env["ProgramFiles(x86)"] || "", "TechEduSpace", "TechEduSpace.exe"),
34
+ ]
35
+ for (const c of candidates) {
36
+ if (fs.existsSync(c)) return c
37
+ }
38
+ } else if (platform === "darwin") {
39
+ const candidates = [
40
+ "/Applications/TechEduSpace Beta.app",
41
+ "/Applications/TechEduSpace.app",
42
+ path.join(os.homedir(), "Applications", "TechEduSpace Beta.app"),
43
+ path.join(os.homedir(), "Applications", "TechEduSpace.app"),
44
+ path.resolve(__dirname, "../../dist/mac-arm64/TechEduSpace Beta.app"),
45
+ path.resolve(__dirname, "../../dist/mac/TechEduSpace.app"),
46
+ path.resolve(process.cwd(), "agents/tes-exam-app/dist/mac-arm64/TechEduSpace Beta.app"),
47
+ path.resolve(process.cwd(), "dist/mac-arm64/TechEduSpace Beta.app"),
48
+ ]
49
+ for (const c of candidates) {
50
+ if (fs.existsSync(c)) return c
51
+ }
52
+ } else if (platform === "linux") {
53
+ try {
54
+ const p = execSync("which techeduspace 2>/dev/null").toString().trim()
55
+ if (p && fs.existsSync(p)) return p
56
+ } catch {}
57
+ const defaultAppImage = path.join(os.homedir(), ".local", "bin", "TESExamApp.AppImage")
58
+ if (fs.existsSync(defaultAppImage)) return defaultAppImage
59
+ }
60
+ return null
61
+ }
62
+
63
+ function launchApp(appPath) {
64
+ const platform = os.platform()
65
+ log(`Launching TechEduSpace workstation...`)
66
+
67
+ let executable = appPath
68
+ if (platform === "darwin" && appPath.endsWith(".app")) {
69
+ const binName = path.basename(appPath, ".app")
70
+ const innerBin = path.join(appPath, "Contents", "MacOS", binName)
71
+ if (fs.existsSync(innerBin)) {
72
+ executable = innerBin
73
+ }
74
+ }
75
+
76
+ const env = { ...process.env }
77
+ delete env.ELECTRON_RUN_AS_NODE
78
+
79
+ const child = spawn(executable, [], { detached: true, stdio: "ignore", env })
80
+ child.unref()
81
+ process.exit(0)
82
+ }
83
+
84
+ function downloadFile(url, dest) {
85
+ return new Promise((resolve, reject) => {
86
+ log(`Downloading installer from ${url}...`)
87
+ const file = fs.createWriteStream(dest)
88
+
89
+ function get(currentUrl) {
90
+ https.get(currentUrl, (response) => {
91
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
92
+ get(response.headers.location)
93
+ return
94
+ }
95
+ if (response.statusCode !== 200) {
96
+ reject(new Error(`Failed to download: HTTP ${response.statusCode}`))
97
+ return
98
+ }
99
+ response.pipe(file)
100
+ file.on("finish", () => {
101
+ file.close(() => resolve(dest))
102
+ })
103
+ }).on("error", (err) => {
104
+ fs.unlink(dest, () => {})
105
+ reject(err)
106
+ })
107
+ }
108
+ get(url)
109
+ })
110
+ }
111
+
112
+ async function main() {
113
+ log("Initializing TechEduSpace Examination Workstation...")
114
+
115
+ const installed = findInstalledApp()
116
+ if (installed) {
117
+ log(`Found installed workstation at: ${installed}`)
118
+ launchApp(installed)
119
+ return
120
+ }
121
+
122
+ const platform = os.platform()
123
+ if (platform === "win32") {
124
+ log("TechEduSpace is not installed. Initiating automated Windows install...")
125
+ const tempInstaller = path.join(os.tmpdir(), "TESExamApp-windows-x64.exe")
126
+ const url = `${BASE_DOWNLOAD_URL}/TESExamApp-windows-x64.exe`
127
+
128
+ try {
129
+ await downloadFile(url, tempInstaller)
130
+ log("Running silent installer (/S)...")
131
+ execSync(`"${tempInstaller}" /S`, { stdio: "inherit" })
132
+ fs.unlinkSync(tempInstaller)
133
+
134
+ const newlyInstalled = findInstalledApp()
135
+ if (newlyInstalled) {
136
+ log("Installation complete! Launching TechEduSpace...")
137
+ launchApp(newlyInstalled)
138
+ } else {
139
+ log("Installation completed. Launch 'TechEduSpace' from Start Menu.")
140
+ }
141
+ } catch (e) {
142
+ err(`Automated install failed: ${e.message}`)
143
+ log("You can download directly from: " + url)
144
+ process.exit(1)
145
+ }
146
+ } else if (platform === "darwin") {
147
+ log("TechEduSpace is not installed. Downloading macOS installer...")
148
+ const arch = process.arch === "arm64" ? "arm64" : "x64"
149
+ const dmgName = `TESExamApp-darwin-${arch}.dmg`
150
+ const tempDmg = path.join(os.tmpdir(), dmgName)
151
+ const url = `${BASE_DOWNLOAD_URL}/${dmgName}`
152
+
153
+ try {
154
+ await downloadFile(url, tempDmg)
155
+ log("Mounting installer image...")
156
+ const mountPoint = path.join(os.tmpdir(), "TechEduSpaceMount")
157
+ try {
158
+ try { execSync(`hdiutil detach "${mountPoint}" -quiet 2>/dev/null`) } catch {}
159
+ execSync(`hdiutil attach "${tempDmg}" -nobrowse -mountpoint "${mountPoint}" -quiet`)
160
+
161
+ let foundApp = null
162
+ for (const name of ["TechEduSpace Beta.app", "TechEduSpace.app"]) {
163
+ const p = path.join(mountPoint, name)
164
+ if (fs.existsSync(p)) {
165
+ foundApp = p
166
+ break
167
+ }
168
+ }
169
+
170
+ const targetDir = fs.existsSync("/Applications") ? "/Applications" : path.join(os.homedir(), "Applications")
171
+ const targetApp = path.join(targetDir, foundApp ? path.basename(foundApp) : "TechEduSpace Beta.app")
172
+
173
+ if (foundApp) {
174
+ log(`Installing TechEduSpace to ${targetApp}...`)
175
+ execSync(`rm -rf "${targetApp}" && cp -R "${foundApp}" "${targetApp}"`)
176
+ }
177
+ execSync(`hdiutil detach "${mountPoint}" -quiet`)
178
+ fs.unlinkSync(tempDmg)
179
+
180
+ log("Installation complete! Launching TechEduSpace...")
181
+ launchApp(targetApp)
182
+ } catch (mountErr) {
183
+ log("Opening DMG for manual install...")
184
+ execSync(`open "${tempDmg}"`)
185
+ }
186
+ } catch (e) {
187
+ err(`Automated download failed: ${e.message}`)
188
+ log("You can download directly from: https://techeduspace.com/downloads")
189
+ process.exit(1)
190
+ }
191
+ } else if (platform === "linux") {
192
+ const appImage = path.join(os.homedir(), ".local", "bin", "TESExamApp.AppImage")
193
+ fs.mkdirSync(path.dirname(appImage), { recursive: true })
194
+ const url = `${BASE_DOWNLOAD_URL}/TESExamApp-linux-x64.AppImage`
195
+ try {
196
+ await downloadFile(url, appImage)
197
+ fs.chmodSync(appImage, 0o755)
198
+ log("Launching TechEduSpace AppImage...")
199
+ launchApp(appImage)
200
+ } catch (e) {
201
+ err(`Download failed: ${e.message}`)
202
+ process.exit(1)
203
+ }
204
+ } else {
205
+ log(`Please download TechEduSpace for ${platform} from https://techeduspace.com/downloads`)
206
+ }
207
+ }
208
+
209
+ main().catch((e) => {
210
+ err(e.message)
211
+ process.exit(1)
212
+ })
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
2
  "name": "techeduspace",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.4",
4
+ "description": "Cross-platform CLI installer and workstation launcher for TechEduSpace",
5
+ "bin": {
6
+ "techeduspace": "./bin/techeduspace.js"
7
+ },
8
+ "keywords": [
9
+ "techeduspace",
10
+ "exam",
11
+ "proctoring",
12
+ "acadure",
13
+ "assessment",
14
+ "coding-test"
15
+ ],
16
+ "author": "Acadure Private Limited <contact@acadure.com>",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/acadure/acadure.git",
20
+ "directory": "agents/tes-exam-app/cli"
21
+ },
22
+ "engines": {
23
+ "node": ">=18"
24
+ }
25
+ }
26
+
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.