@forgecharts/sdk 1.5.72 → 1.5.73

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.
@@ -47,8 +47,14 @@ function timeframeToMs(tf) {
47
47
  const secs = parseTfSeconds(tf);
48
48
  return secs !== null ? secs * 1e3 : null;
49
49
  }
50
+ function normalizeTimeframe(tf) {
51
+ const m = /^(\d+)([a-zA-Z])$/.exec(tf.trim());
52
+ if (!m) return tf.trim();
53
+ const unit = m[2];
54
+ return m[1] + (unit === "M" ? unit : unit.toLowerCase());
55
+ }
50
56
  function parseTfSeconds(tf) {
51
- const m = /^(\d+)(s|m|h|d|w|M)$/.exec(tf);
57
+ const m = /^(\d+)(s|m|h|d|w|M)$/.exec(normalizeTimeframe(tf));
52
58
  if (!m) return null;
53
59
  const n = parseInt(m[1], 10);
54
60
  const unit = m[2];
@@ -64,6 +70,7 @@ function parseTfSeconds(tf) {
64
70
  return unitSec !== void 0 ? n * unitSec : null;
65
71
  }
66
72
  function getBucketStart(timeMs, timeframe) {
73
+ timeframe = normalizeTimeframe(timeframe);
67
74
  if (timeframe === "1w") return getWeekBucketStart(timeMs);
68
75
  if (timeframe === "1M") return getMonthBucketStart(timeMs);
69
76
  if (timeframe === "3M") return getQuarterBucketStart(timeMs);
@@ -7670,32 +7677,7 @@ function formatCountdown(secs) {
7670
7677
  return `${m}:${String(s).padStart(2, "0")}`;
7671
7678
  }
7672
7679
  function tfToSeconds(tf) {
7673
- const map = {
7674
- "1s": 1,
7675
- "5s": 5,
7676
- "10s": 10,
7677
- "15s": 15,
7678
- "30s": 30,
7679
- "1m": 60,
7680
- "3m": 180,
7681
- "5m": 300,
7682
- "15m": 900,
7683
- "30m": 1800,
7684
- "1h": 3600,
7685
- "2h": 7200,
7686
- "4h": 14400,
7687
- "6h": 21600,
7688
- "8h": 28800,
7689
- "12h": 43200,
7690
- "1D": 86400,
7691
- "3D": 259200,
7692
- "1W": 604800,
7693
- "1M": 2592e3,
7694
- "3M": 7776e3,
7695
- "6M": 15552e3,
7696
- "12M": 31536e3
7697
- };
7698
- return map[tf] ?? 3600;
7680
+ return parseTfSeconds(tf) ?? 3600;
7699
7681
  }
7700
7682
  var PixiLastPriceRenderer = class {
7701
7683
  _lineGfx;
@@ -9680,34 +9662,16 @@ var PixiChart = class {
9680
9662
  }
9681
9663
  return { time: bestBar.time, price: snappedPrice };
9682
9664
  }
9683
- /** Convert a Timeframe string to seconds (internal helper). */
9665
+ /**
9666
+ * Convert a Timeframe string to seconds (internal helper).
9667
+ *
9668
+ * Delegates to the shared parser — this was one of three private maps, and
9669
+ * the only one still keyed '1D'/'1W' uppercase, so canonical '1d' fell to
9670
+ * the 3600 fallback here while '1D' fell to the 1m fallback everywhere
9671
+ * else. One derivation, one dialect.
9672
+ */
9684
9673
  _tfToSeconds(tf) {
9685
- const map = {
9686
- "1s": 1,
9687
- "5s": 5,
9688
- "10s": 10,
9689
- "15s": 15,
9690
- "30s": 30,
9691
- "1m": 60,
9692
- "3m": 180,
9693
- "5m": 300,
9694
- "15m": 900,
9695
- "30m": 1800,
9696
- "1h": 3600,
9697
- "2h": 7200,
9698
- "4h": 14400,
9699
- "6h": 21600,
9700
- "8h": 28800,
9701
- "12h": 43200,
9702
- "1D": 86400,
9703
- "3D": 259200,
9704
- "1W": 604800,
9705
- "1M": 2592e3,
9706
- "3M": 7776e3,
9707
- "6M": 15552e3,
9708
- "12M": 31536e3
9709
- };
9710
- return map[tf] ?? 3600;
9674
+ return parseTfSeconds(tf) ?? 3600;
9711
9675
  }
9712
9676
  // ─── Option resolvers ────────────────────────────────────────────────────────
9713
9677
  _resolveOptions(opts) {
@@ -18367,7 +18331,7 @@ var DEMONSTRATION_STROKE = "rgba(255, 200, 50, 0.7)";
18367
18331
  var DEMONSTRATION_COLOR = "var(--crosshair-overlay, rgba(255,255,255,0.75))";
18368
18332
 
18369
18333
  // src/version.ts
18370
- var FORGECHARTS_VERSION = "1.5.72" ;
18334
+ var FORGECHARTS_VERSION = "1.5.73" ;
18371
18335
  function applyRuntimeConfig(caps, config) {
18372
18336
  if (!config) return caps;
18373
18337
  const orderEntry = config.enableOrderEntry === false ? false : caps.orderEntry;
@@ -26206,6 +26170,7 @@ function IndicatorsDialog({ onAdd, onClose, maxIndicators, getAuthToken }) {
26206
26170
  ] }) });
