create-op-node 0.10.12 → 0.10.13

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/dist/cli.js CHANGED
@@ -12,18 +12,38 @@ import { readFileSync } from 'fs';
12
12
  import * as tls from 'tls';
13
13
  import { Validator } from '@cfworker/json-schema';
14
14
 
15
+ // src/lib/constants.ts
16
+ var PGSODIUM_KEY_RE = /^[a-f0-9]{64}$/;
17
+ var TUNNEL_TOKEN_RE = /^[A-Za-z0-9_\-.=]+$/;
18
+ var SAFE_PATH_RE = /^[A-Za-z0-9_\-./ ]+$/;
19
+ var SAFE_LAUNCHCTL_VALUE_RE = /^[A-Za-z0-9+/=._-]+$/;
20
+ var URL_SAFE_PASSWORD_RE = /^[A-Za-z0-9_-]+$/;
21
+ var SAFE_URL_RE = /^[A-Za-z0-9:/_.-]+$/;
22
+ var VERIFY_NETWORK_TIMEOUT_MS = 1e4;
23
+ var API_REQUEST_TIMEOUT_MS = 15e3;
24
+ var BODY_PREVIEW_MAX = 200;
25
+
15
26
  // src/lib/cloudflare.ts
16
27
  var CF_API = "https://api.cloudflare.com/client/v4";
17
28
  async function get(token, path, fetchImpl = fetch) {
18
- const res = await fetchImpl(`${CF_API}${path}`, {
19
- headers: { Authorization: `Bearer ${token}` }
20
- });
21
- let body = null;
29
+ const ctrl = new AbortController();
30
+ const timer = setTimeout(() => ctrl.abort(), API_REQUEST_TIMEOUT_MS);
22
31
  try {
23
- body = await res.json();
32
+ const res = await fetchImpl(`${CF_API}${path}`, {
33
+ headers: { Authorization: `Bearer ${token}` },
34
+ signal: ctrl.signal
35
+ });
36
+ let body = null;
37
+ try {
38
+ body = await res.json();
39
+ } catch {
40
+ }
41
+ return { status: res.status, body };
24
42
  } catch {
43
+ return { status: 0, body: null };
44
+ } finally {
45
+ clearTimeout(timer);
25
46
  }
26
- return { status: res.status, body };
27
47
  }
28
48
  function shortError(body) {
29
49
  if (typeof body === "object" && body !== null && "errors" in body && Array.isArray(body.errors)) {
@@ -38,6 +58,12 @@ function shortError(body) {
38
58
  async function probeCloudflareToken(input) {
39
59
  const issues = [];
40
60
  const verify = await get(input.token, `/accounts/${input.accountId}/tokens/verify`);
61
+ if (verify.status === 0) {
62
+ issues.push(
63
+ "Couldn't reach Cloudflare (network error or timeout). Check your connection and retry."
64
+ );
65
+ return { ok: false, issues };
66
+ }
41
67
  if (verify.status !== 200) {
42
68
  issues.push(
43
69
  `Token verify failed (HTTP ${verify.status}): ${shortError(verify.body)}`
@@ -55,7 +81,9 @@ async function probeCloudflareToken(input) {
55
81
  const res = await get(input.token, check.path);
56
82
  if (res.status === 200) continue;
57
83
  if (res.status === 404 && check.treat404AsPass) continue;
58
- if (res.status === 401 || res.status === 403) {
84
+ if (res.status === 0) {
85
+ issues.push(`Couldn't reach Cloudflare while checking ${check.name} (network error or timeout).`);
86
+ } else if (res.status === 401 || res.status === 403) {
59
87
  issues.push(`Missing scope: ${check.name}`);
60
88
  } else if (res.status === 400 && typeof res.body === "object" && res.body !== null && "errors" in res.body && Array.isArray(res.body.errors) && res.body.errors.some((e) => e.code === 10042)) {
61
89
  issues.push(
@@ -75,6 +103,9 @@ async function tunnelStatus(input) {
75
103
  `/accounts/${input.accountId}/cfd_tunnel/${input.tunnelId}`,
76
104
  fetchImpl
77
105
  );
106
+ if (res.status === 0) {
107
+ return { ok: false, reason: "couldn't reach Cloudflare (network error or timeout)" };
108
+ }
78
109
  if (res.status !== 200) {
79
110
  return {
80
111
  ok: false,
@@ -90,17 +121,6 @@ async function tunnelStatus(input) {
90
121
  }
91
122
  }
92
123
 
93
- // src/lib/constants.ts
94
- var PGSODIUM_KEY_RE = /^[a-f0-9]{64}$/;
95
- var TUNNEL_TOKEN_RE = /^[A-Za-z0-9_\-.=]+$/;
96
- var SAFE_PATH_RE = /^[A-Za-z0-9_\-./ ]+$/;
97
- var SAFE_LAUNCHCTL_VALUE_RE = /^[A-Za-z0-9+/=._-]+$/;
98
- var URL_SAFE_PASSWORD_RE = /^[A-Za-z0-9_-]+$/;
99
- var SAFE_URL_RE = /^[A-Za-z0-9:/_.-]+$/;
100
- var VERIFY_NETWORK_TIMEOUT_MS = 1e4;
101
- var API_REQUEST_TIMEOUT_MS = 15e3;
102
- var BODY_PREVIEW_MAX = 200;
103
-
104
124
  // src/lib/tfc.ts
105
125
  var TFC_API = "https://app.terraform.io/api/v2";
106
126
  var ORG_SLUG_RE = /^[A-Za-z0-9_-]{1,40}$/;
@@ -4831,7 +4851,7 @@ async function looksLikeRegionsRepo(dir) {
4831
4851
  }
4832
4852
 
4833
4853
  // src/cli.ts
4834
- var VERSION = "0.10.12";
4854
+ var VERSION = "0.10.13";
4835
4855
  var program = new Command();
4836
4856
  program.name("create-op-node").description(
4837
4857
  "Interactive bootstrap for an Opus Populi federation node.\nCloudflare infrastructure \u2192 Mac Studio \u2192 live public API."