@profullstack/readm3 0.14.1 → 0.15.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 +10 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/package.json +1 -1
- package/dist/coinpay-login.d.ts +0 -4
- package/dist/coinpay-login.d.ts.map +0 -1
- package/dist/coinpay-login.js +0 -95
- package/dist/coinpay-login.js.map +0 -1
package/README.md
CHANGED
|
@@ -451,6 +451,16 @@ or lands in History when you have unsaved edits. There is no `--wait`: a second
|
|
|
451
451
|
hands its files to the window already open and exits, so `readm3 edit` is not a
|
|
452
452
|
`core.editor` for git.
|
|
453
453
|
|
|
454
|
+
**Signing in** in the app is **Sign in with your browser** on the Account page: your
|
|
455
|
+
browser opens readm3.com, where your password manager and email are, you approve the
|
|
456
|
+
desktop app, and the app is signed in (OAuth with a loopback redirect, then one exchange
|
|
457
|
+
of that token for the window's session at `POST /oauth/desktop-session`). An emailed link
|
|
458
|
+
or CoinPay page inside the app would sign in the browser instead, so the app does not offer them.
|
|
459
|
+
|
|
460
|
+
**Open in app** on readm3.com/viewer opens the same page in the desktop app through a
|
|
461
|
+
`readm3://open?url=…` link the app registers (macOS, Windows, and Linux through the
|
|
462
|
+
installer's desktop entry). When nothing answers, the button becomes **Get the app**.
|
|
463
|
+
|
|
454
464
|
Files opened with "Open with" (Finder and Explorer included) go straight into the
|
|
455
465
|
editor. The window loads readm3.com, so sign-in, sync and sharing work as on the web;
|
|
456
466
|
a copy of the editor ships inside the app for a first launch with no connection. The
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ColorMode } from "./print.ts";
|
|
2
2
|
import { type ViewerOptions } from "./viewer.ts";
|
|
3
|
-
export declare const VERSION = "0.
|
|
3
|
+
export declare const VERSION = "0.15.0";
|
|
4
4
|
/** The help text, exported so a test can hold it to the flags it documents. */
|
|
5
5
|
export declare const USAGE: string;
|
|
6
6
|
export interface ParsedArgs extends ViewerOptions {
|
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { printDocument, COLOR_MODES } from "./print.js";
|
|
|
11
11
|
import { run } from "./viewer.js";
|
|
12
12
|
import { isCloudCommand, cloudMain, CLOUD_USAGE } from "./cloud-cli.js";
|
|
13
13
|
import { isDesktopCommand, desktopMain, installedDesktop, prefersDesktop, DESKTOP_USAGE } from "./desktop-cli.js";
|
|
14
|
-
export const VERSION = "0.
|
|
14
|
+
export const VERSION = "0.15.0";
|
|
15
15
|
/** The help text, exported so a test can hold it to the flags it documents. */
|
|
16
16
|
export const USAGE = `readm3 — a plain text editor for Markdown and code
|
|
17
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/readm3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Markdown editing and sharing for people and teams. Web/PWA, CLI, API and MCP with version history, view/edit links, and a terminal reader.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/dist/coinpay-login.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"coinpay-login.d.ts","sourceRoot":"","sources":["../src/coinpay-login.ts"],"names":[],"mappings":"AAUA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAuBnE,mFAAmF;AACnF,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA2EvE"}
|
package/dist/coinpay-login.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `readm3 login --coinpay`: an OAuth 2.1 authorization code grant with PKCE,
|
|
3
|
-
* started here and finished on a loopback redirect (CoinPay accepts any port on
|
|
4
|
-
* 127.0.0.1). The CLI never sees a client secret: it hands the code and its
|
|
5
|
-
* verifier to readm3, which makes the exchange and answers with an ordinary
|
|
6
|
-
* readm3 API token.
|
|
7
|
-
*/
|
|
8
|
-
import { spawn } from "node:child_process";
|
|
9
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
10
|
-
import { createServer } from "node:http";
|
|
11
|
-
import { cloudRequest } from "./cloud-client.js";
|
|
12
|
-
const WAIT_MS = 5 * 60_000;
|
|
13
|
-
function openBrowser(url) {
|
|
14
|
-
const [command, ...args] = process.platform === "darwin"
|
|
15
|
-
? ["open", url]
|
|
16
|
-
: process.platform === "win32"
|
|
17
|
-
? ["cmd", "/c", "start", "", url]
|
|
18
|
-
: ["xdg-open", url];
|
|
19
|
-
try {
|
|
20
|
-
const child = spawn(command, args, { stdio: "ignore", detached: true });
|
|
21
|
-
child.on("error", () => { });
|
|
22
|
-
child.unref();
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
/* The link is printed; opening it is a convenience. */
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const page = (message) => `<!doctype html><meta charset="utf-8"><title>readm3</title><p style="font:16px system-ui;margin:3em">${message}</p>`;
|
|
29
|
-
/** Returns a readm3 API token for the CoinPay account the person signs in with. */
|
|
30
|
-
export async function coinpayLogin(config) {
|
|
31
|
-
const anonymous = { ...config, token: undefined };
|
|
32
|
-
const status = await cloudRequest("coinpay/status", "GET", undefined, anonymous);
|
|
33
|
-
if (!status.enabled || !status.clientId || !status.coinpayUrl)
|
|
34
|
-
throw new Error("This readm3 server does not offer Sign in with CoinPay.");
|
|
35
|
-
const verifier = randomBytes(32).toString("base64url");
|
|
36
|
-
const state = randomBytes(24).toString("base64url");
|
|
37
|
-
const server = createServer();
|
|
38
|
-
await new Promise((resolve, reject) => {
|
|
39
|
-
server.once("error", reject);
|
|
40
|
-
server.listen(0, "127.0.0.1", resolve);
|
|
41
|
-
});
|
|
42
|
-
const port = server.address().port;
|
|
43
|
-
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
44
|
-
try {
|
|
45
|
-
const code = await new Promise((resolve, reject) => {
|
|
46
|
-
const timer = setTimeout(() => reject(new Error("Timed out waiting for CoinPay. Run readm3 login --coinpay again.")), WAIT_MS);
|
|
47
|
-
server.on("request", (request, response) => {
|
|
48
|
-
const url = new URL(request.url ?? "/", redirectUri);
|
|
49
|
-
if (url.pathname !== "/callback") {
|
|
50
|
-
response.writeHead(404).end();
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const finish = (ok, message) => {
|
|
54
|
-
response
|
|
55
|
-
.writeHead(ok ? 200 : 400, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" })
|
|
56
|
-
.end(page(message));
|
|
57
|
-
clearTimeout(timer);
|
|
58
|
-
};
|
|
59
|
-
if (url.searchParams.get("state") !== state) {
|
|
60
|
-
// Not ours: someone else's tab or a stale link. Keep waiting for the real one.
|
|
61
|
-
response.writeHead(400, { "content-type": "text/html; charset=utf-8" }).end(page("This sign-in link does not belong to the waiting readm3 CLI."));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const error = url.searchParams.get("error");
|
|
65
|
-
const code = url.searchParams.get("code");
|
|
66
|
-
if (error || !code) {
|
|
67
|
-
finish(false, "CoinPay sign-in did not complete. You can close this tab.");
|
|
68
|
-
reject(new Error(`CoinPay sign-in failed: ${url.searchParams.get("error_description") || error || "no code returned"}.`));
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
finish(true, "Signed in to readm3 with CoinPay. You can close this tab and return to the terminal.");
|
|
72
|
-
resolve(code);
|
|
73
|
-
});
|
|
74
|
-
const authorize = `${status.coinpayUrl}/api/oauth/authorize?${new URLSearchParams({
|
|
75
|
-
client_id: status.clientId,
|
|
76
|
-
redirect_uri: redirectUri,
|
|
77
|
-
response_type: "code",
|
|
78
|
-
scope: status.scopes || "openid profile email",
|
|
79
|
-
state,
|
|
80
|
-
code_challenge: createHash("sha256").update(verifier).digest("base64url"),
|
|
81
|
-
code_challenge_method: "S256",
|
|
82
|
-
})}`;
|
|
83
|
-
process.stderr.write(`Sign in with CoinPay in your browser. If it does not open, visit:\n${authorize}\n`);
|
|
84
|
-
if (!process.env.READM3_NO_BROWSER)
|
|
85
|
-
openBrowser(authorize);
|
|
86
|
-
});
|
|
87
|
-
const result = await cloudRequest("coinpay/oauth/cli-exchange", "POST", { code, code_verifier: verifier, redirect_uri: redirectUri }, anonymous);
|
|
88
|
-
return result.token;
|
|
89
|
-
}
|
|
90
|
-
finally {
|
|
91
|
-
server.closeAllConnections?.();
|
|
92
|
-
server.close();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
//# sourceMappingURL=coinpay-login.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"coinpay-login.js","sourceRoot":"","sources":["../src/coinpay-login.ts"],"names":[],"mappings":"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"}
|