@woniru/we-installer 0.1.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.
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # Woniru Engine Installer (WE)
2
+
3
+ This repository contains the **public NPX installer** for **Woniru Engine (WE)**.
4
+
5
+ The installer is intentionally small and public. It **does not** contain the engine source code.
6
+ Instead, it guides the user through GitHub authorization and then **downloads the private WE repository** (only if the user has access), installs dependencies, and launches a local configuration wizard.
7
+
8
+ ---
9
+
10
+ ## Quick Start
11
+
12
+ Run the installer using NPX:
13
+
14
+ ```bash
15
+ npx @woniru/we-installer
16
+ ```
17
+
18
+ ## What the Installer Does
19
+
20
+ 1. The installer performs the following steps:
21
+ 1. Opens a browser to authorize with GitHub using the Device Flow.
22
+ 1. Verifies that the user has collaborator access to the private Woniru Engine repository.
23
+ 1. Downloads the engine source code from the repository.
24
+ 1. Runs npm install in the project directory.
25
+ 1. Launches a local configuration wizard.
26
+
27
+ ## The configuration wizard guides the user through:
28
+
29
+ ### Step 1 — Redis Setup
30
+
31
+ - Connect to an existing Redis instance, or
32
+
33
+ - Automatically create a new Redis instance using Docker.
34
+
35
+ ### Step 2 — Database Configuration
36
+
37
+ - Database host
38
+
39
+ - Database user
40
+
41
+ - Database password
42
+
43
+ - Database name
44
+
45
+ - Applies the WE schema to the database.
46
+
47
+ ### Step 3 — Admin Access
48
+
49
+ - Creates the initial admin user.
50
+
51
+ - Displays commands required to start the server.
52
+
53
+ ## Default Admin Credentials
54
+
55
+ After installation completes, the default admin account is:
56
+
57
+ **Username:**
58
+ ```
59
+ admin@we.com
60
+ ```
61
+
62
+ **Password:**
63
+ ```
64
+ weAdmin
65
+ ```
66
+
67
+ These credentials can be changed after logging into the system.
68
+
69
+ ## Commands After Installation
70
+
71
+ The installer provides two commands:
72
+
73
+ **Start the server:**
74
+ ```
75
+ npm run dev --redisAdminKey=<your-admin-key>
76
+ ```
77
+
78
+ **Recalculate user permissions:**
79
+ ```
80
+ npm run recalculate:user-permissions
81
+ ```
82
+
83
+ The second command is only required if permissions need to be recalculated after changes.
84
+
85
+ ## Access Control
86
+
87
+ This installer is public, but the **Woniru Engine repository is private**.
88
+
89
+ If you are a collaborator on the repository, the installer will download the engine successfully.
90
+
91
+ If you are not authorized, the installer will stop with an access error.
92
+
93
+ ## Requirements
94
+
95
+ Before running the installer ensure the following are installed:
96
+
97
+ **Node.js** version 18 or higher
98
+
99
+ **npm** version 9 or higher
100
+
101
+ **Docker Desktop** for running private redis instance
102
+
103
+ Network access is required for:
104
+
105
+ - GitHub
106
+ - npm registry
107
+ - your configured database server
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { runAuth } = require("../src/auth");
4
+ const { runDownload } = require("../src/download");
5
+
6
+ const command = process.argv[2];
7
+
8
+ (async () => {
9
+ if (!command) {
10
+ console.log("Usage: we-installer <command>");
11
+ console.log("Commands:");
12
+ console.log(" auth Authenticate with GitHub");
13
+ console.log(" install Auth + download repo");
14
+ process.exit(0);
15
+ }
16
+
17
+ if (command === "auth") {
18
+ await runAuth();
19
+ return;
20
+ }
21
+
22
+ if (command === "install") {
23
+ const { token, user, ui } = await runAuth(); // make sure runAuth returns ui as well (see note below)
24
+ await runDownload({ token, ui });
25
+ console.log(`Done. Authenticated as ${user.login}.`);
26
+ return;
27
+ }
28
+
29
+ console.log(`Unknown command: ${command}`);
30
+ process.exit(1);
31
+ })().catch((err) => {
32
+ console.error("Error:", err.message);
33
+ process.exit(1);
34
+ });
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@woniru/we-installer",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "commonjs",
6
+ "bin": {
7
+ "we-installer": "./bin/we-installer.js"
8
+ },
9
+ "dependencies": {
10
+ "adm-zip": "^0.5.16",
11
+ "mysql2": "^3.18.2",
12
+ "open": "^11.0.0",
13
+ "redis": "^5.11.0"
14
+ },
15
+ "files": [
16
+ "bin",
17
+ "src",
18
+ "templates"
19
+ ]
20
+ }
package/src/auth.js ADDED
@@ -0,0 +1,87 @@
1
+ // src/auth.js
2
+ const { requestDeviceCode, pollForAccessToken } = require("./githubDeviceFlow");
3
+ const { startAuthServer } = require("./authServer");
4
+ const { getGithubUser } = require("./githubApi");
5
+
6
+ function openBrowserNative(url) {
7
+ const { exec } = require("child_process");
8
+ const platform = process.platform;
9
+
10
+ // Best-effort open; no external deps
11
+ if (platform === "win32") exec(`start "" "${url}"`);
12
+ else if (platform === "darwin") exec(`open "${url}"`);
13
+ else exec(`xdg-open "${url}"`);
14
+ }
15
+
16
+ /**
17
+ * Auth flow:
18
+ * 1) Request device code
19
+ * 2) Start local server + open browser
20
+ * 3) Poll GitHub for access token
21
+ * 4) Fetch /user to confirm identity
22
+ * 5) Switch UI phase to "install" so the page shows Accept/Manual section
23
+ *
24
+ * Returns: { token, user, ui }
25
+ */
26
+ async function runAuth() {
27
+ const clientId = 'Ov23lifTq8hC15zQcG4C';
28
+ if (!clientId) throw new Error("Missing env var WE_GITHUB_CLIENT_ID");
29
+
30
+ // Optional: allow overriding scope later; default is repo for private repo access
31
+ const scope = "repo";
32
+
33
+ console.log("Requesting GitHub device code...");
34
+ const device = await requestDeviceCode({ clientId, scope });
35
+
36
+ const ui = await startAuthServer({
37
+ verificationUri: device.verification_uri,
38
+ userCode: device.user_code
39
+ });
40
+
41
+ console.log("\nOpen this page to continue:");
42
+ console.log(ui.url + "\n");
43
+
44
+ // Best-effort open browser (user can still open manually from printed URL)
45
+ try { openBrowserNative(ui.url); } catch { }
46
+
47
+ // Phase: auth
48
+ ui.setPhase("auth");
49
+ ui.setStatus("Waiting for approval in GitHub…");
50
+
51
+ // Poll for access token
52
+ let token;
53
+ try {
54
+ token = await pollForAccessToken({
55
+ clientId,
56
+ deviceCode: device.device_code,
57
+ intervalSeconds: device.interval ?? 5,
58
+ expiresInSeconds: device.expires_in ?? 900
59
+ });
60
+ } catch (err) {
61
+ ui.setStatus(`Authorization failed ❌ ${err.message}`);
62
+ throw err;
63
+ }
64
+
65
+ // Verify identity
66
+ ui.setStatus("Authorized ✅ Verifying identity…");
67
+
68
+ let me;
69
+ try {
70
+ me = await getGithubUser({ token });
71
+ } catch (err) {
72
+ ui.setStatus(`Failed to verify identity ❌ ${err.message}`);
73
+ throw err;
74
+ }
75
+
76
+ ui.setUserLogin(me.login);
77
+ console.log(`✅ GitHub authentication successful as: ${me.login}`);
78
+
79
+ // ✅ THIS is the “one line” you were looking for:
80
+ // Move UI to install-choice phase so the page hides auth controls and shows Accept/Manual.
81
+ ui.setPhase("install");
82
+ ui.setStatus("Choose install location in the browser: Accept (use current directory) or Choose manually…");
83
+
84
+ return { token, user: me, ui };
85
+ }
86
+
87
+ module.exports = { runAuth };