@jamiexiongr/panda 0.0.0-fallback-test-2

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,40 @@
1
+ # @jamiexiongr/panda
2
+
3
+ Combined installer and CLI entry for Panda.
4
+
5
+ This package is intended for end users who want to run Panda on their own machine and open it from a phone over Tailscale.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js `>= 20.19.0`
10
+ - A desktop installation of Tailscale with CLI access
11
+ - Your computer and phone joined to the same tailnet
12
+ - Recommended mobile browsers:
13
+ iPhone / iPad with Safari 16.4+;
14
+ Android with a current Chrome stable release
15
+
16
+ For the complete Chinese install and usage guide in this repository, see `docs/panda-user-guide.md`.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install -g @jamiexiongr/panda@latest --registry=https://registry.npmjs.org/
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```bash
27
+ panda hub
28
+ panda hub tailscareserv
29
+
30
+ panda agent
31
+ panda agent tailscareserv
32
+ ```
33
+
34
+ `tailscareserv` and `--tailscale-serve` both enable automatic `tailscale serve` publishing.
35
+
36
+ ## Notes
37
+
38
+ - `panda hub tailscareserv` is the quickest path to a mobile-installable HTTPS PWA inside your tailnet.
39
+ - `panda agent tailscareserv` makes the agent register `https/wss` direct URLs when no explicit direct URL env vars are set.
40
+ - If `tailscale serve` says it is not enabled on your tailnet, open the approval link printed by the CLI and enable Serve for that node.
package/bin/panda.cjs ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import('../dist/cli.mjs')
package/dist/cli.mjs ADDED
@@ -0,0 +1,166 @@
1
+ // packages/provider-codex/src/tailscale.ts
2
+ import { execFileSync } from "child_process";
3
+ var ENABLED_ARGS = /* @__PURE__ */ new Set([
4
+ "tailscareserv",
5
+ "--tailscareserv",
6
+ "tailscale-serve",
7
+ "--tailscale-serve"
8
+ ]);
9
+ var PUBLIC_ARGS = /* @__PURE__ */ new Set([
10
+ "tailscareserv-pub",
11
+ "--tailscareserv-pub",
12
+ "tailscale-serve-pub",
13
+ "--tailscale-serve-pub",
14
+ "tailscalefunnel",
15
+ "--tailscalefunnel",
16
+ "tailscale-funnel",
17
+ "--tailscale-funnel"
18
+ ]);
19
+ var DISABLED_ARGS = /* @__PURE__ */ new Set([
20
+ "no-tailscareserv",
21
+ "--no-tailscareserv",
22
+ "no-tailscale-serve",
23
+ "--no-tailscale-serve",
24
+ "no-tailscareserv-pub",
25
+ "--no-tailscareserv-pub",
26
+ "no-tailscale-serve-pub",
27
+ "--no-tailscale-serve-pub",
28
+ "no-tailscalefunnel",
29
+ "--no-tailscalefunnel",
30
+ "no-tailscale-funnel",
31
+ "--no-tailscale-funnel"
32
+ ]);
33
+ var trimToNull = (value) => {
34
+ const normalized = value?.trim() ?? "";
35
+ return normalized ? normalized : null;
36
+ };
37
+ var parseBooleanLike = (value) => {
38
+ const normalized = trimToNull(value)?.toLowerCase();
39
+ if (!normalized) {
40
+ return null;
41
+ }
42
+ if (["1", "true", "yes", "on"].includes(normalized)) {
43
+ return true;
44
+ }
45
+ if (["0", "false", "no", "off"].includes(normalized)) {
46
+ return false;
47
+ }
48
+ return null;
49
+ };
50
+ var parsePublicationModeLike = (value) => {
51
+ const normalized = trimToNull(value)?.toLowerCase();
52
+ if (!normalized) {
53
+ return null;
54
+ }
55
+ if (["serve", "private", "tailnet"].includes(normalized)) {
56
+ return "serve";
57
+ }
58
+ if (["funnel", "public", "pub"].includes(normalized)) {
59
+ return "funnel";
60
+ }
61
+ if (["disabled", "none", "off"].includes(normalized)) {
62
+ return "disabled";
63
+ }
64
+ return null;
65
+ };
66
+ var resolveTailscalePublicationMode = (options) => {
67
+ const argv = options?.argv ?? [];
68
+ for (const candidate of argv) {
69
+ const normalized = candidate.trim().toLowerCase();
70
+ if (PUBLIC_ARGS.has(normalized)) {
71
+ return "funnel";
72
+ }
73
+ if (ENABLED_ARGS.has(normalized)) {
74
+ return "serve";
75
+ }
76
+ if (DISABLED_ARGS.has(normalized)) {
77
+ return "disabled";
78
+ }
79
+ }
80
+ const env = options?.env ?? process.env;
81
+ const scopedMode = options?.envPrefix ? parsePublicationModeLike(env[`${options.envPrefix}_TAILSCALE_PUBLISH_MODE`]) : null;
82
+ if (scopedMode) {
83
+ return scopedMode;
84
+ }
85
+ const genericMode = parsePublicationModeLike(env.PANDA_TAILSCALE_PUBLISH_MODE);
86
+ if (genericMode) {
87
+ return genericMode;
88
+ }
89
+ const scopedEnabled = options?.envPrefix ? parseBooleanLike(env[`${options.envPrefix}_TAILSCALE_SERVE`]) : null;
90
+ if (scopedEnabled !== null) {
91
+ return scopedEnabled ? "serve" : "disabled";
92
+ }
93
+ const envEnabled = parseBooleanLike(env.PANDA_TAILSCALE_SERVE);
94
+ if (envEnabled !== null) {
95
+ return envEnabled ? "serve" : "disabled";
96
+ }
97
+ return "disabled";
98
+ };
99
+
100
+ // release/panda/src/cli.ts
101
+ var printUsage = () => {
102
+ console.log(`panda <command>
103
+
104
+ Commands:
105
+ agent [tailscareserv|tailscareserv-pub] [--hub-url=<url>] Start the Panda agent service
106
+ hub [tailscareserv|tailscareserv-pub] Start the Panda hub service with the bundled web UI
107
+ help Show this message`);
108
+ };
109
+ var resolveCliOptionValue = (argv, aliases) => {
110
+ for (let index = 0; index < argv.length; index += 1) {
111
+ const candidate = argv[index]?.trim() ?? "";
112
+ const normalized = candidate.toLowerCase();
113
+ for (const alias of aliases) {
114
+ if (normalized === alias) {
115
+ return argv[index + 1]?.trim() || null;
116
+ }
117
+ if (normalized.startsWith(`${alias}=`)) {
118
+ return candidate.slice(alias.length + 1).trim() || null;
119
+ }
120
+ }
121
+ }
122
+ return null;
123
+ };
124
+ var main = async () => {
125
+ const command = process.argv[2]?.trim().toLowerCase() ?? "help";
126
+ const commandArgs = process.argv.slice(3);
127
+ const agentPublicationMode = resolveTailscalePublicationMode({
128
+ argv: commandArgs,
129
+ envPrefix: "PANDA_AGENT"
130
+ });
131
+ const hubPublicationMode = resolveTailscalePublicationMode({
132
+ argv: commandArgs,
133
+ envPrefix: "PANDA_HUB"
134
+ });
135
+ if (command === "help" || command === "--help" || command === "-h") {
136
+ printUsage();
137
+ return;
138
+ }
139
+ if (command === "agent") {
140
+ const { startJamiexiongrAgent } = await import("@jamiexiongr/panda-agent");
141
+ await startJamiexiongrAgent({
142
+ tailscalePublicationMode: agentPublicationMode,
143
+ hubUrl: resolveCliOptionValue(commandArgs, [
144
+ "hub",
145
+ "--hub",
146
+ "hub-url",
147
+ "--hub-url",
148
+ "huburl",
149
+ "--huburl"
150
+ ]),
151
+ argv: commandArgs
152
+ });
153
+ return;
154
+ }
155
+ if (command === "hub") {
156
+ const { startJamiexiongrHub } = await import("@jamiexiongr/panda-hub");
157
+ await startJamiexiongrHub({
158
+ tailscalePublicationMode: hubPublicationMode
159
+ });
160
+ return;
161
+ }
162
+ console.error(`Unknown command: ${command}`);
163
+ printUsage();
164
+ process.exitCode = 1;
165
+ };
166
+ void main();
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@jamiexiongr/panda",
3
+ "version": "0.0.0-fallback-test-2",
4
+ "type": "module",
5
+ "private": false,
6
+ "description": "Panda combined installer",
7
+ "bin": {
8
+ "panda": "./bin/panda.cjs"
9
+ },
10
+ "dependencies": {
11
+ "@jamiexiongr/panda-agent": "0.0.0-fallback-test-2",
12
+ "@jamiexiongr/panda-hub": "0.0.0-fallback-test-2"
13
+ },
14
+ "files": [
15
+ "bin",
16
+ "dist"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public",
20
+ "registry": "https://registry.npmjs.org/"
21
+ },
22
+ "engines": {
23
+ "node": ">=20.19.0"
24
+ }
25
+ }