@actiondock/testing 2.0.11 → 2.0.12

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.
@@ -0,0 +1,137 @@
1
+ import { ActionRunner, type ExecutionService, type ExecutionStartOptions, InMemoryEventSink, type ProjectConfig } from "@actiondock/core";
2
+ import { type ActionDefinition, type Config, type ExecutionEvent, type ExecutionResult, type Logger, MemoryLogger, type RuntimeError, type StateStore } from "@actiondock/sdk";
3
+ import { FakeClock } from "./clock";
4
+ import { MockProcessExecutor } from "./process";
5
+ import { MemoryStorage } from "./storage";
6
+ /**
7
+ * 规范化运行时错误异常类。
8
+ * 当 run 方法执行失败时抛出,完整实现 RuntimeError 契约。
9
+ */
10
+ export declare class ActionRuntimeError extends Error implements RuntimeError {
11
+ code: string;
12
+ details?: unknown;
13
+ cause?: unknown;
14
+ constructor(error: RuntimeError);
15
+ }
16
+ /**
17
+ * 带有写入和调试能力的配置接口。
18
+ */
19
+ export interface TestConfig extends Config {
20
+ /** 写入配置键值 */
21
+ set(key: string, value: unknown): void;
22
+ /** 删除指定配置键 */
23
+ delete(key: string): boolean;
24
+ /** 列出所有已存储配置项 */
25
+ list(): Record<string, unknown>;
26
+ }
27
+ /**
28
+ * 测试配置管理器实现。
29
+ */
30
+ export declare class TestConfigStore implements TestConfig {
31
+ private runtimeConfig;
32
+ private storage;
33
+ constructor(storage: MemoryStorage, projectConfig?: ProjectConfig, overrides?: Record<string, unknown>);
34
+ get<T = unknown>(key: string): T | undefined;
35
+ get<T = unknown>(key: string, defaultValue: T): T;
36
+ has(key: string): boolean;
37
+ set(key: string, value: unknown): void;
38
+ delete(key: string): boolean;
39
+ list(): Record<string, unknown>;
40
+ }
41
+ /**
42
+ * 测试事件接收器实现。
43
+ * 记录执行期间产生的所有事件并支持历史检索。
44
+ */
45
+ export declare class TestEventSink extends InMemoryEventSink {
46
+ private allEvents;
47
+ private sequenceCounter;
48
+ /** 获取下一个单调自增序号 */
49
+ nextSequence(): number;
50
+ emit(event: ExecutionEvent): void;
51
+ /**
52
+ * 检索历史事件列表。
53
+ *
54
+ * @param runId 可选运行标识筛选
55
+ */
56
+ getEvents(runId?: string): ExecutionEvent[];
57
+ /**
58
+ * 清理所有捕获的事件记录。
59
+ */
60
+ clearAll(): void;
61
+ }
62
+ /**
63
+ * 测试运行时初始化选项。
64
+ */
65
+ export interface TestRuntimeOptions {
66
+ /** 绑定的 Package 标识 */
67
+ packageId?: string;
68
+ /** 初始注入的配置键值映射 */
69
+ config?: Record<string, unknown>;
70
+ /** 运行级别临时配置覆写字典 */
71
+ configOverrides?: Record<string, unknown>;
72
+ /** 初始注入的状态键值映射 */
73
+ state?: Record<string, unknown>;
74
+ /** 可选注入的模拟时钟实例 */
75
+ clock?: FakeClock;
76
+ /** 可选注入的模拟进程执行器 */
77
+ process?: MockProcessExecutor;
78
+ /** 可选注入的日志记录器(默认使用 MemoryLogger) */
79
+ logger?: Logger;
80
+ /** 可选注入的底层存储实例 */
81
+ storage?: MemoryStorage;
82
+ /** 项目静态配置元数据 */
83
+ projectConfig?: ProjectConfig;
84
+ /** 预注册的 Action 动作列表 */
85
+ actions?: ActionDefinition[] | Record<string, ActionDefinition> | Map<string, ActionDefinition>;
86
+ }
87
+ /**
88
+ * 测试运行时接口。
89
+ */
90
+ export interface TestRuntime {
91
+ /** 调试配置接口 */
92
+ config: TestConfig;
93
+ /** 调试状态持久化接口 */
94
+ state: StateStore;
95
+ /** 调试模拟时钟接口 */
96
+ clock: FakeClock;
97
+ /** 调试模拟进程执行接口 */
98
+ process: MockProcessExecutor;
99
+ /** 调试执行事件捕获接口 */
100
+ events: TestEventSink;
101
+ /** 调试日志记录捕获接口 */
102
+ logger: MemoryLogger;
103
+ /** 底层存储引擎 */
104
+ storage: MemoryStorage;
105
+ /** 统一执行服务 */
106
+ executionService: ExecutionService;
107
+ /** 核心执行器引擎(向后兼容保留) */
108
+ runner: ActionRunner;
109
+ /** 注册 Action 动作定义 */
110
+ registerAction(action: ActionDefinition): void;
111
+ /** 获取已注册的 Action 动作定义 */
112
+ getAction(id: string): ActionDefinition | undefined;
113
+ /** 列出已注册的所有 Action 动作定义 */
114
+ listActions(): ActionDefinition[];
115
+ /**
116
+ * 执行 Action 并直接返回业务结果数据,失败时抛出 ActionRuntimeError 规范化异常。
117
+ *
118
+ * @param action Action 动作定义或已注册标识
119
+ * @param input 输入参数数据
120
+ */
121
+ run<I = unknown, O = unknown>(action: ActionDefinition<I, O> | string, input?: I): Promise<O>;
122
+ /**
123
+ * 执行 Action 并返回完整的 ExecutionResult 信封结构。
124
+ *
125
+ * @param action Action 动作定义或已注册标识
126
+ * @param input 输入参数数据
127
+ * @param options 可选执行控制参数
128
+ */
129
+ execute<I = unknown, O = unknown>(action: ActionDefinition<I, O> | string, input?: I, options?: ExecutionStartOptions): Promise<ExecutionResult<O>>;
130
+ }
131
+ /**
132
+ * 创建全功能测试运行时实例。
133
+ * 基于统一 ExecutionService 协调执行全生命周期,并暴露配置、状态、时钟、进程与事件等调试接口。
134
+ *
135
+ * @param options 测试运行时选项
136
+ */
137
+ export declare function createTestRuntime(options?: TestRuntimeOptions): TestRuntime;
@@ -0,0 +1,20 @@
1
+ import { type Clock, SqliteRuntimeStorage, type SqliteDriver } from "@actiondock/core";
2
+ /**
3
+ * 内存运行时存储初始化选项。
4
+ */
5
+ export interface MemoryStorageOptions {
6
+ /** 绑定的 Package 标识,默认为 test-pkg */
7
+ packageId?: string;
8
+ /** 可选注入的时间提供器,便于与模拟时钟联动 */
9
+ clock?: Clock;
10
+ /** 可选显式注入的底层 SQLite 驱动 */
11
+ driver?: SqliteDriver;
12
+ }
13
+ /**
14
+ * 统一内存运行时存储实现。
15
+ * 基于 SqliteRuntimeStorage 构建,默认使用 :memory: 内存数据库并对接虚拟时钟,
16
+ * 确保与生产环境具备完全相同的配置优先级、状态过期契约与运行终态行为。
17
+ */
18
+ export declare class MemoryStorage extends SqliteRuntimeStorage {
19
+ constructor(options?: MemoryStorageOptions);
20
+ }
package/package.json CHANGED
@@ -1,37 +1,38 @@
1
1
  {
2
2
  "name": "@actiondock/testing",
3
- "version": "2.0.11",
3
+ "version": "2.0.12",
4
4
  "description": "ActionDock Test Runtime for testing Actions with real Core execution semantics",
5
5
  "type": "module",
6
- "main": "./src/index.ts",
7
- "module": "./src/index.ts",
8
- "types": "./src/index.ts",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "import": "./src/index.ts",
12
- "types": "./src/index.ts"
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
13
14
  }
