devicerent 0.2.0 → 0.2.1

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,135 +1,135 @@
1
- # devicerent
2
-
3
- DeviceRent from your terminal. Rent a **real** Android phone by the minute,
4
- install your APK, run a Quick test or Espresso, get a hosted Appium URL, or hand
5
- the phone to DeviceyAI — everything the website does except show you the live
6
- screen. You don't need to know how to code to use it.
7
-
8
- ## Start here
9
-
10
- You need [Node.js](https://nodejs.org) 22 or newer (the LTS download). Then open
11
- a terminal — on Windows press Start and type **Terminal**, on a Mac press ⌘-Space
12
- and type **Terminal** — and type:
13
-
14
- ```bash
15
- npx devicerent
16
- ```
17
-
18
- That opens a guided session:
19
-
20
- ```
21
- ╭──────────────────────────────────────────────────╮
22
- │ ✻ Welcome to DeviceRent │
23
- │ Real Android phones, rented by the minute. │
24
- │ you@example.com · Pro · Wallet €12.50 │
25
- ╰──────────────────────────────────────────────────╯
26
- ╭──────────────────────────────────────────────────╮
27
- │ > rent a phone │
28
- ╰──────────────────────────────────────────────────╯
29
- / for commands · ? for help no phone rented
30
- ```
31
-
32
- Then just say what you want, in plain words:
33
-
34
- | Type | What happens |
35
- | --- | --- |
36
- | `rent` | Pick a phone from a menu; it shows **your** price and asks before billing starts |
37
- | *drag your `.apk` onto the window* | Installs it on the rented phone, then offers to open it |
38
- | `test my app` | The Quick test: opens your app, taps around, reports any crash |
39
- | `take a screenshot` | Saves a picture of the phone's screen to Downloads and opens it |
40
- | `open Settings and turn on dark mode` | Anything else in plain words goes to DeviceyAI, which does it on the phone (it asks first, and uses AI credits) |
41
- | `I'm done` | Stops the rental (it asks first; the phone is wiped afterwards) |
42
- | `balance` · `topup` · `plans` | Your wallet and plan; payment opens Stripe in your browser |
43
- | `/` | Every command, with a live menu — ↑↓ to choose, Enter to run |
44
-
45
- Leaving with a phone still rented asks whether to stop it first. Arrow keys,
46
- Enter and Esc work in every menu; Ctrl-C stops whatever is running.
47
-
48
- ## One command at a time (scripts and CI)
49
-
50
- Every command also works on its own, exactly as before, and that is what
51
- scripts and CI should use:
52
-
53
- ```bash
54
- npm install -g devicerent # Node 22 or newer
55
- devicerent login # approve in your browser, like `gh auth login`
56
- devicerent devices # what is in the rack right now
57
- devicerent rent "Pixel 7a" # billing starts now
58
- devicerent install app-debug.apk --launch
59
- devicerent test quick com.example.app --report quick-test.md
60
- devicerent stop
61
- ```
62
-
63
- `devicerent` with no command opens the guided session only when a person is at
64
- a terminal. Piped, with `--json`, under `CI`, or with
65
- `DEVICERENT_NO_INTERACTIVE=1`, it prints the help text instead, and every
66
- command's output and exit code are unchanged.
67
-
68
- ## Signing in
69
-
70
- `devicerent login` opens `devicerent.net` in your browser and asks you to
71
- approve the sign-in. Nothing is typed into the terminal: the page hands the
72
- terminal a one-time sign-in token, encrypted so that only the waiting
73
- `devicerent` process can open it. If your account has two-factor turned on, the
74
- terminal asks for your authenticator code too.
75
-
76
- Signing in on a machine without a browser (an SSH session, a VM):
77
-
78
- ```bash
79
- devicerent login --no-browser # open the printed link anywhere, paste the code back
80
- ```
81
-
82
- The session is stored in `~/.config/devicerent/` (`%APPDATA%\devicerent` on
83
- Windows), readable only by you, and is only ever sent to the DeviceRent that
84
- issued it. `devicerent logout` signs this terminal out and leaves your browser
85
- sessions alone.
86
-
87
- ## Commands
88
-
89
- | Group | Commands |
90
- | --- | --- |
91
- | Account | `whoami`, `wallet [--history]`, `history`, `credits [buy s\|m\|l]`, `topup <eur>`, `subscribe <plus\|pro\|slot> [--yearly]`, `billing`, `keys list\|create\|revoke` |
92
- | Rentals | `devices [--available]`, `rent <device…>` (up to three), `status`, `stop [rental] \| --all` |
93
- | Phone | `install <apk…> [--launch]`, `apps`, `launch <pkg>`, `uninstall <pkg>`, `shell [cmd]`, `logcat [-f] [--package] [--level]`, `screenshot [file]`, `push`, `pull`, `ui [--xml]` |
94
- | Testing | `test espresso [--runner] [--class] [--junit out.xml]`, `test quick <apk\|pkg> [--report] [--fix-prompt]`, `appium [--check]`, `connect [--port]` |
95
- | DeviceyAI | `ai "<task>" [--allow-actions] [--allow-shell] [--model]`, `ai --models` |
96
-
97
- Every command takes `--json` for machine-readable output, and `-h` for help.
98
- With more than one rental running, pick the phone with `--rental <id or name>`.
99
-
100
- Payments always happen in the browser: `topup`, `subscribe`, `credits buy` and
101
- `billing` print a Stripe link and open it.
102
-
103
- ## How you are billed
104
-
105
- Exactly as on the website. A rental bills per minute from `rent` until `stop`,
106
- at your plan's rate. A rental with no activity for 30 minutes is stopped for
107
- you; installing, testing, shell input and DeviceyAI steps count as activity,
108
- merely holding `logcat -f` or an idle `connect` tunnel open does not.
109
- DeviceyAI spends AI credits, the same as in the panel.
110
-
111
- ## Exit codes
112
-
113
- `0` success · `1` failure (a test failed, the app crashed, a request was
114
- refused) · `2` usage error or not signed in · `3` the test run itself broke.
115
-
116
- `test espresso` writes JUnit XML with `--junit`, so it drops into a CI report.
117
-
118
- ## Pointing at another DeviceRent
119
-
120
- `--api-base <url>` (or `DEVICERENT_API_BASE`) targets another deployment, for
121
- example a local `next start` on `http://localhost:3000`. Each deployment keeps
122
- its own session.
123
-
124
- ## Security
125
-
126
- - The terminal holds an ordinary DeviceRent session for your account — the same
127
- identity and the same row-level security as your browser tab. It can do what
128
- you can do on the site; admin pages stay browser-only.
129
- - Phones are reached over the same serial-pinned, ten-minute bridge tokens the
130
- session page uses. The Pi never sees your session.
131
- - Approve a sign-in only if you just ran `devicerent login` yourself, and never
132
- send the code from `--no-browser` to anyone.
133
-
134
- Source: [`clients/devicerent-cli`](https://github.com/DeviceRent-net/devicerent.net/tree/main/clients/devicerent-cli).
135
- Design notes: `docs/CLI.md` in the same repository.
1
+ # devicerent
2
+
3
+ DeviceRent from your terminal. Rent a **real** Android phone by the minute,
4
+ install your APK, run a Quick test or Espresso, get a hosted Appium URL, or hand
5
+ the phone to DeviceyAI — everything the website does except show you the live
6
+ screen. You don't need to know how to code to use it.
7
+
8
+ ## Start here
9
+
10
+ You need [Node.js](https://nodejs.org) 22 or newer (the LTS download). Then open
11
+ a terminal — on Windows press Start and type **Terminal**, on a Mac press ⌘-Space
12
+ and type **Terminal** — and type:
13
+
14
+ ```bash
15
+ npx devicerent
16
+ ```
17
+
18
+ That opens a guided session:
19
+
20
+ ```
21
+ ╭──────────────────────────────────────────────────╮
22
+ │ ✻ Welcome to DeviceRent │
23
+ │ Real Android phones, rented by the minute. │
24
+ │ you@example.com · Pro · Wallet €12.50 │
25
+ ╰──────────────────────────────────────────────────╯
26
+ ╭──────────────────────────────────────────────────╮
27
+ │ > rent a phone │
28
+ ╰──────────────────────────────────────────────────╯
29
+ / for commands · ? for help no phone rented
30
+ ```
31
+
32
+ Then just say what you want, in plain words:
33
+
34
+ | Type | What happens |
35
+ | --- | --- |
36
+ | `rent` | Pick a phone from a menu; it shows **your** price and asks before billing starts |
37
+ | *drag your `.apk` onto the window* | Installs it on the rented phone, then offers to open it |
38
+ | `test my app` | The Quick test: opens your app, taps around, reports any crash |
39
+ | `take a screenshot` | Saves a picture of the phone's screen to Downloads and opens it |
40
+ | `open Settings and turn on dark mode` | Anything else in plain words goes to DeviceyAI, which does it on the phone (it asks first, and uses AI credits) |
41
+ | `I'm done` | Stops the rental (it asks first; the phone is wiped afterwards) |
42
+ | `balance` · `topup` · `plans` | Your wallet and plan; payment opens Stripe in your browser |
43
+ | `/` | Every command, with a live menu — ↑↓ to choose, Enter to run |
44
+
45
+ Leaving with a phone still rented asks whether to stop it first. Arrow keys,
46
+ Enter and Esc work in every menu; Ctrl-C stops whatever is running.
47
+
48
+ ## One command at a time (scripts and CI)
49
+
50
+ Every command also works on its own, exactly as before, and that is what
51
+ scripts and CI should use:
52
+
53
+ ```bash
54
+ npm install -g devicerent # Node 22 or newer
55
+ devicerent login # approve in your browser, like `gh auth login`
56
+ devicerent devices # what is in the rack right now
57
+ devicerent rent "Pixel 7a" # billing starts now
58
+ devicerent install app-debug.apk --launch
59
+ devicerent test quick com.example.app --report quick-test.md
60
+ devicerent stop
61
+ ```
62
+
63
+ `devicerent` with no command opens the guided session only when a person is at
64
+ a terminal. Piped, with `--json`, under `CI`, or with
65
+ `DEVICERENT_NO_INTERACTIVE=1`, it prints the help text instead, and every
66
+ command's output and exit code are unchanged.
67
+
68
+ ## Signing in
69
+
70
+ `devicerent login` opens `devicerent.net` in your browser and asks you to
71
+ approve the sign-in. Nothing is typed into the terminal: the page hands the
72
+ terminal a one-time sign-in token, encrypted so that only the waiting
73
+ `devicerent` process can open it. If your account has two-factor turned on, the
74
+ terminal asks for your authenticator code too.
75
+
76
+ Signing in on a machine without a browser (an SSH session, a VM):
77
+
78
+ ```bash
79
+ devicerent login --no-browser # open the printed link anywhere, paste the code back
80
+ ```
81
+
82
+ The session is stored in `~/.config/devicerent/` (`%APPDATA%\devicerent` on
83
+ Windows), readable only by you, and is only ever sent to the DeviceRent that
84
+ issued it. `devicerent logout` signs this terminal out and leaves your browser
85
+ sessions alone.
86
+
87
+ ## Commands
88
+
89
+ | Group | Commands |
90
+ | --- | --- |
91
+ | Account | `whoami`, `wallet [--history]`, `history`, `credits [buy s\|m\|l]`, `topup <eur>`, `subscribe <plus\|pro\|slot> [--yearly]`, `billing`, `keys list\|create\|revoke` |
92
+ | Rentals | `devices [--available]`, `rent <device…>` (up to three), `status`, `stop [rental] \| --all` |
93
+ | Phone | `install <apk…> [--launch]`, `apps`, `launch <pkg>`, `uninstall <pkg>`, `shell [cmd]`, `logcat [-f] [--package] [--level]`, `screenshot [file]`, `push`, `pull`, `ui [--xml]` |
94
+ | Testing | `test espresso [--runner] [--class] [--junit out.xml]`, `test quick <apk\|pkg> [--report] [--fix-prompt]`, `appium [--check]`, `connect [--port]` |
95
+ | DeviceyAI | `ai "<task>" [--allow-actions] [--allow-shell] [--model]`, `ai --models` |
96
+
97
+ Every command takes `--json` for machine-readable output, and `-h` for help.
98
+ With more than one rental running, pick the phone with `--rental <id or name>`.
99
+
100
+ Payments always happen in the browser: `topup`, `subscribe`, `credits buy` and
101
+ `billing` print a Stripe link and open it.
102
+
103
+ ## How you are billed
104
+
105
+ Exactly as on the website. A rental bills per minute from `rent` until `stop`,
106
+ at your plan's rate. A rental with no activity for 30 minutes is stopped for
107
+ you; installing, testing, shell input and DeviceyAI steps count as activity,
108
+ merely holding `logcat -f` or an idle `connect` tunnel open does not.
109
+ DeviceyAI spends AI credits, the same as in the panel.
110
+
111
+ ## Exit codes
112
+
113
+ `0` success · `1` failure (a test failed, the app crashed, a request was
114
+ refused) · `2` usage error or not signed in · `3` the test run itself broke.
115
+
116
+ `test espresso` writes JUnit XML with `--junit`, so it drops into a CI report.
117
+
118
+ ## Pointing at another DeviceRent
119
+
120
+ `--api-base <url>` (or `DEVICERENT_API_BASE`) targets another deployment, for
121
+ example a local `next start` on `http://localhost:3000`. Each deployment keeps
122
+ its own session.
123
+
124
+ ## Security
125
+
126
+ - The terminal holds an ordinary DeviceRent session for your account — the same
127
+ identity and the same row-level security as your browser tab. It can do what
128
+ you can do on the site; admin pages stay browser-only.
129
+ - Phones are reached over the same serial-pinned, ten-minute bridge tokens the
130
+ session page uses. The Pi never sees your session.
131
+ - Approve a sign-in only if you just ran `devicerent login` yourself, and never
132
+ send the code from `--no-browser` to anyone.
133
+
134
+ Source: [`clients/devicerent-cli`](https://github.com/DeviceRent-net/devicerent.net/tree/main/clients/devicerent-cli).
135
+ Design notes: `docs/CLI.md` in the same repository.
@@ -7,11 +7,14 @@
7
7
  // import (a static one would be hoisted above the check): on an old Node the
8
8
  // bundle dies with an error nobody can act on, and the people this tool is
9
9
  // for are told what to install instead.
10
- import { nodeTooOld, tooOldMessage } from "./nodeCheck.mjs";
10
+ import { loadFailedMessage, nodeTooOld, tooOldMessage } from "./nodeCheck.mjs";
11
11
 
12
12
  if (nodeTooOld(process.version)) {
13
13
  process.stderr.write(tooOldMessage(process.version));
14
14
  process.exitCode = 1;
15
15
  } else {
16
- import("../dist/devicerent.mjs");
16
+ import("../dist/devicerent.mjs").catch((err) => {
17
+ process.stderr.write(loadFailedMessage(err));
18
+ process.exitCode = 1;
19
+ });
17
20
  }
package/bin/nodeCheck.mjs CHANGED
@@ -19,3 +19,18 @@ export function tooOldMessage(version) {
19
19
  "Install the LTS version from https://nodejs.org, open a new terminal, then run: npx devicerent\n"
20
20
  );
21
21
  }
22
+
23
+ /**
24
+ * The bundle itself failed to load: a file missing from a broken install, or
25
+ * a dependency whose download did not finish. One sentence and what to do,
26
+ * not a stack trace.
27
+ */
28
+ export function loadFailedMessage(err) {
29
+ var first = String((err && err.message) || err).split("\n")[0];
30
+ return (
31
+ "DeviceRent could not start: " +
32
+ first +
33
+ "\n" +
34
+ "Reinstall it and try again: npx devicerent@latest (or, if you installed it: npm install -g devicerent@latest)\n"
35
+ );
36
+ }