remobi 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,40 @@
1
+ # [0.2.0](https://github.com/connorads/remobi/compare/v0.1.0...v0.2.0) (2026-03-15)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **ci:** add npm to mise.toml for OIDC trusted publishing ([44bb745](https://github.com/connorads/remobi/commit/44bb7452d0d9e3496bacc4aaf5a63f2236a8f80f))
7
+ * exclude package.json from Biome formatter ([044183f](https://github.com/connorads/remobi/commit/044183fd636fe56eb17f1cd650338c85be46ce5e))
8
+ * remove leading ./ from bin path for npm 11 compatibility ([33ba38d](https://github.com/connorads/remobi/commit/33ba38daab05224fc6eeb28402bb9860c36873d2))
9
+ * remove redundant checks from prepublishOnly ([efdb742](https://github.com/connorads/remobi/commit/efdb742087842ba131ed704e3e29676aa672ab87))
10
+
11
+
12
+ ### Features
13
+
14
+ * add pixel R> logo and integrate across project ([44b238a](https://github.com/connorads/remobi/commit/44b238aa7909cec2c408acb5bde32f9f2c645e26))
15
+
16
+ ## [0.2.2](https://github.com/connorads/remobi/compare/v0.2.1...v0.2.2) (2026-03-15)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * **ci:** add npm to mise.toml for OIDC trusted publishing ([44bb745](https://github.com/connorads/remobi/commit/44bb7452d0d9e3496bacc4aaf5a63f2236a8f80f))
22
+
23
+ ## [0.2.1](https://github.com/connorads/remobi/compare/v0.2.0...v0.2.1) (2026-03-15)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * exclude package.json from Biome formatter ([044183f](https://github.com/connorads/remobi/commit/044183fd636fe56eb17f1cd650338c85be46ce5e))
29
+ * remove redundant checks from prepublishOnly ([efdb742](https://github.com/connorads/remobi/commit/efdb742087842ba131ed704e3e29676aa672ab87))
30
+
31
+ # [0.2.0](https://github.com/connorads/remobi/compare/v0.1.0...v0.2.0) (2026-03-15)
32
+
33
+
34
+ ### Features
35
+
36
+ * add pixel R> logo and integrate across project ([44b238a](https://github.com/connorads/remobi/commit/44b238aa7909cec2c408acb5bde32f9f2c645e26))
37
+
1
38
  # Changelog
2
39
 
3
40
  ## 0.1.0 — 2026-03-15
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ <div align="center">
2
+ <img src="logo/logo.svg" width="128" alt="remobi logo"/>
3
+ </div>
4
+
1
5
  # remobi
2
6
 
3
7
  [![CI](https://github.com/connorads/remobi/actions/workflows/ci.yml/badge.svg)](https://github.com/connorads/remobi/actions/workflows/ci.yml)
package/dist/build.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as generatePwaHtml, n as sleep, r as spawnProcess, t as readStdin } from "./node-compat-BzXgbTV9.mjs";
1
+ import { i as generatePwaHtml, n as sleep, r as spawnProcess, t as readStdin } from "./node-compat-CqwRIRV_.mjs";
2
2
  import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { dirname, resolve } from "node:path";
4
4
 
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as sleep, r as spawnProcess, t as readStdin } from "./node-compat-BzXgbTV9.mjs";
2
+ import { n as sleep, r as spawnProcess, t as readStdin } from "./node-compat-CqwRIRV_.mjs";
3
3
  import { build, bundleOverlay, injectFromStdin, injectOverlay } from "./build.mjs";
4
4
  import { defaultConfig, defineConfig, mergeConfig, serialiseThemeForTtyd } from "./src/config.mjs";
5
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -3,14 +3,39 @@ import { spawn } from "node:child_process";
3
3
  //#region src/pwa/icon.ts
4
4
  /**
5
5
  * SVG icon for remobi PWA.
6
- * Dark rounded-rect background (#1e1e2e catppuccin mocha base),
7
- * green chevron () in #a6e3a1 (catppuccin green),
8
- * underscore cursor in #89b4fa (catppuccin blue).
6
+ * Pixel-art R> on catppuccin mocha base (#1e1e2e).
7
+ * Green R (#a6e3a1), blue chevron (#89b4fa).
8
+ * Uses <rect> elements renders identically on all platforms.
9
9
  */
10
10
  const ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
11
- <rect width="512" height="512" rx="80" ry="80" fill="#1e1e2e"/>
12
- <text x="100" y="330" font-family="monospace" font-size="260" font-weight="bold" fill="#a6e3a1">›</text>
13
- <text x="195" y="400" font-family="monospace" font-size="140" font-weight="bold" fill="#89b4fa">_</text>
11
+ <rect width="512" height="512" rx="80" fill="#1e1e2e"/>
12
+ <g fill="#a6e3a1">
13
+ <rect x="76" y="130" width="28" height="28" rx="4"/>
14
+ <rect x="112" y="130" width="28" height="28" rx="4"/>
15
+ <rect x="148" y="130" width="28" height="28" rx="4"/>
16
+ <rect x="184" y="130" width="28" height="28" rx="4"/>
17
+ <rect x="76" y="166" width="28" height="28" rx="4"/>
18
+ <rect x="220" y="166" width="28" height="28" rx="4"/>
19
+ <rect x="76" y="202" width="28" height="28" rx="4"/>
20
+ <rect x="220" y="202" width="28" height="28" rx="4"/>
21
+ <rect x="76" y="238" width="28" height="28" rx="4"/>
22
+ <rect x="112" y="238" width="28" height="28" rx="4"/>
23
+ <rect x="148" y="238" width="28" height="28" rx="4"/>
24
+ <rect x="184" y="238" width="28" height="28" rx="4"/>
25
+ <rect x="76" y="274" width="28" height="28" rx="4"/>
26
+ <rect x="148" y="274" width="28" height="28" rx="4"/>
27
+ <rect x="76" y="310" width="28" height="28" rx="4"/>
28
+ <rect x="184" y="310" width="28" height="28" rx="4"/>
29
+ <rect x="76" y="346" width="28" height="28" rx="4"/>
30
+ <rect x="220" y="346" width="28" height="28" rx="4"/>
31
+ </g>
32
+ <g fill="#89b4fa">
33
+ <rect x="328" y="166" width="28" height="28" rx="4"/>
34
+ <rect x="364" y="202" width="28" height="28" rx="4"/>
35
+ <rect x="400" y="238" width="28" height="28" rx="4"/>
36
+ <rect x="364" y="274" width="28" height="28" rx="4"/>
37
+ <rect x="328" y="310" width="28" height="28" rx="4"/>
38
+ </g>
14
39
  </svg>`;
15
40
  /** Convert SVG string to a data URI */
16
41
  function svgToDataUri(svg) {
@@ -80,4 +105,4 @@ function spawnProcess(cmd, opts) {
80
105
 
81
106
  //#endregion
82
107
  export { generatePwaHtml as i, sleep as n, spawnProcess as r, readStdin as t };
83
- //# sourceMappingURL=node-compat-BzXgbTV9.mjs.map
108
+ //# sourceMappingURL=node-compat-CqwRIRV_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-compat-CqwRIRV_.mjs","names":["nodeSpawn"],"sources":["../src/pwa/icon.ts","../src/pwa/meta-tags.ts","../src/util/node-compat.ts"],"sourcesContent":["/**\n * SVG icon for remobi PWA.\n * Pixel-art R> on catppuccin mocha base (#1e1e2e).\n * Green R (#a6e3a1), blue chevron (#89b4fa).\n * Uses <rect> elements — renders identically on all platforms.\n */\nexport const ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <rect width=\"512\" height=\"512\" rx=\"80\" fill=\"#1e1e2e\"/>\n <g fill=\"#a6e3a1\">\n <rect x=\"76\" y=\"130\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"112\" y=\"130\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"148\" y=\"130\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"184\" y=\"130\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"76\" y=\"166\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"220\" y=\"166\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"76\" y=\"202\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"220\" y=\"202\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"76\" y=\"238\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"112\" y=\"238\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"148\" y=\"238\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"184\" y=\"238\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"76\" y=\"274\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"148\" y=\"274\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"76\" y=\"310\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"184\" y=\"310\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"76\" y=\"346\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"220\" y=\"346\" width=\"28\" height=\"28\" rx=\"4\"/>\n </g>\n <g fill=\"#89b4fa\">\n <rect x=\"328\" y=\"166\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"364\" y=\"202\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"400\" y=\"238\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"364\" y=\"274\" width=\"28\" height=\"28\" rx=\"4\"/>\n <rect x=\"328\" y=\"310\" width=\"28\" height=\"28\" rx=\"4\"/>\n </g>\n</svg>`\n\n/** Convert SVG string to a data URI */\nexport function svgToDataUri(svg: string): string {\n\treturn `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`\n}\n","import type { PwaConfig } from '../types'\nimport { ICON_SVG, svgToDataUri } from './icon'\n\n/** Escape a string for safe use in HTML attribute values */\nexport function escapeAttr(value: string): string {\n\treturn value\n\t\t.replace(/&/g, '&amp;')\n\t\t.replace(/\"/g, '&quot;')\n\t\t.replace(/</g, '&lt;')\n\t\t.replace(/>/g, '&gt;')\n}\n\n/** Generate PWA HTML to inject into </head> */\nexport function generatePwaHtml(name: string, pwa: PwaConfig): string {\n\tconst svgDataUri = svgToDataUri(ICON_SVG)\n\treturn [\n\t\t`<link rel=\"manifest\" href=\"/manifest.json\">`,\n\t\t`<meta name=\"theme-color\" content=\"${escapeAttr(pwa.themeColor)}\">`,\n\t\t`<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">`,\n\t\t`<meta name=\"apple-mobile-web-app-title\" content=\"${escapeAttr(name)}\">`,\n\t\t`<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">`,\n\t\t`<link rel=\"icon\" type=\"image/svg+xml\" href=\"${svgDataUri}\">`,\n\t].join('\\n')\n}\n","import { spawn as nodeSpawn } from 'node:child_process'\nimport type { Readable } from 'node:stream'\n\nexport const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms))\n\nexport async function readStdin(): Promise<string> {\n\tconst chunks: Buffer[] = []\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(Buffer.from(chunk))\n\t}\n\treturn Buffer.concat(chunks).toString('utf-8')\n}\n\nexport interface SpawnedProcess {\n\treadonly pid: number | undefined\n\treadonly stdout: Readable | null\n\treadonly stderr: Readable | null\n\treadonly stdin: NodeJS.WritableStream | null\n\tkill(signal?: NodeJS.Signals): boolean\n\treadonly exited: Promise<number>\n}\n\nexport function spawnProcess(\n\tcmd: readonly string[],\n\topts?: {\n\t\tcwd?: string\n\t\tstdin?: 'ignore' | 'pipe'\n\t\tstdout?: 'ignore' | 'pipe'\n\t\tstderr?: 'ignore' | 'pipe'\n\t},\n): SpawnedProcess {\n\tconst [command, ...args] = cmd\n\tif (!command) throw new Error('spawnProcess requires at least one argument')\n\n\tconst proc = nodeSpawn(command, args, {\n\t\tcwd: opts?.cwd,\n\t\tstdio: [opts?.stdin ?? 'ignore', opts?.stdout ?? 'ignore', opts?.stderr ?? 'ignore'],\n\t})\n\n\tconst exited = new Promise<number>((resolve, reject) => {\n\t\tproc.on('close', (code) => resolve(code ?? 1))\n\t\tproc.on('error', reject)\n\t})\n\n\treturn {\n\t\tget pid() {\n\t\t\treturn proc.pid\n\t\t},\n\t\tget stdout() {\n\t\t\treturn proc.stdout\n\t\t},\n\t\tget stderr() {\n\t\t\treturn proc.stderr\n\t\t},\n\t\tget stdin() {\n\t\t\treturn proc.stdin\n\t\t},\n\t\tkill(signal?: NodeJS.Signals) {\n\t\t\treturn proc.kill(signal)\n\t\t},\n\t\texited,\n\t}\n}\n\nexport async function collectStream(stream: Readable | null): Promise<string> {\n\tif (!stream) return ''\n\tconst chunks: Buffer[] = []\n\tfor await (const chunk of stream) {\n\t\tchunks.push(Buffer.from(chunk))\n\t}\n\treturn Buffer.concat(chunks).toString('utf-8')\n}\n"],"mappings":";;;;;;;;;AAMA,MAAa,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCxB,SAAgB,aAAa,KAAqB;AACjD,QAAO,6BAA6B,OAAO,KAAK,IAAI,CAAC,SAAS,SAAS;;;;;;ACnCxE,SAAgB,WAAW,OAAuB;AACjD,QAAO,MACL,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO;;;AAIxB,SAAgB,gBAAgB,MAAc,KAAwB;CACrE,MAAM,aAAa,aAAa,SAAS;AACzC,QAAO;EACN;EACA,qCAAqC,WAAW,IAAI,WAAW,CAAC;EAChE;EACA,oDAAoD,WAAW,KAAK,CAAC;EACrE;EACA,+CAA+C,WAAW;EAC1D,CAAC,KAAK,KAAK;;;;;ACnBb,MAAa,SAAS,OAA8B,IAAI,SAAS,MAAM,WAAW,GAAG,GAAG,CAAC;AAEzF,eAAsB,YAA6B;CAClD,MAAM,SAAmB,EAAE;AAC3B,YAAW,MAAM,SAAS,QAAQ,MACjC,QAAO,KAAK,OAAO,KAAK,MAAM,CAAC;AAEhC,QAAO,OAAO,OAAO,OAAO,CAAC,SAAS,QAAQ;;AAY/C,SAAgB,aACf,KACA,MAMiB;CACjB,MAAM,CAAC,SAAS,GAAG,QAAQ;AAC3B,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,8CAA8C;CAE5E,MAAM,OAAOA,MAAU,SAAS,MAAM;EACrC,KAAK,MAAM;EACX,OAAO;GAAC,MAAM,SAAS;GAAU,MAAM,UAAU;GAAU,MAAM,UAAU;GAAS;EACpF,CAAC;AAOF,QAAO;EACN,IAAI,MAAM;AACT,UAAO,KAAK;;EAEb,IAAI,SAAS;AACZ,UAAO,KAAK;;EAEb,IAAI,SAAS;AACZ,UAAO,KAAK;;EAEb,IAAI,QAAQ;AACX,UAAO,KAAK;;EAEb,KAAK,QAAyB;AAC7B,UAAO,KAAK,KAAK,OAAO;;EAEzB,QArBc,IAAI,SAAiB,SAAS,WAAW;AACvD,QAAK,GAAG,UAAU,SAAS,QAAQ,QAAQ,EAAE,CAAC;AAC9C,QAAK,GAAG,SAAS,OAAO;IACvB;EAmBD"}
package/package.json CHANGED
@@ -1,88 +1,102 @@
1
1
  {
2
- "name": "remobi",
3
- "version": "0.1.0",
4
- "description": "Monitor and control your coding agents from your phone. Touch controls for tmux over the web.",
5
- "type": "module",
6
- "bin": {
7
- "remobi": "./dist/cli.mjs"
8
- },
9
- "exports": {
10
- ".": {
11
- "types": "./dist/src/index.d.mts",
12
- "default": "./dist/src/index.mjs"
13
- },
14
- "./config": {
15
- "types": "./dist/src/config.d.mts",
16
- "default": "./dist/src/config.mjs"
17
- },
18
- "./types": {
19
- "types": "./dist/src/types.d.mts"
20
- }
21
- },
22
- "files": [
23
- "dist/",
24
- "styles/",
25
- "src/pwa/icons/",
26
- "README.md",
27
- "CHANGELOG.md",
28
- "LICENSE"
29
- ],
30
- "engines": {
31
- "node": ">=22.0.0"
32
- },
33
- "repository": {
34
- "type": "git",
35
- "url": "git+https://github.com/connorads/remobi.git"
36
- },
37
- "homepage": "https://github.com/connorads/remobi",
38
- "bugs": "https://github.com/connorads/remobi/issues",
39
- "devDependencies": {
40
- "@biomejs/biome": "^1.9.0",
41
- "esbuild": "^0.25.0",
42
- "@happy-dom/global-registrator": "^20.6.1",
43
- "@types/node": "^22.0.0",
44
- "@types/ws": "^8.18.0",
45
- "knip": "^5.85.0",
46
- "oxlint": "^1.50.0",
47
- "publint": "^0.3.17",
48
- "tsdown": "^0.20.0",
49
- "tsx": "^4.19.0",
50
- "typescript": "^5.9.3",
51
- "vitest": "^3.0.0"
52
- },
53
- "license": "MIT",
54
- "author": "Connor",
55
- "keywords": [
56
- "ttyd",
57
- "tmux",
58
- "terminal",
59
- "mobile",
60
- "overlay",
61
- "touch",
62
- "node",
63
- "agents",
64
- "claude",
65
- "remote",
66
- "pwa"
67
- ],
68
- "dependencies": {
69
- "@hono/node-server": "^1.14.0",
70
- "@hono/node-ws": "^1.1.0",
71
- "hono": "^4.7.0",
72
- "valibot": "^1.2.0",
73
- "ws": "^8.18.0"
74
- },
75
- "scripts": {
76
- "build:overlay": "tsx scripts/build-overlay.ts",
77
- "build:dist": "tsdown && pnpm run build:overlay",
78
- "build": "tsx cli.ts build",
79
- "check": "biome check .",
80
- "check:fix": "biome check --fix .",
81
- "lint:knip": "knip",
82
- "lint:ox": "oxlint --import-plugin --promise-plugin",
83
- "lint:publint": "publint",
84
- "lint:typos": "typos",
85
- "test": "vitest run",
86
- "test:coverage": "vitest run --coverage"
87
- }
88
- }
2
+ "name": "remobi",
3
+ "version": "0.2.0",
4
+ "description": "Monitor and control your coding agents from your phone. Touch controls for tmux over the web.",
5
+ "type": "module",
6
+ "bin": {
7
+ "remobi": "dist/cli.mjs"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/src/index.d.mts",
12
+ "default": "./dist/src/index.mjs"
13
+ },
14
+ "./config": {
15
+ "types": "./dist/src/config.d.mts",
16
+ "default": "./dist/src/config.mjs"
17
+ },
18
+ "./types": {
19
+ "types": "./dist/src/types.d.mts"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist/",
24
+ "styles/",
25
+ "src/pwa/icons/",
26
+ "README.md",
27
+ "CHANGELOG.md",
28
+ "LICENSE"
29
+ ],
30
+ "publishConfig": {
31
+ "provenance": true
32
+ },
33
+ "engines": {
34
+ "node": ">=22.0.0"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/connorads/remobi.git"
39
+ },
40
+ "homepage": "https://github.com/connorads/remobi",
41
+ "bugs": "https://github.com/connorads/remobi/issues",
42
+ "scripts": {
43
+ "build:overlay": "tsx scripts/build-overlay.ts",
44
+ "build:dist": "tsdown && pnpm run build:overlay",
45
+ "build": "tsx cli.ts build",
46
+ "check": "biome check .",
47
+ "check:fix": "biome check --fix .",
48
+ "lint:knip": "knip",
49
+ "lint:ox": "oxlint --import-plugin --promise-plugin",
50
+ "lint:publint": "publint",
51
+ "lint:typos": "typos",
52
+ "test": "vitest run",
53
+ "test:coverage": "vitest run --coverage",
54
+ "release": "semantic-release",
55
+ "prepublishOnly": "pnpm run lint:ox && pnpm run lint:knip && pnpm run build:dist && pnpm run lint:publint"
56
+ },
57
+ "devDependencies": {
58
+ "@biomejs/biome": "^1.9.0",
59
+ "@happy-dom/global-registrator": "^20.6.1",
60
+ "@semantic-release/changelog": "^6.0.3",
61
+ "@semantic-release/git": "^10.0.1",
62
+ "@types/node": "^22.0.0",
63
+ "@types/ws": "^8.18.0",
64
+ "esbuild": "^0.25.0",
65
+ "knip": "^5.85.0",
66
+ "oxlint": "^1.50.0",
67
+ "publint": "^0.3.17",
68
+ "semantic-release": "^25.0.3",
69
+ "tsdown": "^0.20.0",
70
+ "tsx": "^4.19.0",
71
+ "typescript": "^5.9.3",
72
+ "vitest": "^3.0.0"
73
+ },
74
+ "license": "MIT",
75
+ "author": "Connor",
76
+ "keywords": [
77
+ "ttyd",
78
+ "tmux",
79
+ "terminal",
80
+ "mobile",
81
+ "overlay",
82
+ "touch",
83
+ "node",
84
+ "agents",
85
+ "claude",
86
+ "remote",
87
+ "pwa"
88
+ ],
89
+ "dependencies": {
90
+ "@hono/node-server": "^1.14.0",
91
+ "@hono/node-ws": "^1.1.0",
92
+ "hono": "^4.7.0",
93
+ "valibot": "^1.2.0",
94
+ "ws": "^8.18.0"
95
+ },
96
+ "pnpm": {
97
+ "onlyBuiltDependencies": [
98
+ "@biomejs/biome",
99
+ "esbuild"
100
+ ]
101
+ }
102
+ }
Binary file
Binary file
Binary file
@@ -1 +0,0 @@
1
- {"version":3,"file":"node-compat-BzXgbTV9.mjs","names":["nodeSpawn"],"sources":["../src/pwa/icon.ts","../src/pwa/meta-tags.ts","../src/util/node-compat.ts"],"sourcesContent":["/**\n * SVG icon for remobi PWA.\n * Dark rounded-rect background (#1e1e2e catppuccin mocha base),\n * green chevron (›) in #a6e3a1 (catppuccin green),\n * underscore cursor in #89b4fa (catppuccin blue).\n */\nexport const ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <rect width=\"512\" height=\"512\" rx=\"80\" ry=\"80\" fill=\"#1e1e2e\"/>\n <text x=\"100\" y=\"330\" font-family=\"monospace\" font-size=\"260\" font-weight=\"bold\" fill=\"#a6e3a1\">›</text>\n <text x=\"195\" y=\"400\" font-family=\"monospace\" font-size=\"140\" font-weight=\"bold\" fill=\"#89b4fa\">_</text>\n</svg>`\n\n/** Convert SVG string to a data URI */\nexport function svgToDataUri(svg: string): string {\n\treturn `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`\n}\n","import type { PwaConfig } from '../types'\nimport { ICON_SVG, svgToDataUri } from './icon'\n\n/** Escape a string for safe use in HTML attribute values */\nexport function escapeAttr(value: string): string {\n\treturn value\n\t\t.replace(/&/g, '&amp;')\n\t\t.replace(/\"/g, '&quot;')\n\t\t.replace(/</g, '&lt;')\n\t\t.replace(/>/g, '&gt;')\n}\n\n/** Generate PWA HTML to inject into </head> */\nexport function generatePwaHtml(name: string, pwa: PwaConfig): string {\n\tconst svgDataUri = svgToDataUri(ICON_SVG)\n\treturn [\n\t\t`<link rel=\"manifest\" href=\"/manifest.json\">`,\n\t\t`<meta name=\"theme-color\" content=\"${escapeAttr(pwa.themeColor)}\">`,\n\t\t`<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">`,\n\t\t`<meta name=\"apple-mobile-web-app-title\" content=\"${escapeAttr(name)}\">`,\n\t\t`<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">`,\n\t\t`<link rel=\"icon\" type=\"image/svg+xml\" href=\"${svgDataUri}\">`,\n\t].join('\\n')\n}\n","import { spawn as nodeSpawn } from 'node:child_process'\nimport type { Readable } from 'node:stream'\n\nexport const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms))\n\nexport async function readStdin(): Promise<string> {\n\tconst chunks: Buffer[] = []\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(Buffer.from(chunk))\n\t}\n\treturn Buffer.concat(chunks).toString('utf-8')\n}\n\nexport interface SpawnedProcess {\n\treadonly pid: number | undefined\n\treadonly stdout: Readable | null\n\treadonly stderr: Readable | null\n\treadonly stdin: NodeJS.WritableStream | null\n\tkill(signal?: NodeJS.Signals): boolean\n\treadonly exited: Promise<number>\n}\n\nexport function spawnProcess(\n\tcmd: readonly string[],\n\topts?: {\n\t\tcwd?: string\n\t\tstdin?: 'ignore' | 'pipe'\n\t\tstdout?: 'ignore' | 'pipe'\n\t\tstderr?: 'ignore' | 'pipe'\n\t},\n): SpawnedProcess {\n\tconst [command, ...args] = cmd\n\tif (!command) throw new Error('spawnProcess requires at least one argument')\n\n\tconst proc = nodeSpawn(command, args, {\n\t\tcwd: opts?.cwd,\n\t\tstdio: [opts?.stdin ?? 'ignore', opts?.stdout ?? 'ignore', opts?.stderr ?? 'ignore'],\n\t})\n\n\tconst exited = new Promise<number>((resolve, reject) => {\n\t\tproc.on('close', (code) => resolve(code ?? 1))\n\t\tproc.on('error', reject)\n\t})\n\n\treturn {\n\t\tget pid() {\n\t\t\treturn proc.pid\n\t\t},\n\t\tget stdout() {\n\t\t\treturn proc.stdout\n\t\t},\n\t\tget stderr() {\n\t\t\treturn proc.stderr\n\t\t},\n\t\tget stdin() {\n\t\t\treturn proc.stdin\n\t\t},\n\t\tkill(signal?: NodeJS.Signals) {\n\t\t\treturn proc.kill(signal)\n\t\t},\n\t\texited,\n\t}\n}\n\nexport async function collectStream(stream: Readable | null): Promise<string> {\n\tif (!stream) return ''\n\tconst chunks: Buffer[] = []\n\tfor await (const chunk of stream) {\n\t\tchunks.push(Buffer.from(chunk))\n\t}\n\treturn Buffer.concat(chunks).toString('utf-8')\n}\n"],"mappings":";;;;;;;;;AAMA,MAAa,WAAW;;;;;;AAOxB,SAAgB,aAAa,KAAqB;AACjD,QAAO,6BAA6B,OAAO,KAAK,IAAI,CAAC,SAAS,SAAS;;;;;;ACVxE,SAAgB,WAAW,OAAuB;AACjD,QAAO,MACL,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO;;;AAIxB,SAAgB,gBAAgB,MAAc,KAAwB;CACrE,MAAM,aAAa,aAAa,SAAS;AACzC,QAAO;EACN;EACA,qCAAqC,WAAW,IAAI,WAAW,CAAC;EAChE;EACA,oDAAoD,WAAW,KAAK,CAAC;EACrE;EACA,+CAA+C,WAAW;EAC1D,CAAC,KAAK,KAAK;;;;;ACnBb,MAAa,SAAS,OAA8B,IAAI,SAAS,MAAM,WAAW,GAAG,GAAG,CAAC;AAEzF,eAAsB,YAA6B;CAClD,MAAM,SAAmB,EAAE;AAC3B,YAAW,MAAM,SAAS,QAAQ,MACjC,QAAO,KAAK,OAAO,KAAK,MAAM,CAAC;AAEhC,QAAO,OAAO,OAAO,OAAO,CAAC,SAAS,QAAQ;;AAY/C,SAAgB,aACf,KACA,MAMiB;CACjB,MAAM,CAAC,SAAS,GAAG,QAAQ;AAC3B,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,8CAA8C;CAE5E,MAAM,OAAOA,MAAU,SAAS,MAAM;EACrC,KAAK,MAAM;EACX,OAAO;GAAC,MAAM,SAAS;GAAU,MAAM,UAAU;GAAU,MAAM,UAAU;GAAS;EACpF,CAAC;AAOF,QAAO;EACN,IAAI,MAAM;AACT,UAAO,KAAK;;EAEb,IAAI,SAAS;AACZ,UAAO,KAAK;;EAEb,IAAI,SAAS;AACZ,UAAO,KAAK;;EAEb,IAAI,QAAQ;AACX,UAAO,KAAK;;EAEb,KAAK,QAAyB;AAC7B,UAAO,KAAK,KAAK,OAAO;;EAEzB,QArBc,IAAI,SAAiB,SAAS,WAAW;AACvD,QAAK,GAAG,UAAU,SAAS,QAAQ,QAAQ,EAAE,CAAC;AAC9C,QAAK,GAAG,SAAS,OAAO;IACvB;EAmBD"}