Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

oakscriptjs

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

oakscriptjs - npm Package Compare versions

Comparing version
0.2.7
to
0.2.8
dist/index.cjs

Sorry, the diff of this file is too big to display

+560
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/runtime/index.ts
var runtime_exports = {};
__export(runtime_exports, {
LightweightChartsAdapter: () => LightweightChartsAdapter,
SimpleInputAdapter: () => SimpleInputAdapter,
clearContext: () => clearContext,
clearPlots: () => clearPlots,
disableAutoRecalculate: () => disableAutoRecalculate,
enableAutoRecalculate: () => enableAutoRecalculate,
getActivePlots: () => getActivePlots,
getContext: () => getContext,
hline: () => hline,
input_bool: () => input_bool,
input_float: () => input_float,
input_int: () => input_int,
input_source: () => input_source,
input_string: () => input_string,
plot: () => plot,
recalculate: () => recalculate,
registerCalculate: () => registerCalculate,
resetInputs: () => resetInputs,
setContext: () => setContext
});
module.exports = __toCommonJS(runtime_exports);
// src/runtime/runtime.ts
var context = null;
var calculateFn = null;
var activePlots = [];
var plotCounter = 0;
function setContext(ctx) {
context = ctx;
plotCounter = 0;
clearPlots();
}
function clearContext() {
clearPlots();
context = null;
calculateFn = null;
plotCounter = 0;
}
function getContext() {
return context;
}
function registerCalculate(fn) {
calculateFn = fn;
}
function recalculate() {
if (calculateFn) {
clearPlots();
plotCounter = 0;
calculateFn();
}
}
function clearPlots() {
if (context) {
for (const plot2 of activePlots) {
try {
context.chart.removeSeries(plot2.series);
} catch {
}
}
}
activePlots.length = 0;
}
function getSeriesType(style) {
switch (style) {
case "histogram":
case "columns":
return "histogram";
case "area":
case "areabr":
return "area";
case "circles":
case "cross":
return "line";
default:
return "line";
}
}
function getLineStyle(style) {
switch (style) {
case "dotted":
return 1;
case "dashed":
return 2;
case "solid":
default:
return 0;
}
}
function plot(series, title, color, linewidth, style, colors) {
if (!context) {
throw new Error("OakScript context not set. Call setContext() before plotting.");
}
const plotId = `plot_${plotCounter++}${title ? "_" + title.replace(/\s+/g, "_") : ""}`;
const seriesType = getSeriesType(style);
const options = {
color,
lineWidth: linewidth,
lineStyle: getLineStyle(style)
};
const seriesHandle = context.chart.addSeries(seriesType, options);
const data = [];
for (let index = 0; index < series.length; index++) {
const value = series[index];
const time = context.ohlcv.time[index];
if (time !== void 0 && value !== void 0 && !Number.isNaN(value)) {
const point = { time, value };
if (colors && colors[index]) {
point.color = colors[index];
}
data.push(point);
}
}
seriesHandle.setData(data);
activePlots.push({ id: plotId, series: seriesHandle });
return plotId;
}
function hline(price, title, color, linestyle, linewidth) {
if (!context) {
throw new Error("OakScript context not set. Call setContext() before creating hlines.");
}
const hlineId = `hline_${plotCounter++}${title ? "_" + title.replace(/\s+/g, "_") : ""}`;
const options = {
color,
lineWidth: linewidth,
lineStyle: getLineStyle(linestyle)
};
const seriesHandle = context.chart.addSeries("line", options);
const data = context.ohlcv.time.map((time) => ({
time,
value: price
}));
seriesHandle.setData(data);
activePlots.push({ id: hlineId, series: seriesHandle });
return hlineId;
}
function getActivePlots() {
return activePlots;
}
// src/runtime/inputs.ts
var registeredInputs = /* @__PURE__ */ new Map();
var autoRecalculateEnabled = false;
function enableAutoRecalculate() {
autoRecalculateEnabled = true;
}
function disableAutoRecalculate() {
autoRecalculateEnabled = false;
}
function resetInputs() {
registeredInputs.clear();
inputCounter = 0;
}
var inputCounter = 0;
function generateInputId(title, defval, type) {
if (title) {
return title.replace(/\s+/g, "_");
}
return `${type}_${inputCounter++}_${String(defval)}`;
}
function input_int(defval, title, options) {
const context2 = getContext();
if (!context2) {
return Math.floor(defval);
}
const id = generateInputId(title, defval, "int");
const config = {
id,
type: "int",
defval: Math.floor(defval),
title,
min: options?.min,
max: options?.max,
step: options?.step ?? 1
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "number" ? Math.floor(value) : Math.floor(defval);
}
function input_float(defval, title, options) {
const context2 = getContext();
if (!context2) {
return defval;
}
const id = generateInputId(title, defval, "float");
const config = {
id,
type: "float",
defval,
title,
min: options?.min,
max: options?.max,
step: options?.step ?? 0.1
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "number" ? value : defval;
}
function input_bool(defval, title) {
const context2 = getContext();
if (!context2) {
return defval;
}
const id = generateInputId(title, defval, "bool");
const config = {
id,
type: "bool",
defval,
title
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "boolean" ? value : defval;
}
function input_string(defval, title, options) {
const context2 = getContext();
if (!context2) {
return defval;
}
const id = generateInputId(title, defval, "string");
const config = {
id,
type: "string",
defval,
title,
options
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "string" ? value : defval;
}
function input_source(defval, title) {
const context2 = getContext();
if (!context2) {
return [];
}
const id = generateInputId(title, defval, "source");
const config = {
id,
type: "source",
defval,
title,
options: ["open", "high", "low", "close", "volume", "hl2", "hlc3", "ohlc4"]
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const sourceName = context2.inputs.getValue(id) ?? defval;
return getSourceData(context2.ohlcv, sourceName);
}
function getSourceData(ohlcv, sourceName) {
switch (sourceName) {
case "open":
return ohlcv.open;
case "high":
return ohlcv.high;
case "low":
return ohlcv.low;
case "close":
return ohlcv.close;
case "volume":
return ohlcv.volume;
case "hl2":
return ohlcv.high.map((h, i) => {
const l = ohlcv.low[i];
return l !== void 0 ? (h + l) / 2 : NaN;
});
case "hlc3":
return ohlcv.high.map((h, i) => {
const l = ohlcv.low[i];
const c = ohlcv.close[i];
return l !== void 0 && c !== void 0 ? (h + l + c) / 3 : NaN;
});
case "ohlc4":
return ohlcv.open.map((o, i) => {
const h = ohlcv.high[i];
const l = ohlcv.low[i];
const c = ohlcv.close[i];
return h !== void 0 && l !== void 0 && c !== void 0 ? (o + h + l + c) / 4 : NaN;
});
default:
return ohlcv.close;
}
}
// src/runtime/adapters/LightweightChartsAdapter.ts
var LightweightChartsAdapter = class {
chart;
mainSeries;
paneCount = 0;
/**
* Create a new LightweightChartsAdapter
* @param chart - The lightweight-charts chart instance
* @param mainSeries - Optional main price series (candlestick/line series)
*/
constructor(chart, mainSeries) {
this.chart = chart;
if (mainSeries) {
this.mainSeries = this.wrapSeries(mainSeries);
}
}
/**
* Wrap a lightweight-charts series to implement SeriesHandle
* @param lwcSeries - The lightweight-charts series
* @returns SeriesHandle wrapper
*/
wrapSeries(lwcSeries) {
return {
setData: (data) => {
lwcSeries.setData(data);
},
// Store reference for removal
_lwcSeries: lwcSeries
};
}
/**
* Map series type string to lightweight-charts series definition
* @param type - Series type ('line', 'histogram', 'area')
* @returns Lightweight-charts series definition object
*/
getSeriesDefinition(type) {
switch (type) {
case "histogram":
return { type: "Histogram" };
case "area":
return { type: "Area" };
case "baseline":
return { type: "Baseline" };
case "bar":
return { type: "Bar" };
case "line":
default:
return { type: "Line" };
}
}
/**
* Convert OakScriptJS series options to lightweight-charts options
* @param options - OakScriptJS series options
* @returns Lightweight-charts compatible options
*/
convertOptions(options) {
if (!options) {
return {};
}
const lwcOptions = {};
if (options.color) {
lwcOptions.color = options.color;
}
if (options.lineWidth !== void 0) {
lwcOptions.lineWidth = options.lineWidth;
}
if (options.lineStyle !== void 0) {
lwcOptions.lineStyle = options.lineStyle;
}
if (options.priceScaleId) {
lwcOptions.priceScaleId = options.priceScaleId;
}
return lwcOptions;
}
/**
* Add a new series to the chart
* @param type - Series type ('line', 'histogram', 'area')
* @param options - Series options
* @returns SeriesHandle for the new series
*/
addSeries(type, options) {
const seriesDefinition = this.getSeriesDefinition(type);
const lwcOptions = this.convertOptions(options);
const lwcSeries = this.chart.addSeries(seriesDefinition, lwcOptions);
return this.wrapSeries(lwcSeries);
}
/**
* Remove a series from the chart
* @param series - SeriesHandle to remove
*/
removeSeries(series) {
const wrappedSeries = series;
if (wrappedSeries._lwcSeries) {
this.chart.removeSeries(wrappedSeries._lwcSeries);
}
}
/**
* Get the main price series
* @returns Main series handle or undefined
*/
getMainSeries() {
return this.mainSeries;
}
/**
* Create a new pane (if supported by the chart configuration)
* @returns Index of the new pane
*/
createPane() {
return ++this.paneCount;
}
};
// src/runtime/adapters/SimpleInputAdapter.ts
var SimpleInputAdapter = class {
inputs = /* @__PURE__ */ new Map();
changeCallbacks = [];
/**
* Register an input configuration
* If already registered, returns current value without modifying config
* @param config - Input configuration
* @returns Current value (defval on first registration)
*/
registerInput(config) {
if (!this.inputs.has(config.id)) {
this.inputs.set(config.id, { config, value: config.defval });
}
return this.inputs.get(config.id).value;
}
/**
* Get current value of an input
* @param id - Input identifier
* @returns Current value or undefined if not registered
*/
getValue(id) {
return this.inputs.get(id)?.value;
}
/**
* Set value of an input with validation
* Validates against config constraints (min/max/step for numerics, options for strings)
* @param id - Input identifier
* @param value - New value
*/
setValue(id, value) {
const input = this.inputs.get(id);
if (!input) {
return;
}
const { config } = input;
let validatedValue = value;
if ((config.type === "int" || config.type === "float") && typeof value === "number") {
if (config.min !== void 0 && value < config.min) {
validatedValue = config.min;
}
if (config.max !== void 0 && value > config.max) {
validatedValue = config.max;
}
if (config.type === "int") {
validatedValue = Math.floor(validatedValue);
}
}
if (config.type === "string" && config.options && typeof value === "string") {
if (!config.options.includes(value)) {
return;
}
}
if (config.type === "source" && config.options && typeof value === "string") {
if (!config.options.includes(value)) {
return;
}
}
input.value = validatedValue;
this.changeCallbacks.forEach((cb) => cb(id, validatedValue));
}
/**
* Register a callback for input value changes
* @param callback - Function to call when any input value changes
*/
onInputChange(callback) {
this.changeCallbacks.push(callback);
}
/**
* Get all registered inputs (for UI rendering)
* @returns Map of input IDs to their configs and values
*/
getAllInputs() {
return new Map(this.inputs);
}
/**
* Clear all registered inputs
* Useful for testing or resetting state
*/
clear() {
this.inputs.clear();
this.changeCallbacks = [];
}
/**
* Remove a specific change callback
* @param callback - The callback to remove
*/
removeChangeCallback(callback) {
const index = this.changeCallbacks.indexOf(callback);
if (index !== -1) {
this.changeCallbacks.splice(index, 1);
}
}
};
+6
-6
{
"name": "oakscriptjs",
"version": "0.2.7",
"version": "0.2.8",
"type": "module",
"description": "PineScript v6 compatible technical analysis library for JavaScript/TypeScript",
"main": "dist/index.js",
"main": "dist/index.cjs",
"module": "dist/index.mjs",

@@ -13,3 +13,3 @@ "types": "dist/index.d.ts",

"import": "./dist/index.mjs",
"require": "./dist/index.js"
"require": "./dist/index.cjs"
},

@@ -19,3 +19,3 @@ "./runtime": {

"import": "./dist/runtime/index.mjs",
"require": "./dist/runtime/index.js"
"require": "./dist/runtime/index.cjs"
}

@@ -32,5 +32,5 @@ },

"build:esm": "esbuild src/index.ts --bundle --format=esm --outfile=dist/index.mjs --platform=neutral --external:@types/* --external:lightweight-charts",
"build:cjs": "esbuild src/index.ts --bundle --format=cjs --outfile=dist/index.js --platform=neutral --external:@types/* --external:lightweight-charts",
"build:cjs": "esbuild src/index.ts --bundle --format=cjs --outfile=dist/index.cjs --platform=neutral --external:@types/* --external:lightweight-charts",
"build:runtime:esm": "esbuild src/runtime/index.ts --bundle --format=esm --outfile=dist/runtime/index.mjs --platform=neutral --external:@types/* --external:lightweight-charts",
"build:runtime:cjs": "esbuild src/runtime/index.ts --bundle --format=cjs --outfile=dist/runtime/index.js --platform=neutral --external:@types/* --external:lightweight-charts",
"build:runtime:cjs": "esbuild src/runtime/index.ts --bundle --format=cjs --outfile=dist/runtime/index.cjs --platform=neutral --external:@types/* --external:lightweight-charts",
"build:types": "tsc --emitDeclarationOnly --outDir dist",

@@ -37,0 +37,0 @@ "clean": "rimraf dist",

Sorry, the diff of this file is too big to display

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/runtime/index.ts
var runtime_exports = {};
__export(runtime_exports, {
LightweightChartsAdapter: () => LightweightChartsAdapter,
SimpleInputAdapter: () => SimpleInputAdapter,
clearContext: () => clearContext,
clearPlots: () => clearPlots,
disableAutoRecalculate: () => disableAutoRecalculate,
enableAutoRecalculate: () => enableAutoRecalculate,
getActivePlots: () => getActivePlots,
getContext: () => getContext,
hline: () => hline,
input_bool: () => input_bool,
input_float: () => input_float,
input_int: () => input_int,
input_source: () => input_source,
input_string: () => input_string,
plot: () => plot,
recalculate: () => recalculate,
registerCalculate: () => registerCalculate,
resetInputs: () => resetInputs,
setContext: () => setContext
});
module.exports = __toCommonJS(runtime_exports);
// src/runtime/runtime.ts
var context = null;
var calculateFn = null;
var activePlots = [];
var plotCounter = 0;
function setContext(ctx) {
context = ctx;
plotCounter = 0;
clearPlots();
}
function clearContext() {
clearPlots();
context = null;
calculateFn = null;
plotCounter = 0;
}
function getContext() {
return context;
}
function registerCalculate(fn) {
calculateFn = fn;
}
function recalculate() {
if (calculateFn) {
clearPlots();
plotCounter = 0;
calculateFn();
}
}
function clearPlots() {
if (context) {
for (const plot2 of activePlots) {
try {
context.chart.removeSeries(plot2.series);
} catch {
}
}
}
activePlots.length = 0;
}
function getSeriesType(style) {
switch (style) {
case "histogram":
case "columns":
return "histogram";
case "area":
case "areabr":
return "area";
case "circles":
case "cross":
return "line";
default:
return "line";
}
}
function getLineStyle(style) {
switch (style) {
case "dotted":
return 1;
case "dashed":
return 2;
case "solid":
default:
return 0;
}
}
function plot(series, title, color, linewidth, style, colors) {
if (!context) {
throw new Error("OakScript context not set. Call setContext() before plotting.");
}
const plotId = `plot_${plotCounter++}${title ? "_" + title.replace(/\s+/g, "_") : ""}`;
const seriesType = getSeriesType(style);
const options = {
color,
lineWidth: linewidth,
lineStyle: getLineStyle(style)
};
const seriesHandle = context.chart.addSeries(seriesType, options);
const data = [];
for (let index = 0; index < series.length; index++) {
const value = series[index];
const time = context.ohlcv.time[index];
if (time !== void 0 && value !== void 0 && !Number.isNaN(value)) {
const point = { time, value };
if (colors && colors[index]) {
point.color = colors[index];
}
data.push(point);
}
}
seriesHandle.setData(data);
activePlots.push({ id: plotId, series: seriesHandle });
return plotId;
}
function hline(price, title, color, linestyle, linewidth) {
if (!context) {
throw new Error("OakScript context not set. Call setContext() before creating hlines.");
}
const hlineId = `hline_${plotCounter++}${title ? "_" + title.replace(/\s+/g, "_") : ""}`;
const options = {
color,
lineWidth: linewidth,
lineStyle: getLineStyle(linestyle)
};
const seriesHandle = context.chart.addSeries("line", options);
const data = context.ohlcv.time.map((time) => ({
time,
value: price
}));
seriesHandle.setData(data);
activePlots.push({ id: hlineId, series: seriesHandle });
return hlineId;
}
function getActivePlots() {
return activePlots;
}
// src/runtime/inputs.ts
var registeredInputs = /* @__PURE__ */ new Map();
var autoRecalculateEnabled = false;
function enableAutoRecalculate() {
autoRecalculateEnabled = true;
}
function disableAutoRecalculate() {
autoRecalculateEnabled = false;
}
function resetInputs() {
registeredInputs.clear();
inputCounter = 0;
}
var inputCounter = 0;
function generateInputId(title, defval, type) {
if (title) {
return title.replace(/\s+/g, "_");
}
return `${type}_${inputCounter++}_${String(defval)}`;
}
function input_int(defval, title, options) {
const context2 = getContext();
if (!context2) {
return Math.floor(defval);
}
const id = generateInputId(title, defval, "int");
const config = {
id,
type: "int",
defval: Math.floor(defval),
title,
min: options?.min,
max: options?.max,
step: options?.step ?? 1
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "number" ? Math.floor(value) : Math.floor(defval);
}
function input_float(defval, title, options) {
const context2 = getContext();
if (!context2) {
return defval;
}
const id = generateInputId(title, defval, "float");
const config = {
id,
type: "float",
defval,
title,
min: options?.min,
max: options?.max,
step: options?.step ?? 0.1
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "number" ? value : defval;
}
function input_bool(defval, title) {
const context2 = getContext();
if (!context2) {
return defval;
}
const id = generateInputId(title, defval, "bool");
const config = {
id,
type: "bool",
defval,
title
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "boolean" ? value : defval;
}
function input_string(defval, title, options) {
const context2 = getContext();
if (!context2) {
return defval;
}
const id = generateInputId(title, defval, "string");
const config = {
id,
type: "string",
defval,
title,
options
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const value = context2.inputs.getValue(id);
return typeof value === "string" ? value : defval;
}
function input_source(defval, title) {
const context2 = getContext();
if (!context2) {
return [];
}
const id = generateInputId(title, defval, "source");
const config = {
id,
type: "source",
defval,
title,
options: ["open", "high", "low", "close", "volume", "hl2", "hlc3", "ohlc4"]
};
if (!registeredInputs.has(id)) {
context2.inputs.registerInput(config);
registeredInputs.set(id, true);
if (autoRecalculateEnabled) {
context2.inputs.onInputChange((changedId) => {
if (changedId === id) {
recalculate();
}
});
}
}
const sourceName = context2.inputs.getValue(id) ?? defval;
return getSourceData(context2.ohlcv, sourceName);
}
function getSourceData(ohlcv, sourceName) {
switch (sourceName) {
case "open":
return ohlcv.open;
case "high":
return ohlcv.high;
case "low":
return ohlcv.low;
case "close":
return ohlcv.close;
case "volume":
return ohlcv.volume;
case "hl2":
return ohlcv.high.map((h, i) => {
const l = ohlcv.low[i];
return l !== void 0 ? (h + l) / 2 : NaN;
});
case "hlc3":
return ohlcv.high.map((h, i) => {
const l = ohlcv.low[i];
const c = ohlcv.close[i];
return l !== void 0 && c !== void 0 ? (h + l + c) / 3 : NaN;
});
case "ohlc4":
return ohlcv.open.map((o, i) => {
const h = ohlcv.high[i];
const l = ohlcv.low[i];
const c = ohlcv.close[i];
return h !== void 0 && l !== void 0 && c !== void 0 ? (o + h + l + c) / 4 : NaN;
});
default:
return ohlcv.close;
}
}
// src/runtime/adapters/LightweightChartsAdapter.ts
var LightweightChartsAdapter = class {
chart;
mainSeries;
paneCount = 0;
/**
* Create a new LightweightChartsAdapter
* @param chart - The lightweight-charts chart instance
* @param mainSeries - Optional main price series (candlestick/line series)
*/
constructor(chart, mainSeries) {
this.chart = chart;
if (mainSeries) {
this.mainSeries = this.wrapSeries(mainSeries);
}
}
/**
* Wrap a lightweight-charts series to implement SeriesHandle
* @param lwcSeries - The lightweight-charts series
* @returns SeriesHandle wrapper
*/
wrapSeries(lwcSeries) {
return {
setData: (data) => {
lwcSeries.setData(data);
},
// Store reference for removal
_lwcSeries: lwcSeries
};
}
/**
* Map series type string to lightweight-charts series definition
* @param type - Series type ('line', 'histogram', 'area')
* @returns Lightweight-charts series definition object
*/
getSeriesDefinition(type) {
switch (type) {
case "histogram":
return { type: "Histogram" };
case "area":
return { type: "Area" };
case "baseline":
return { type: "Baseline" };
case "bar":
return { type: "Bar" };
case "line":
default:
return { type: "Line" };
}
}
/**
* Convert OakScriptJS series options to lightweight-charts options
* @param options - OakScriptJS series options
* @returns Lightweight-charts compatible options
*/
convertOptions(options) {
if (!options) {
return {};
}
const lwcOptions = {};
if (options.color) {
lwcOptions.color = options.color;
}
if (options.lineWidth !== void 0) {
lwcOptions.lineWidth = options.lineWidth;
}
if (options.lineStyle !== void 0) {
lwcOptions.lineStyle = options.lineStyle;
}
if (options.priceScaleId) {
lwcOptions.priceScaleId = options.priceScaleId;
}
return lwcOptions;
}
/**
* Add a new series to the chart
* @param type - Series type ('line', 'histogram', 'area')
* @param options - Series options
* @returns SeriesHandle for the new series
*/
addSeries(type, options) {
const seriesDefinition = this.getSeriesDefinition(type);
const lwcOptions = this.convertOptions(options);
const lwcSeries = this.chart.addSeries(seriesDefinition, lwcOptions);
return this.wrapSeries(lwcSeries);
}
/**
* Remove a series from the chart
* @param series - SeriesHandle to remove
*/
removeSeries(series) {
const wrappedSeries = series;
if (wrappedSeries._lwcSeries) {
this.chart.removeSeries(wrappedSeries._lwcSeries);
}
}
/**
* Get the main price series
* @returns Main series handle or undefined
*/
getMainSeries() {
return this.mainSeries;
}
/**
* Create a new pane (if supported by the chart configuration)
* @returns Index of the new pane
*/
createPane() {
return ++this.paneCount;
}
};
// src/runtime/adapters/SimpleInputAdapter.ts
var SimpleInputAdapter = class {
inputs = /* @__PURE__ */ new Map();
changeCallbacks = [];
/**
* Register an input configuration
* If already registered, returns current value without modifying config
* @param config - Input configuration
* @returns Current value (defval on first registration)
*/
registerInput(config) {
if (!this.inputs.has(config.id)) {
this.inputs.set(config.id, { config, value: config.defval });
}
return this.inputs.get(config.id).value;
}
/**
* Get current value of an input
* @param id - Input identifier
* @returns Current value or undefined if not registered
*/
getValue(id) {
return this.inputs.get(id)?.value;
}
/**
* Set value of an input with validation
* Validates against config constraints (min/max/step for numerics, options for strings)
* @param id - Input identifier
* @param value - New value
*/
setValue(id, value) {
const input = this.inputs.get(id);
if (!input) {
return;
}
const { config } = input;
let validatedValue = value;
if ((config.type === "int" || config.type === "float") && typeof value === "number") {
if (config.min !== void 0 && value < config.min) {
validatedValue = config.min;
}
if (config.max !== void 0 && value > config.max) {
validatedValue = config.max;
}
if (config.type === "int") {
validatedValue = Math.floor(validatedValue);
}
}
if (config.type === "string" && config.options && typeof value === "string") {
if (!config.options.includes(value)) {
return;
}
}
if (config.type === "source" && config.options && typeof value === "string") {
if (!config.options.includes(value)) {
return;
}
}
input.value = validatedValue;
this.changeCallbacks.forEach((cb) => cb(id, validatedValue));
}
/**
* Register a callback for input value changes
* @param callback - Function to call when any input value changes
*/
onInputChange(callback) {
this.changeCallbacks.push(callback);
}
/**
* Get all registered inputs (for UI rendering)
* @returns Map of input IDs to their configs and values
*/
getAllInputs() {
return new Map(this.inputs);
}
/**
* Clear all registered inputs
* Useful for testing or resetting state
*/
clear() {
this.inputs.clear();
this.changeCallbacks = [];
}
/**
* Remove a specific change callback
* @param callback - The callback to remove
*/
removeChangeCallback(callback) {
const index = this.changeCallbacks.indexOf(callback);
if (index !== -1) {
this.changeCallbacks.splice(index, 1);
}
}
};