14
15
  },
15
16
  "files": [
16
- "src",
17
+ "dist",
17
18
  "README.md"
18
19
  ],
19
20
  "engines": {
20
- "node": ">=22.12.0"
21
+ "node": ">=22.13.0"
21
22
  },
22
23
  "publishConfig": {
23
24
  "access": "public",
24
25
  "registry": "https://registry.npmjs.org/"
25
26
  },
26
27
  "scripts": {
28
+ "build": "bun run ../../scripts/build.ts",
27
29
  "test": "bun test"
28
30
  },
29
31
  "dependencies": {
30
- "@actiondock/core": "^2.0.11",
31
- "@actiondock/sdk": "^2.0.11"
32
+ "@actiondock/core": "^2.0.12",
33
+ "@actiondock/sdk": "^2.0.12"
32
34
  },
33
35
  "devDependencies": {
34
- "@types/bun": "latest",
35
36
  "typescript": "^5.7.0"
36
37
  },
37
38
  "keywords": [
package/src/clock.ts DELETED
@@ -1,136 +0,0 @@
1
- import type { Clock } from "@actiondock/core";
2
-
3
- /**
4
- * 待触发的计划计时器项。
5
- */
6
- interface ScheduledSleep {
7
- id: number;
8
- targetMonotonic: number;
9
- targetNow: number;
10
- resolve: () => void;
11
- reject: (err: unknown) => void;
12
- }
13
-
14
- /**
15
- * 模拟时钟初始化选项。
16
- */
17
- export interface FakeClockOptions {
18
- /** 初始时间戳或日期对象 */
19
- now?: Date | number | string;
20
- /** 初始单调时间戳毫秒数 */
21
- startMonotonic?: number;
22
- }
23
-
24
- /**
25
- * 确定性测试模拟时钟实现。
26
- * 遵循 Clock 接口契约,支持手动单调推进时间并调度计时器。
27
- */
28
- export class FakeClock implements Clock {
29
- private currentNow: number;
30
- private currentMonotonic: number;
31
- private nextTimerId = 1;
32
- private pendingSleeps: ScheduledSleep[] = [];
33
-
34
- constructor(options: FakeClockOptions = {}) {
35
- if (options.now !== undefined) {
36
- this.currentNow = new Date(options.now).getTime();
37
- } else {
38
- this.currentNow = Date.now();
39
- }
40
- this.currentMonotonic = options.startMonotonic ?? 0;
41
- }
42
-
43
- /**
44
- * 获取当前模拟墙上时间。
45
- */
46
- now(): Date {
47
- return new Date(this.currentNow);
48
- }
49
-
50
- /**
51
- * 获取当前模拟单调时间戳(毫秒)。
52
- */
53
- monotonic(): number {
54
- return this.currentMonotonic;
55
- }
56
-
57
- /**
58
- * 异步休眠指定毫秒。
59
- * 等待通过 advance 方法推进时间至目标时刻后完成。
60
- *
61
- * @param ms 休眠毫秒数
62
- */
63
- sleep(ms: number): Promise<void> {
64
- if (ms <= 0) {
65
- return Promise.resolve();
66
- }
67
-
68
- return new Promise<void>((resolve, reject) => {
69
- const targetMonotonic = this.currentMonotonic + ms;
70
- const targetNow = this.currentNow + ms;
71
- this.pendingSleeps.push({
72
- id: this.nextTimerId++,
73
- targetMonotonic,
74
- targetNow,
75
- resolve,
76
- reject,
77
- });
78
- this.pendingSleeps.sort((a, b) => a.targetMonotonic - b.targetMonotonic);
79
- });
80
- }
81
-
82
- /**
83
- * 手动向前推进指定毫秒时间。
84
- * 严格按时间戳递增顺序触发并完成所有到期的休眠计时器。
85
- *
86
- * @param ms 推进的毫秒数
87
- */
88
- async advance(ms: number): Promise<void> {
89
- if (ms < 0) {
90
- throw new Error("Cannot advance clock by negative time");
91
- }
92
- if (ms === 0) {
93
- await Promise.resolve();
94
- return;
95
- }
96
-
97
- const destinationMonotonic = this.currentMonotonic + ms;
98
- const destinationNow = this.currentNow + ms;
99
-
100
- while (this.pendingSleeps.length > 0) {
101
- const nextSleep = this.pendingSleeps[0];
102
- if (nextSleep.targetMonotonic > destinationMonotonic) {
103
- break;
104
- }
105
-
106
- this.pendingSleeps.shift();
107
- this.currentMonotonic = nextSleep.targetMonotonic;
108
- this.currentNow = nextSleep.targetNow;
109
- nextSleep.resolve();
110
-
111
- await Promise.resolve();
112
- }
113
-
114
- this.currentMonotonic = destinationMonotonic;
115
- this.currentNow = destinationNow;
116
- await Promise.resolve();
117
- }
118
-
119
- /**
120
- * 获取当前等待中的计时器数量。
121
- */
122
- get pendingCount(): number {
123
- return this.pendingSleeps.length;
124
- }
125
-
126
- /**
127
- * 清除并取消所有等待中的计时器。
128
- */
129
- clear(): void {
130
- const sleeps = this.pendingSleeps;
131
- this.pendingSleeps = [];
132
- for (const item of sleeps) {
133
- item.reject(new Error("FakeClock timer cancelled"));
134
- }
135
- }
136
- }
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from "./clock";
2
- export * from "./process";
3
- export * from "./storage";
4
- export * from "./runtime";