26207
26171
  }
26208
26172
  var DEFAULT_FAVORITES = ["1m", "5m", "15m", "30m", "1h", "4h", "1d", "1w"];
26173
+ var chipLabel = (tf) => /^\d+[dw]$/.test(tf) ? tf.toUpperCase() : tf;
26209
26174
  var TF_LABELS = {
26210
26175
  "1m": "1 minute",
26211
26176
  "2m": "2 minutes",
@@ -26645,7 +26610,7 @@ function TopToolbar({
26645
26610
  onClick: () => onTimeframeChange(tf),
26646
26611
  children: tf
26647
26612
  },
26648
- tf
26613
+ chipLabel(tf)
26649
26614
  )),
26650
26615
  /* @__PURE__ */ jsx(
26651
26616
  "button",
@@ -30213,6 +30178,7 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
30213
30178
  const [savedScripts, setSavedScripts] = useState([]);
30214
30179
  const [scriptsMenuOpen, setScriptsMenuOpen] = useState(false);
30215
30180
  const [saving, setSaving] = useState(false);
30181
+ const [saveError, setSaveError] = useState(null);
30216
30182
  const [activeScriptId, setActiveScriptId] = useState(null);
30217
30183
  const [saveNameInput, setSaveNameInput] = useState("");
30218
30184
  const [showSaveNamePrompt, setShowSaveNamePrompt] = useState(false);
@@ -30306,6 +30272,7 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
30306
30272
  }, [scriptsMenuOpen]);
30307
30273
  const handleSaveScript = useCallback(async (name) => {
30308
30274
  setSaving(true);
30275
+ setSaveError(null);
30309
30276
  const base = apiUrl ?? "";
30310
30277
  const auth = await _authHeaders();
30311
30278
  const scriptSource = code;
@@ -30313,27 +30280,28 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
30313
30280
  const scriptName = name ?? extractScriptName(scriptSource);
30314
30281
  try {
30315
30282
  if (activeScriptId) {
30316
- await fetch(`${base}/api/scripts/${encodeURIComponent(activeScriptId)}/versions`, {
30283
+ const res = await fetch(`${base}/api/scripts/${encodeURIComponent(activeScriptId)}/versions`, {
30317
30284
  method: "POST",
30318
30285
  headers: { "Content-Type": "application/json", ...auth },
30319
30286
  body: JSON.stringify({ source: scriptSource })
30320
30287
  });
30288
+ if (!res.ok) throw new Error(`save failed (${res.status})`);
30321
30289
  } else {
30322
30290
  const res = await fetch(`${base}/api/scripts`, {
30323
30291
  method: "POST",
30324
30292
  headers: { "Content-Type": "application/json", ...auth },
30325
30293
  body: JSON.stringify({ name: scriptName, language: scriptLang, source: scriptSource })
30326
30294
  });
30327
- if (res.ok) {
30328
- const created = await res.json();
30329
- setActiveScriptId(created.id);
30330
- }
30295
+ if (!res.ok) throw new Error(`save failed (${res.status})`);
30296
+ const created = await res.json();
30297
+ setActiveScriptId(created.id);
30331
30298
  }
30332
30299
  await fetchSavedScripts();
30333
- } catch {
30300
+ setShowSaveNamePrompt(false);
30301
+ } catch (err) {
30302
+ setSaveError(err instanceof Error ? err.message : "save failed");
30334
30303
  }
30335
30304
  setSaving(false);
30336
- setShowSaveNamePrompt(false);
30337
30305
  }, [apiUrl, _authHeaders, code, activeScriptId, extractScriptName, fetchSavedScripts]);
30338
30306
  const handleSaveClick = useCallback(() => {
30339
30307
  if (activeScriptId) {
@@ -30436,6 +30404,16 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
30436
30404
  ]
30437
30405
  }
30438
30406
  ),
30407
+ saveError && /* @__PURE__ */ jsx(
30408
+ "span",
30409
+ {
30410
+ className: "script-save-error",
30411
+ role: "alert",
30412
+ title: saveError,
30413
+ style: { color: "var(--fc-danger, #e5484d)", fontSize: 11, marginLeft: 6 },
30414
+ children: saveError
30415
+ }
30416
+ ),
30439
30417
  /* @__PURE__ */ jsxs("div", { className: "script-my-scripts-wrap", ref: scriptsMenuRef, children: [
30440
30418
  /* @__PURE__ */ jsxs(
30441
30419
  "button",
@@ -36637,7 +36615,7 @@ var ManagedAppShell = forwardRef(
36637
36615
  const res = await fetch(`${base}/api/scripts`, {
36638
36616
  method: "POST",
36639
36617
  headers: { ...auth, "Content-Type": "application/json" },
36640
- body: JSON.stringify({ name, source, language: "tscript" })
36618
+ body: JSON.stringify({ name, source, language: "forgescript" })
36641
36619
  });
36642
36620
  if (!res.ok) throw new Error(`Failed to create script (${res.status})`);
36643
36621
  const data = await res.json();