Compare commits
2 Commits
b2d7f18213
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| a3bbd5638a | |||
| c90f4a0244 |
168
.trae/documents/cross-language-sdk-guide.md
Normal file
168
.trae/documents/cross-language-sdk-guide.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# 跨语言 SDK 实现指南:数据传递与序列化
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
Structrail 平台的核心目标是提供一套**语言无关**的数据结构可视化协议。这意味着我们的 SDK 需要在不同特性的编程语言中(从高动态的 Python/JS 到静态底层的 C/C++)提供一致的功能体验。
|
||||||
|
|
||||||
|
**注意,我们不再需要 `preset` 指令了,但是即便 `preset` 的参数被合并到 `create` 指令中,这篇文档对于如何在不同语言中实现 `preset` 功能的说明仍然是有价值的。**
|
||||||
|
|
||||||
|
其中,`preset` 指令(一次性同步数组/容器状态)在静态类型语言(特别是 C 语言)中的实现是最大的挑战。本文档旨在论证其可行性,并为未来各语言 SDK 的实现提供参考规范。
|
||||||
|
|
||||||
|
## 核心挑战:数组的异构性
|
||||||
|
|
||||||
|
在动态语言(TS, Python)中,数组是自描述的对象,包含长度和元素类型信息。
|
||||||
|
在静态托管语言(Java, C#, Go)中,数组/列表也是对象,具备反射或自省能力。
|
||||||
|
在 C/C++ 中,原生数组仅仅是内存地址(指针),且 C 语言完全丢失了长度和类型信息。
|
||||||
|
|
||||||
|
## 通用解决方案:SDK 接口分层
|
||||||
|
|
||||||
|
为了抹平差异,我们建议 SDK 接口设计遵循\*\*“渐进式暴露”\*\*原则:
|
||||||
|
|
||||||
|
1. **Level 1: 智能推断接口**(针对 TS, Python, Java 等)
|
||||||
|
- 用户直接传数组对象。
|
||||||
|
- SDK 内部自动获取长度、遍历序列化。
|
||||||
|
|
||||||
|
2. **Level 2: 显式元数据接口**(针对 C++, Go, Rust 等)
|
||||||
|
- 用户传递数据指针 + 长度。
|
||||||
|
- 利用泛型/模板自动推导元素序列化逻辑。
|
||||||
|
|
||||||
|
3. **Level 3: 手动序列化接口**(针对 C 语言)
|
||||||
|
- 用户传递数据指针 + 长度 + 元素大小 + 序列化策略。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 各语言实现参考
|
||||||
|
|
||||||
|
### 1. TypeScript / JavaScript (已实现)
|
||||||
|
|
||||||
|
利用语言的动态特性,直接接受 `any[]`。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// SDK
|
||||||
|
preset(data: T[]) {
|
||||||
|
// JSON.stringify 天然支持数组序列化
|
||||||
|
this.emit('preset', { data });
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Java / C# / Python
|
||||||
|
|
||||||
|
利用标准库的反射或序列化能力。
|
||||||
|
|
||||||
|
**Java 示例**:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// SDK
|
||||||
|
public <T> void preset(List<T> data) {
|
||||||
|
// 使用 Jackson 或 Gson 库
|
||||||
|
String json = gson.toJson(data);
|
||||||
|
this.emit("preset", json);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. C++ (Modern C++)
|
||||||
|
|
||||||
|
利用模板和 STL 容器特性。
|
||||||
|
|
||||||
|
**C++ 示例**:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 针对 std::vector 的重载
|
||||||
|
template<typename T>
|
||||||
|
void preset(const std::vector<T>& data) {
|
||||||
|
json j = data; // 使用 nlohmann/json 库,自动支持 STL 容器
|
||||||
|
emit("preset", j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 针对原生数组的重载 (C++20 std::span 最佳,或传指针+长度)
|
||||||
|
template<typename T>
|
||||||
|
void preset(const T* arr, size_t size) {
|
||||||
|
std::vector<T> vec(arr, arr + size);
|
||||||
|
preset(vec);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. C 语言 (重点攻坚)
|
||||||
|
|
||||||
|
C 语言没有泛型,没有反射,没有对象。我们需要用户手动提供元数据。
|
||||||
|
|
||||||
|
#### 方案 A: 宏魔法 (Generic Selection) - 推荐用于基础类型
|
||||||
|
|
||||||
|
利用 C11 `_Generic` 关键字模拟函数重载,提升基础类型的使用体验。
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 底层 API
|
||||||
|
void _tracer_preset_int(tracer_t* t, int* arr, size_t len);
|
||||||
|
void _tracer_preset_float(tracer_t* t, float* arr, size_t len);
|
||||||
|
|
||||||
|
// 用户宏接口
|
||||||
|
#define tracer_preset(t, arr, len) _Generic((arr), \
|
||||||
|
int*: _tracer_preset_int, \
|
||||||
|
float*: _tracer_preset_float \
|
||||||
|
)(t, arr, len)
|
||||||
|
|
||||||
|
// 用户调用
|
||||||
|
int nums[] = {1, 2, 3};
|
||||||
|
tracer_preset(t, nums, 3); // 自动匹配 int 版本
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方案 B: 格式化字符串 (Printf Style) - 推荐用于复杂类型
|
||||||
|
|
||||||
|
对于结构体或未覆盖的基础类型,采用类似 `printf` 的描述符。
|
||||||
|
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* @param elem_fmt: 元素类型描述符
|
||||||
|
* "d": int
|
||||||
|
* "f": float
|
||||||
|
* "s": string
|
||||||
|
* "{x:d,y:d}": struct Point {int x; int y}
|
||||||
|
*/
|
||||||
|
void tracer_preset_fmt(tracer_t* t, void* data, size_t len, size_t elem_size, const char* elem_fmt);
|
||||||
|
|
||||||
|
// 用户调用
|
||||||
|
struct Point pts[] = {{1,2}, {3,4}};
|
||||||
|
tracer_preset_fmt(t, pts, 2, sizeof(struct Point), "{x:d,y:d}");
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方案 C: 回调函数 (Callback) - 兜底方案
|
||||||
|
|
||||||
|
万能方案,用户自己负责把元素转成字符串。
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef void (*serializer_func)(void* elem, char* buffer);
|
||||||
|
|
||||||
|
void tracer_preset_cb(tracer_t* t, void* data, size_t len, size_t elem_size, serializer_func cb);
|
||||||
|
|
||||||
|
// 用户调用
|
||||||
|
// 1. 用户定义序列化器
|
||||||
|
void my_int_serializer(void* elem, char* buffer) {
|
||||||
|
sprintf(buffer, "%d", *(int*)elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 传递给 SDK
|
||||||
|
int nums[] = {1, 2, 3};
|
||||||
|
tracer_preset_cb(t, nums, 3, sizeof(int), my_int_serializer);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 协议一致性保障
|
||||||
|
|
||||||
|
无论采用哪种语言实现,生成的 JSON 指令必须严格一致:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "ArrayTracer",
|
||||||
|
"tracer": "uuid-...",
|
||||||
|
"action": "preset",
|
||||||
|
"params": {
|
||||||
|
"data": [1, 2, 3, 4] // 或者是 [{"x":1,"y":2}, ...]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这意味着 C 语言 SDK 内部必须手动拼接 JSON 字符串(`[` + `elem` + `,` + `elem` + `]`)。
|
||||||
|
|
||||||
|
## 结论
|
||||||
|
|
||||||
|
1. **`preset`** **指令是可移植的**:即使在最底层的 C 语言中,通过适当的 API 封装(宏或格式化串),也能实现与高级语言近似的开发体验。
|
||||||
|
2. **不要为了 C 语言阉割协议**:不需要因为 C 语言处理数组麻烦,就放弃 `preset` 而强迫所有语言都用 `patch` 循环。SDK 应该把复杂性封装在内部,留给用户简洁的接口。
|
||||||
224
.trae/documents/sdk-initialization-patterns.md
Normal file
224
.trae/documents/sdk-initialization-patterns.md
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
# 多语言 SDK 初始化设计规范
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
为了简化 SDK 的使用流程并统一 API 设计体验,我们决定将 Tracer 的初始化数据(Initial Data)合并到创建(Create)阶段。这意味着用户在实例化 Tracer 时,可以直接传入初始数据,而无需单独调用 `preset` 方法。
|
||||||
|
|
||||||
|
这一设计模式(Construct as Initialize)在大多数现代编程语言中都有成熟的最佳实践。本文档旨在为不同语言的 SDK 实现提供具体的代码范式参考。
|
||||||
|
|
||||||
|
## 核心原则
|
||||||
|
|
||||||
|
1. **优先使用构造函数参数**:如果语言支持(如 Python, Kotlin, Swift),优先使用带默认值的命名参数。
|
||||||
|
2. **利用语言特性**:
|
||||||
|
- **重载 (Overloading)**:适用于 Java, C++, C#。
|
||||||
|
- **配置对象 (Options Object)**:适用于 TS, JS, Lua。
|
||||||
|
- **Builder / Functional Options**:适用于 Go, Rust。
|
||||||
|
3. **保持协议底层一致**:无论上层 API 如何设计,底层生成的 `create` 指令 JSON 必须包含 `array` (或对应数据字段) 参数。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 各语言实现参考
|
||||||
|
|
||||||
|
### 1. TypeScript / JavaScript (当前基准)
|
||||||
|
|
||||||
|
利用接口(Interface)定义配置对象,简洁且扩展性强。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 定义
|
||||||
|
interface ArrayTracerOptions<T> {
|
||||||
|
description: string;
|
||||||
|
array?: T[]; // 可选初始化数据
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createArrayTracer = <T>(options: ArrayTracerOptions<T>) => { ... }
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
const t1 = createArrayTracer({ description: "Empty" });
|
||||||
|
const t2 = createArrayTracer({
|
||||||
|
description: "My Array",
|
||||||
|
array: [1, 2, 3]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Python (Keyword Arguments)
|
||||||
|
|
||||||
|
利用 `**kwargs` 或显式关键字参数,非常符合 Pythonic 风格。
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ArrayTracer:
|
||||||
|
def __init__(self, description: str, data: list = None):
|
||||||
|
self.description = description
|
||||||
|
if data:
|
||||||
|
self._emit_create(data)
|
||||||
|
|
||||||
|
# 调用
|
||||||
|
t1 = ArrayTracer(description="Empty")
|
||||||
|
t2 = ArrayTracer(description="My Array", data=[1, 2, 3])
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Java (Constructor Overloading)
|
||||||
|
|
||||||
|
利用构造函数重载提供多种初始化路径。
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class ArrayTracer<T> {
|
||||||
|
// 构造函数 1: 仅描述
|
||||||
|
public ArrayTracer(String description) {
|
||||||
|
this(description, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造函数 2: 描述 + 数据
|
||||||
|
public ArrayTracer(String description, List<T> data) {
|
||||||
|
// ... implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
var t1 = new ArrayTracer<Integer>("Empty");
|
||||||
|
var t2 = new ArrayTracer<Integer>("My Array", Arrays.asList(1, 2, 3));
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. C++ (Overloading & Initializer List)
|
||||||
|
|
||||||
|
利用 `std::initializer_list` 支持花括号初始化,语法极其简洁。
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template <typename T>
|
||||||
|
class ArrayTracer {
|
||||||
|
public:
|
||||||
|
// 基础构造
|
||||||
|
ArrayTracer(std::string description) { ... }
|
||||||
|
|
||||||
|
// 带数据构造 (支持 vector)
|
||||||
|
ArrayTracer(std::string description, const std::vector<T>& data) { ... }
|
||||||
|
|
||||||
|
// 带数据构造 (支持 {1,2,3} 字面量)
|
||||||
|
ArrayTracer(std::string description, std::initializer_list<T> data) { ... }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
ArrayTracer<int> t1("Empty");
|
||||||
|
ArrayTracer<int> t2("My Array", {1, 2, 3});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Go (Functional Options Pattern)
|
||||||
|
|
||||||
|
Go 社区处理复杂构造参数的标准模式。
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Option func(*ArrayTracer)
|
||||||
|
|
||||||
|
func WithData(data []interface{}) Option {
|
||||||
|
return func(t *ArrayTracer) {
|
||||||
|
t.initialData = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewArrayTracer(desc string, opts ...Option) *ArrayTracer {
|
||||||
|
t := &ArrayTracer{Description: desc}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(t)
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
t1 := NewArrayTracer("Empty")
|
||||||
|
t2 := NewArrayTracer("My Array", WithData([]interface{}{1, 2, 3}))
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Rust (Builder Pattern)
|
||||||
|
|
||||||
|
利用 Builder 模式处理构造参数,保证类型安全和可读性。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ArrayTracerBuilder { ... }
|
||||||
|
|
||||||
|
impl ArrayTracer {
|
||||||
|
pub fn builder(description: &str) -> ArrayTracerBuilder { ... }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArrayTracerBuilder {
|
||||||
|
pub fn with_data(mut self, data: Vec<i32>) -> Self { ... }
|
||||||
|
pub fn build(self) -> ArrayTracer { ... }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
let t = ArrayTracer::builder("My Array")
|
||||||
|
.with_data(vec![1, 2, 3])
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. C# (Optional Arguments)
|
||||||
|
|
||||||
|
类似于 TypeScript 和 Kotlin,C# 支持命名参数和默认值。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class ArrayTracer<T> {
|
||||||
|
public ArrayTracer(string description, IEnumerable<T> data = null) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
var t1 = new ArrayTracer<int>("Empty");
|
||||||
|
var t2 = new ArrayTracer<int>("My Array", data: new[] { 1, 2, 3 });
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. C 语言 (Special Case)
|
||||||
|
|
||||||
|
C 语言不支持重载,且缺乏自省能力,因此建议提供两种创建模式:
|
||||||
|
|
||||||
|
**方案 A: 基础数据类型 (使用宏或特定后缀)**
|
||||||
|
对于 `int`, `float` 等基础类型,提供专用函数。
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 基础创建
|
||||||
|
tracer_t* tracer_create_array(const char* desc);
|
||||||
|
|
||||||
|
// 带数据创建 (Explicit is better than implicit)
|
||||||
|
tracer_t* tracer_create_array_with_data(const char* desc, void* data, size_t len);
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
tracer_t* t1 = tracer_create_array("Empty");
|
||||||
|
int nums[] = {1, 2, 3};
|
||||||
|
tracer_t* t2 = tracer_create_array_with_data("My Array", nums, 3);
|
||||||
|
```
|
||||||
|
|
||||||
|
**方案 B: 自定义结构体 (Callback 模式)**
|
||||||
|
对于用户自定义的 `struct`,采用类似 `qsort` 的回调函数模式,让用户提供序列化逻辑。
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 定义序列化回调: 将 elem 转换为 JSON 字符串写入 buffer
|
||||||
|
typedef void (*serializer_func)(const void* elem, char* buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param serializer 用户提供的序列化函数
|
||||||
|
*/
|
||||||
|
tracer_t* tracer_create_array_custom(
|
||||||
|
const char* desc,
|
||||||
|
const void* data,
|
||||||
|
size_t len,
|
||||||
|
size_t elem_size,
|
||||||
|
serializer_func serializer
|
||||||
|
);
|
||||||
|
|
||||||
|
// 用户代码示例
|
||||||
|
typedef struct { int x; int y; } Point;
|
||||||
|
|
||||||
|
// 用户编写序列化逻辑
|
||||||
|
void point_serializer(const void* elem, char* buffer) {
|
||||||
|
const Point* p = (const Point*)elem;
|
||||||
|
sprintf(buffer, "{\"x\":%d,\"y\":%d}", p->x, p->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
Point pts[] = {{1,2}, {3,4}};
|
||||||
|
tracer_t* t = tracer_create_array_custom("Points", pts, 2, sizeof(Point), point_serializer);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
通过统一采用**“构造即初始化”**的设计模式,我们能够在几乎所有主流编程语言中提供一致、简洁且符合语言习惯(Idiomatic)的 SDK 使用体验。这不仅降低了用户的学习成本,也使得代码更加紧凑和易读。
|
||||||
15
.trae/rules/project-introduction.md
Normal file
15
.trae/rules/project-introduction.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
## 项目背景
|
||||||
|
|
||||||
|
我正在设计一款数据结构与算法可视化平台(以下简称为“平台”),允许用户在平台上编写算法的实现代码,当用户提交代码后,平台会能够获取到代码中所涉及的数据结构的变化过程,并以可视化的形式来渲染整个变化过程,并且将数据结构的变化与代码的执行过程关联起来,给用户的感受就像是在调试代码一样,算法执行到某一步时,代码中的相关部分会高亮显示。用户可以在平台上通过“下一步”功能来查看算法的执行过程中每一个步骤所对应的数据结构变化,并且还可以具有“时间旅行”的功能,允许用户通过“上一步”功能来向前回溯算法的执行。此外,从长期规划和产品化的角度来说,平台还会支持添加对多种主流编程语言的支持。
|
||||||
|
|
||||||
|
## 项目目标
|
||||||
|
|
||||||
|
基于上述设想,我肯定无法接受从编译技术的角度去适配每一种编程语言(例如代码插桩甚至改造编译器),因为这会导致平台的开发变得非常复杂,维护成本也会非常高。因此我的想法是设计一套语言无关的协议,用来描述各种数据结构的变化(跟踪器),因此这套协议会定义需要支持的数据结构类型,以及每一种数据结构类型需要支持的操作指令,并且我倾向于将指令设计得更加“底层”一些,类似于“原语”的概念。
|
||||||
|
|
||||||
|
> 例如针对顺序表结构,我可能会定义 pick(获取元素)、drop(取消获取)、patch(修改元素) 指令来替代 swap(交换元素) 操作,因为交换两个元素的本质就是 获取元素 + 修改元素,而我在其中添加 drop 指令的目的则是使可视化过程更加具体,例如 pick 指令会将其选定的元素高亮,那么 drop 指令就可以取消该元素的高亮行为。
|
||||||
|
|
||||||
|
我们会先选取一种编程语言(例如 TypeScript)来实现这套协议,在实现的过程中,需要考虑到未来将添加其他编程语言的支持,因此需要考虑到不同编程语言之间的差异,例如语法/类型系统差异,进而反过来优化这套协议,以使其能够更好地支持不同的编程语言,这是一个双向的过程。
|
||||||
|
|
||||||
|
当我们实现了这套协议后,就形成了一套 SDK,用户可以在平台中标记想要记录的数据结构(注册跟踪器),并调用 SDK 提供的 API 来记录数据结构的变化,当代码被编译运行后,就能够自然地获取数据结构的变化过程(序列化为 JSON)。
|
||||||
|
|
||||||
|
所以本项目的最终目标就是设计这一套语言无关的协议,并在多个主流编程语言上实现该协议。
|
||||||
19
.trae/rules/tracer-type.md
Normal file
19
.trae/rules/tracer-type.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
## Tracer 是什么?
|
||||||
|
|
||||||
|
Tracer 代表一个数据结构变化的跟踪器,用户可以通过调用 Tracer 提供的 API 来记录数据结构的变化。每当用户想要记录一个数据结构的变化时,就需要创建一个对应的 Tracer。这种将数据结构变化的记录留给用户的设计,使得用户可以在算法的实现中灵活地记录数据结构的变化,从而降低对原有算法代码逻辑的侵入性,同时也在一定程度上提高了可视化效果的灵活度,用户可以自由控制记录数据结构变化的时机。
|
||||||
|
|
||||||
|
## Tracer 类型
|
||||||
|
|
||||||
|
- ArrayTracer: 顺序表(数组)
|
||||||
|
- StackTracer: 栈
|
||||||
|
- QueueTracer: 队列
|
||||||
|
- MatrixTracer: 矩阵
|
||||||
|
- SortTracer: 排序算法(也许可以合并到 ArrayTracer,暂时不确定)
|
||||||
|
- LinkTracer: 链表
|
||||||
|
- TreeTracer: 树
|
||||||
|
- GraphTracer: 图
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- LogTracer: 日志
|
||||||
|
- ControlTracer: 控制
|
||||||
15
README.md
15
README.md
@@ -1,15 +0,0 @@
|
|||||||
# structrail-design
|
|
||||||
|
|
||||||
To install dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bun install
|
|
||||||
```
|
|
||||||
|
|
||||||
To run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bun run index.ts
|
|
||||||
```
|
|
||||||
|
|
||||||
This project was created using `bun init` in bun v1.2.23. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
|
||||||
29
bun.lock
29
bun.lock
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"name": "structrail-design",
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/bun": "latest",
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@types/bun": ["@types/bun@1.2.23", "", { "dependencies": { "bun-types": "1.2.23" } }, "sha512-le8ueOY5b6VKYf19xT3McVbXqLqmxzPXHsQT/q9JHgikJ2X22wyTW3g3ohz2ZMnp7dod6aduIiq8A14Xyimm0A=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.7.1", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q=="],
|
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
|
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.2.23", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-R9f0hKAZXgFU3mlrA0YpE/fiDvwV0FT9rORApt2aQVWSuJDzZOyB5QLc0N/4HF57CS8IXJ6+L5E4W1bW6NS2Aw=="],
|
|
||||||
|
|
||||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
7
index.ts
7
index.ts
@@ -1,7 +0,0 @@
|
|||||||
import { ArrayTracer } from "./src/tracers.ts";
|
|
||||||
|
|
||||||
const arrayTracer = ArrayTracer.define<number>({
|
|
||||||
description: "Array Tracer",
|
|
||||||
});
|
|
||||||
|
|
||||||
arrayTracer.preset([1, 2, 3]);
|
|
||||||
34
tracers.ts/.gitignore
vendored
Normal file
34
tracers.ts/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# dependencies (bun install)
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# output
|
||||||
|
out
|
||||||
|
dist
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# code coverage
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# logs
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.eslintcache
|
||||||
|
.cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
15
tracers.ts/README.md
Normal file
15
tracers.ts/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# tracers.ts
|
||||||
|
|
||||||
|
To install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run src/index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This project was created using `bun init` in bun v1.3.4. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
||||||
26
tracers.ts/bun.lock
Normal file
26
tracers.ts/bun.lock
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "tracers.ts",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@25.2.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "structrail-design",
|
"name": "tracers.ts",
|
||||||
"module": "index.ts",
|
"module": "src/index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
1
tracers.ts/src/context/index.ts
Normal file
1
tracers.ts/src/context/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './tracer-context';
|
||||||
22
tracers.ts/src/context/tracer-context.ts
Normal file
22
tracers.ts/src/context/tracer-context.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import type { TracerCommand } from '../types';
|
||||||
|
|
||||||
|
const createTracerContext = () => {
|
||||||
|
const commands: TracerCommand[] = [];
|
||||||
|
|
||||||
|
const getTracerContext = () => {
|
||||||
|
const command = (command: TracerCommand) => {
|
||||||
|
commands.push(command);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
commands,
|
||||||
|
command,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
getTracerContext,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const { getTracerContext } = createTracerContext();
|
||||||
20
tracers.ts/src/index.ts
Normal file
20
tracers.ts/src/index.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getTracerContext } from './context';
|
||||||
|
import {
|
||||||
|
createArrayTracer,
|
||||||
|
createControlTracer,
|
||||||
|
createLogTracer,
|
||||||
|
} from './tracers';
|
||||||
|
|
||||||
|
const logTracer = createLogTracer({ description: 'LogTracer' });
|
||||||
|
const controlTracer = createControlTracer({ description: 'ControlTracer' });
|
||||||
|
|
||||||
|
const arrayTracer = createArrayTracer({
|
||||||
|
description: 'ArrayTracer',
|
||||||
|
array: [1, 2, 3],
|
||||||
|
});
|
||||||
|
|
||||||
|
arrayTracer.patch(0, 100);
|
||||||
|
|
||||||
|
controlTracer.step();
|
||||||
|
|
||||||
|
console.log(getTracerContext().commands);
|
||||||
90
tracers.ts/src/tracers/array-tracer.ts
Normal file
90
tracers.ts/src/tracers/array-tracer.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import { getTracerContext } from '../context';
|
||||||
|
import type { JsonValue } from '../types';
|
||||||
|
|
||||||
|
interface ArrayTracerCreateOptions<T extends JsonValue[]> {
|
||||||
|
description?: string;
|
||||||
|
array?: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createArrayTracer = <T extends JsonValue[]>(
|
||||||
|
options: ArrayTracerCreateOptions<T>,
|
||||||
|
) => {
|
||||||
|
const { description = 'ArrayTracer', array } = options;
|
||||||
|
const tracer = crypto.randomUUID();
|
||||||
|
|
||||||
|
const { command } = getTracerContext();
|
||||||
|
|
||||||
|
command({
|
||||||
|
type: 'ArrayTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'create',
|
||||||
|
params: {
|
||||||
|
description: description,
|
||||||
|
array: array,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const scale = (size: number) => {
|
||||||
|
command({
|
||||||
|
type: 'ArrayTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'scale',
|
||||||
|
params: {
|
||||||
|
size: size,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const pick = (index: number) => {
|
||||||
|
command({
|
||||||
|
type: 'ArrayTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'pick',
|
||||||
|
params: {
|
||||||
|
index: index,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const drop = (index: number) => {
|
||||||
|
command({
|
||||||
|
type: 'ArrayTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'drop',
|
||||||
|
params: {
|
||||||
|
index: index,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const patch = (index: number, value: T[number]) => {
|
||||||
|
command({
|
||||||
|
type: 'ArrayTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'patch',
|
||||||
|
params: {
|
||||||
|
index: index,
|
||||||
|
value: value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const unset = (index: number) => {
|
||||||
|
command({
|
||||||
|
type: 'ArrayTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'unset',
|
||||||
|
params: {
|
||||||
|
index: index,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
scale,
|
||||||
|
pick,
|
||||||
|
drop,
|
||||||
|
patch,
|
||||||
|
unset,
|
||||||
|
};
|
||||||
|
};
|
||||||
81
tracers.ts/src/tracers/control-tracer.ts
Normal file
81
tracers.ts/src/tracers/control-tracer.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { getTracerContext } from '../context';
|
||||||
|
|
||||||
|
export const getLocation = (targetFn?: Function) => {
|
||||||
|
const stackObject: { stack: string } = { stack: '' };
|
||||||
|
Error.captureStackTrace(stackObject, targetFn ?? getLocation);
|
||||||
|
const { stack } = stackObject;
|
||||||
|
// D:\Projects\structrail-sdk\tracers.ts\src\index.ts:23:18
|
||||||
|
const location = stack.split('\n').at(1)?.trim().split(' ').at(1)?.trim();
|
||||||
|
// console.log(location);
|
||||||
|
if (!location) return null;
|
||||||
|
|
||||||
|
const matches = location?.match(/:(\d+):?(\d+)?\)?$/);
|
||||||
|
// console.log(matches);
|
||||||
|
const file = location?.replace(matches?.at(0) ?? '', '');
|
||||||
|
// console.log(file);
|
||||||
|
const line = parseInt(matches?.at(1) ?? '0');
|
||||||
|
// console.log(line);
|
||||||
|
|
||||||
|
return {
|
||||||
|
file,
|
||||||
|
line,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ControlTracerCreateOptions {
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createControlTracer = (options: ControlTracerCreateOptions) => {
|
||||||
|
const { description = 'ControlTracer' } = options;
|
||||||
|
const tracer = crypto.randomUUID();
|
||||||
|
|
||||||
|
const { command } = getTracerContext();
|
||||||
|
|
||||||
|
command({
|
||||||
|
type: 'ControlTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'create',
|
||||||
|
params: {
|
||||||
|
description: description,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const step = (...range: (number | [number, number])[]) => {
|
||||||
|
const { line: currentLine } = getLocation(step) ?? {};
|
||||||
|
if (!currentLine) return;
|
||||||
|
// console.log(currentLine);
|
||||||
|
|
||||||
|
const linesSet = new Set<number>([currentLine]);
|
||||||
|
range.forEach((item) => {
|
||||||
|
if (Array.isArray(item) && item.length === 2) {
|
||||||
|
const [offsetStart, offsetEnd] = item;
|
||||||
|
const lineStart = currentLine - offsetStart;
|
||||||
|
const lineEnd = currentLine - offsetEnd;
|
||||||
|
const lineMin = Math.min(lineStart, lineEnd);
|
||||||
|
const lineMax = Math.max(lineStart, lineEnd);
|
||||||
|
for (let line = lineMin; line <= lineMax; line++) {
|
||||||
|
linesSet.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof item === 'number') {
|
||||||
|
const line = item;
|
||||||
|
linesSet.add(currentLine - line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const lines = Array.from(linesSet).sort((line1, line2) => line1 - line2);
|
||||||
|
|
||||||
|
command({
|
||||||
|
type: 'ControlTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'step',
|
||||||
|
params: {
|
||||||
|
lines: lines,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
step,
|
||||||
|
};
|
||||||
|
};
|
||||||
3
tracers.ts/src/tracers/index.ts
Normal file
3
tracers.ts/src/tracers/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './array-tracer';
|
||||||
|
export * from './control-tracer';
|
||||||
|
export * from './log-tracer';
|
||||||
44
tracers.ts/src/tracers/log-tracer.ts
Normal file
44
tracers.ts/src/tracers/log-tracer.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { getTracerContext } from '../context';
|
||||||
|
|
||||||
|
interface LogTracerCreateOptions {
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createLogTracer = (options: LogTracerCreateOptions) => {
|
||||||
|
const { description = 'LogTracer' } = options;
|
||||||
|
const tracer = crypto.randomUUID();
|
||||||
|
|
||||||
|
const { command } = getTracerContext();
|
||||||
|
|
||||||
|
command({
|
||||||
|
type: 'LogTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'create',
|
||||||
|
params: {
|
||||||
|
description: description,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const log = (...args: unknown[]) => {
|
||||||
|
const parsed = args.map((arg) => {
|
||||||
|
if (typeof arg === 'string') {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
return JSON.stringify(arg);
|
||||||
|
});
|
||||||
|
const message = parsed.join(' ');
|
||||||
|
|
||||||
|
command({
|
||||||
|
type: 'LogTracer',
|
||||||
|
tracer: tracer,
|
||||||
|
action: 'log',
|
||||||
|
params: {
|
||||||
|
message: message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
log,
|
||||||
|
};
|
||||||
|
};
|
||||||
57
tracers.ts/src/types/array-tracer.ts
Normal file
57
tracers.ts/src/types/array-tracer.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import type { BaseTracerCommand, JsonValue } from './common';
|
||||||
|
|
||||||
|
type BaseArrayTracerCommand = BaseTracerCommand & {
|
||||||
|
type: 'ArrayTracer';
|
||||||
|
};
|
||||||
|
|
||||||
|
type ArrayTracerCreateCommand = BaseArrayTracerCommand & {
|
||||||
|
action: 'create';
|
||||||
|
params: {
|
||||||
|
description: string;
|
||||||
|
array?: JsonValue[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type ArrayTracerScaleCommand = BaseArrayTracerCommand & {
|
||||||
|
action: 'scale';
|
||||||
|
params: {
|
||||||
|
size: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type ArrayTracerPickCommand = BaseArrayTracerCommand & {
|
||||||
|
action: 'pick';
|
||||||
|
params: {
|
||||||
|
index: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type ArrayTracerDropCommand = BaseArrayTracerCommand & {
|
||||||
|
action: 'drop';
|
||||||
|
params: {
|
||||||
|
index: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type ArrayTracerPatchCommand = BaseArrayTracerCommand & {
|
||||||
|
action: 'patch';
|
||||||
|
params: {
|
||||||
|
index: number;
|
||||||
|
value: JsonValue;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type ArrayTracerUnsetCommand = BaseArrayTracerCommand & {
|
||||||
|
action: 'unset';
|
||||||
|
params: {
|
||||||
|
index: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ArrayTracerCommand =
|
||||||
|
| ArrayTracerCreateCommand
|
||||||
|
| ArrayTracerScaleCommand
|
||||||
|
| ArrayTracerPickCommand
|
||||||
|
| ArrayTracerDropCommand
|
||||||
|
| ArrayTracerPatchCommand
|
||||||
|
| ArrayTracerUnsetCommand;
|
||||||
8
tracers.ts/src/types/command.ts
Normal file
8
tracers.ts/src/types/command.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { ArrayTracerCommand } from './array-tracer';
|
||||||
|
import type { ControlTracerCommand } from './control-tracer';
|
||||||
|
import type { LogTracerCommand } from './log-tracer';
|
||||||
|
|
||||||
|
export type TracerCommand =
|
||||||
|
| ArrayTracerCommand
|
||||||
|
| LogTracerCommand
|
||||||
|
| ControlTracerCommand;
|
||||||
16
tracers.ts/src/types/common.ts
Normal file
16
tracers.ts/src/types/common.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export type JsonValue =
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null
|
||||||
|
| JsonValue[]
|
||||||
|
| { [key: string]: JsonValue };
|
||||||
|
|
||||||
|
export type TracerType = 'ArrayTracer' | 'LogTracer' | 'ControlTracer';
|
||||||
|
|
||||||
|
export type TracerId = ReturnType<typeof crypto.randomUUID>;
|
||||||
|
|
||||||
|
export type BaseTracerCommand = {
|
||||||
|
type: TracerType;
|
||||||
|
tracer: TracerId;
|
||||||
|
};
|
||||||
23
tracers.ts/src/types/control-tracer.ts
Normal file
23
tracers.ts/src/types/control-tracer.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import type { BaseTracerCommand } from './common';
|
||||||
|
|
||||||
|
type BaseControlTracerCommand = BaseTracerCommand & {
|
||||||
|
type: 'ControlTracer';
|
||||||
|
};
|
||||||
|
|
||||||
|
type ControlTracerCreateCommand = BaseControlTracerCommand & {
|
||||||
|
action: 'create';
|
||||||
|
params: {
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type ControlTracerStepCommand = BaseControlTracerCommand & {
|
||||||
|
action: 'step';
|
||||||
|
params: {
|
||||||
|
lines: number[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ControlTracerCommand =
|
||||||
|
| ControlTracerCreateCommand
|
||||||
|
| ControlTracerStepCommand;
|
||||||
5
tracers.ts/src/types/index.ts
Normal file
5
tracers.ts/src/types/index.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export * from './array-tracer';
|
||||||
|
export * from './command';
|
||||||
|
export * from './common';
|
||||||
|
export * from './control-tracer';
|
||||||
|
export * from './log-tracer';
|
||||||
21
tracers.ts/src/types/log-tracer.ts
Normal file
21
tracers.ts/src/types/log-tracer.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { BaseTracerCommand } from "./common";
|
||||||
|
|
||||||
|
type BaseLogTracerCommand = BaseTracerCommand & {
|
||||||
|
type: 'LogTracer';
|
||||||
|
};
|
||||||
|
|
||||||
|
type LogTracerCreateCommand = BaseLogTracerCommand & {
|
||||||
|
action: 'create';
|
||||||
|
params: {
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type LogTracerLogCommand = BaseLogTracerCommand & {
|
||||||
|
action: 'log';
|
||||||
|
params: {
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LogTracerCommand = LogTracerCreateCommand | LogTracerLogCommand;
|
||||||
Reference in New Issue
Block a user