@akashic/headless-driver 2.6.3 → 2.7.1
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/lib/play/AMFlowClientManager.d.ts +7 -0
- package/lib/play/AMFlowClientManager.js +12 -0
- package/lib/play/PlayManager.d.ts +2 -1
- package/lib/play/PlayManager.js +3 -1
- package/lib/play/amflow/AMFlowClient.d.ts +1 -1
- package/lib/play/amflow/AMFlowClient.js +43 -30
- package/lib/play/amflow/AMFlowStore.d.ts +18 -1
- package/lib/play/amflow/AMFlowStore.js +31 -2
- package/package.json +2 -2
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { Permission } from "@akashic/amflow";
|
|
2
2
|
import { AMFlowClient } from "./amflow/AMFlowClient";
|
|
3
|
+
import type { AMFlowStoreOptions } from "./amflow/AMFlowStore";
|
|
3
4
|
export declare class AMFlowClientManager {
|
|
4
5
|
/**
|
|
5
6
|
* PlayId と AMFlowStore を紐付けるマップ情報。
|
|
6
7
|
*/
|
|
7
8
|
private storeMap;
|
|
9
|
+
/**
|
|
10
|
+
* 対象の PlayID の オプションを設定する。
|
|
11
|
+
* @param playId PlayID
|
|
12
|
+
* @param options オプション
|
|
13
|
+
*/
|
|
14
|
+
setAMFlowStoreOptions(playId: string, options: AMFlowStoreOptions | null): void;
|
|
8
15
|
/**
|
|
9
16
|
* 対象の PlayID の AMFlowClient を作成する。
|
|
10
17
|
* @param playId PlayID
|
|
@@ -10,6 +10,18 @@ class AMFlowClientManager {
|
|
|
10
10
|
*/
|
|
11
11
|
this.storeMap = new Map();
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* 対象の PlayID の オプションを設定する。
|
|
15
|
+
* @param playId PlayID
|
|
16
|
+
* @param options オプション
|
|
17
|
+
*/
|
|
18
|
+
setAMFlowStoreOptions(playId, options) {
|
|
19
|
+
let store = this.storeMap.get(playId);
|
|
20
|
+
if (!store) {
|
|
21
|
+
store = this.createAMFlowStore(playId);
|
|
22
|
+
}
|
|
23
|
+
store.setOptions(options);
|
|
24
|
+
}
|
|
13
25
|
/**
|
|
14
26
|
* 対象の PlayID の AMFlowClient を作成する。
|
|
15
27
|
* @param playId PlayID
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Permission } from "@akashic/amflow";
|
|
2
|
+
import type { AMFlowStoreOptions } from "./amflow";
|
|
2
3
|
import type { AMFlowClient } from "./amflow/AMFlowClient";
|
|
3
4
|
import type { DumpedPlaylog } from "./amflow/types";
|
|
4
5
|
import type { ContentLocation } from "./Content";
|
|
@@ -18,7 +19,7 @@ export declare class PlayManager {
|
|
|
18
19
|
* Play を作成する。
|
|
19
20
|
* @param playLocation パラメータ
|
|
20
21
|
*/
|
|
21
|
-
createPlay(playLocation: PlayManagerParameters, playlog?: DumpedPlaylog): Promise<string>;
|
|
22
|
+
createPlay(playLocation: PlayManagerParameters, playlog?: DumpedPlaylog, options?: AMFlowStoreOptions): Promise<string>;
|
|
22
23
|
/**
|
|
23
24
|
* Play を削除する。
|
|
24
25
|
* @param playID PlayID
|
package/lib/play/PlayManager.js
CHANGED
|
@@ -24,10 +24,12 @@ class PlayManager {
|
|
|
24
24
|
* Play を作成する。
|
|
25
25
|
* @param playLocation パラメータ
|
|
26
26
|
*/
|
|
27
|
-
createPlay(playLocation, playlog) {
|
|
27
|
+
createPlay(playLocation, playlog, options) {
|
|
28
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
29
|
const playId = `${this.nextPlayId++}`;
|
|
30
30
|
this.plays.push(Object.assign({ playId, status: "running", createdAt: Date.now(), lastSuspendedAt: null }, playLocation));
|
|
31
|
+
if (options)
|
|
32
|
+
this.amflowClientManager.setAMFlowStoreOptions(playId, options);
|
|
31
33
|
if (playlog) {
|
|
32
34
|
const amflow = this.createAMFlow(playId);
|
|
33
35
|
amflow.setDumpedPlaylog(playlog);
|
|
@@ -15,7 +15,7 @@ export declare class AMFlowClient implements AMFlow {
|
|
|
15
15
|
private permission;
|
|
16
16
|
private tickHandlers;
|
|
17
17
|
private eventHandlers;
|
|
18
|
-
private
|
|
18
|
+
private waitingStartPointRequests;
|
|
19
19
|
constructor(playId: string, store: AMFlowStore);
|
|
20
20
|
open(playId: string, callback?: (error: Error | null) => void): void;
|
|
21
21
|
close(callback?: (error: Error | null) => void): void;
|
|
@@ -14,14 +14,39 @@ class AMFlowClient {
|
|
|
14
14
|
this.permission = null;
|
|
15
15
|
this.tickHandlers = [];
|
|
16
16
|
this.eventHandlers = [];
|
|
17
|
-
this.
|
|
17
|
+
this.waitingStartPointRequests = [];
|
|
18
|
+
this.handleSendTick = (tick) => {
|
|
19
|
+
this.tickHandlers.forEach((h) => h(tick));
|
|
20
|
+
};
|
|
21
|
+
this.handleSendEvent = (event) => {
|
|
22
|
+
this.eventHandlers.forEach((h) => h(event));
|
|
23
|
+
};
|
|
24
|
+
this.handlePutStartPoint = (startPoint) => {
|
|
25
|
+
this.onPutStartPoint.fire(startPoint);
|
|
26
|
+
if (this.waitingStartPointRequests.length) {
|
|
27
|
+
const remains = [];
|
|
28
|
+
this.waitingStartPointRequests.forEach((req) => {
|
|
29
|
+
const { frame, timestamp } = req.options;
|
|
30
|
+
if ((frame != null && startPoint.frame <= frame) ||
|
|
31
|
+
(timestamp != null && startPoint.timestamp < timestamp) ||
|
|
32
|
+
(frame == null && timestamp == null && startPoint.frame === 0)) {
|
|
33
|
+
req.callback(null, startPoint);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (startPoint.frame === 0) {
|
|
37
|
+
req.callback((0, ErrorFactory_1.createError)("bad_request"));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
remains.push(req);
|
|
41
|
+
});
|
|
42
|
+
this.waitingStartPointRequests = remains;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
18
45
|
this.playId = playId;
|
|
19
46
|
this.store = store;
|
|
20
47
|
}
|
|
21
48
|
open(playId, callback) {
|
|
22
49
|
(0, Logger_1.getSystemLogger)().info("AMFlowClient#open()", playId);
|
|
23
|
-
this.store.sendEventTrigger.add(this.handleSendEvent, this);
|
|
24
|
-
this.store.sendTickTrigger.add(this.handleSendTick, this);
|
|
25
50
|
this.store.putStartPointTrigger.add(this.handlePutStartPoint, this);
|
|
26
51
|
this.state = "open";
|
|
27
52
|
if (callback) {
|
|
@@ -101,6 +126,8 @@ class AMFlowClient {
|
|
|
101
126
|
throw (0, ErrorFactory_1.createError)("permission_error", "Permission denied");
|
|
102
127
|
}
|
|
103
128
|
this.tickHandlers.push(handler);
|
|
129
|
+
if (this.tickHandlers.length === 1)
|
|
130
|
+
this.store.onTick(this.handleSendTick);
|
|
104
131
|
}
|
|
105
132
|
offTick(handler) {
|
|
106
133
|
if (this.state !== "open") {
|
|
@@ -110,6 +137,8 @@ class AMFlowClient {
|
|
|
110
137
|
throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
|
|
111
138
|
}
|
|
112
139
|
this.tickHandlers = this.tickHandlers.filter((h) => h !== handler);
|
|
140
|
+
if (this.tickHandlers.length === 0)
|
|
141
|
+
this.store.offTick(this.handleSendTick);
|
|
113
142
|
}
|
|
114
143
|
sendEvent(event) {
|
|
115
144
|
if (this.state !== "open") {
|
|
@@ -138,12 +167,8 @@ class AMFlowClient {
|
|
|
138
167
|
throw (0, ErrorFactory_1.createError)("permission_error", "Permission denied");
|
|
139
168
|
}
|
|
140
169
|
this.eventHandlers.push(handler);
|
|
141
|
-
if (
|
|
142
|
-
this.
|
|
143
|
-
this.unconsumedEvents.forEach((ev) => h(ev));
|
|
144
|
-
});
|
|
145
|
-
this.unconsumedEvents = [];
|
|
146
|
-
}
|
|
170
|
+
if (this.eventHandlers.length === 1)
|
|
171
|
+
this.store.onEvent(this.handleSendEvent);
|
|
147
172
|
}
|
|
148
173
|
offEvent(handler) {
|
|
149
174
|
if (this.state !== "open") {
|
|
@@ -153,6 +178,8 @@ class AMFlowClient {
|
|
|
153
178
|
throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
|
|
154
179
|
}
|
|
155
180
|
this.eventHandlers = this.eventHandlers.filter((h) => h !== handler);
|
|
181
|
+
if (this.eventHandlers.length === 0)
|
|
182
|
+
this.store.offEvent(this.handleSendEvent);
|
|
156
183
|
}
|
|
157
184
|
getTickList(optsOrBegin, endOrCallback, callbackOrUndefined) {
|
|
158
185
|
setImmediate(() => {
|
|
@@ -229,12 +256,11 @@ class AMFlowClient {
|
|
|
229
256
|
return;
|
|
230
257
|
}
|
|
231
258
|
const startPoint = this.store.getStartPoint(opts);
|
|
232
|
-
if (startPoint) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
else {
|
|
236
|
-
callback((0, ErrorFactory_1.createError)("runtime_error", "No start point"), undefined);
|
|
259
|
+
if (!startPoint) {
|
|
260
|
+
this.waitingStartPointRequests.push({ options: opts, callback });
|
|
261
|
+
return;
|
|
237
262
|
}
|
|
263
|
+
callback(null, startPoint);
|
|
238
264
|
});
|
|
239
265
|
}
|
|
240
266
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
@@ -258,15 +284,15 @@ class AMFlowClient {
|
|
|
258
284
|
return;
|
|
259
285
|
}
|
|
260
286
|
if (!this.store.isDestroyed()) {
|
|
261
|
-
this.store.
|
|
262
|
-
this.store.
|
|
287
|
+
this.store.offEvent(this.handleSendEvent);
|
|
288
|
+
this.store.offTick(this.handleSendTick);
|
|
263
289
|
this.store.putStartPointTrigger.remove(this.handlePutStartPoint, this);
|
|
264
290
|
}
|
|
265
291
|
this.store = null;
|
|
266
292
|
this.permission = null;
|
|
267
293
|
this.tickHandlers = null;
|
|
268
294
|
this.eventHandlers = null;
|
|
269
|
-
this.
|
|
295
|
+
this.waitingStartPointRequests = null;
|
|
270
296
|
this.onPutStartPoint = null;
|
|
271
297
|
}
|
|
272
298
|
isDestroyed() {
|
|
@@ -275,18 +301,5 @@ class AMFlowClient {
|
|
|
275
301
|
dump() {
|
|
276
302
|
return this.store.dump();
|
|
277
303
|
}
|
|
278
|
-
handleSendTick(tick) {
|
|
279
|
-
this.tickHandlers.forEach((h) => h(tick));
|
|
280
|
-
}
|
|
281
|
-
handleSendEvent(event) {
|
|
282
|
-
if (this.eventHandlers.length <= 0) {
|
|
283
|
-
this.unconsumedEvents.push(event);
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
this.eventHandlers.forEach((h) => h(event));
|
|
287
|
-
}
|
|
288
|
-
handlePutStartPoint(startPoint) {
|
|
289
|
-
this.onPutStartPoint.fire(startPoint);
|
|
290
|
-
}
|
|
291
304
|
}
|
|
292
305
|
exports.AMFlowClient = AMFlowClient;
|
|
@@ -2,24 +2,40 @@ import type { GetStartPointOptions, GetTickListOptions, Permission, StartPoint }
|
|
|
2
2
|
import type { Event, Tick, TickList } from "@akashic/playlog";
|
|
3
3
|
import { Trigger } from "@akashic/trigger";
|
|
4
4
|
import type { DumpedPlaylog } from "./types";
|
|
5
|
+
export interface AMFlowStoreOptions {
|
|
6
|
+
/**
|
|
7
|
+
* 受信されないイベントをバッファリングするか。
|
|
8
|
+
*
|
|
9
|
+
* 真の場合、受信者が一つもない状態で送信されたイベントをバッファに保持する。
|
|
10
|
+
* 保持されたイベントは、最初のイベントハンドラが (AMFlow#onEvent() で) 登録された時、そのハンドラにすべて引き渡される。
|
|
11
|
+
* (二つ目以降のハンドラは受け取れないことに注意)
|
|
12
|
+
*/
|
|
13
|
+
preservesUnhandledEvents?: boolean;
|
|
14
|
+
}
|
|
5
15
|
/**
|
|
6
16
|
* AMFlow のストア。
|
|
7
17
|
* 一つのプレーに対して一つ存在する。
|
|
8
18
|
*/
|
|
9
19
|
export declare class AMFlowStore {
|
|
10
20
|
playId: string;
|
|
21
|
+
putStartPointTrigger: Trigger<StartPoint>;
|
|
11
22
|
sendEventTrigger: Trigger<Event>;
|
|
12
23
|
sendTickTrigger: Trigger<Tick>;
|
|
13
|
-
putStartPointTrigger: Trigger<StartPoint>;
|
|
14
24
|
private permissionMap;
|
|
15
25
|
private startPoints;
|
|
16
26
|
private unfilteredTickList;
|
|
17
27
|
private filteredTickList;
|
|
18
28
|
private suspended;
|
|
29
|
+
private options;
|
|
30
|
+
private unhandledEvents;
|
|
19
31
|
constructor(playId: string);
|
|
20
32
|
authenticate(token: string, revoke?: boolean): Permission;
|
|
21
33
|
sendTick(tick: Tick): void;
|
|
22
34
|
sendEvent(event: Event): void;
|
|
35
|
+
onTick(handler: (tick: Tick) => void): void;
|
|
36
|
+
offTick(handler: (tick: Tick) => void): void;
|
|
37
|
+
onEvent(handler: (event: Event) => void): void;
|
|
38
|
+
offEvent(handler: (event: Event) => void): void;
|
|
23
39
|
getTickList(opts: GetTickListOptions): TickList | null;
|
|
24
40
|
putStartPoint(startPoint: StartPoint): void;
|
|
25
41
|
getStartPoint(opts: GetStartPointOptions): StartPoint | null;
|
|
@@ -41,6 +57,7 @@ export declare class AMFlowStore {
|
|
|
41
57
|
resume(): void;
|
|
42
58
|
setTickList(tickList: TickList | null): void;
|
|
43
59
|
setDumpedPlaylog(dumped: DumpedPlaylog): void;
|
|
60
|
+
setOptions(options: AMFlowStoreOptions | null): void;
|
|
44
61
|
destroy(): void;
|
|
45
62
|
isDestroyed(): boolean;
|
|
46
63
|
createPlayToken(permission: Permission): string;
|
|
@@ -11,13 +11,16 @@ const ErrorFactory_1 = require("./ErrorFactory");
|
|
|
11
11
|
*/
|
|
12
12
|
class AMFlowStore {
|
|
13
13
|
constructor(playId) {
|
|
14
|
+
this.putStartPointTrigger = new trigger_1.Trigger();
|
|
15
|
+
// 現状外部から参照する必要はないが、互換性のため少なくとも 2.x.x の間は公開する
|
|
14
16
|
this.sendEventTrigger = new trigger_1.Trigger();
|
|
15
17
|
this.sendTickTrigger = new trigger_1.Trigger();
|
|
16
|
-
this.putStartPointTrigger = new trigger_1.Trigger();
|
|
17
18
|
this.permissionMap = new Map();
|
|
18
19
|
this.startPoints = [];
|
|
19
20
|
this.unfilteredTickList = null;
|
|
20
21
|
this.filteredTickList = null;
|
|
22
|
+
this.options = null;
|
|
23
|
+
this.unhandledEvents = [];
|
|
21
24
|
this.playId = playId;
|
|
22
25
|
this.suspended = false;
|
|
23
26
|
}
|
|
@@ -39,10 +42,32 @@ class AMFlowStore {
|
|
|
39
42
|
this.sendTickTrigger.fire(tick);
|
|
40
43
|
}
|
|
41
44
|
sendEvent(event) {
|
|
45
|
+
var _a;
|
|
42
46
|
if (this.isSuspended()) {
|
|
43
47
|
throw (0, ErrorFactory_1.createError)("bad_request", "Play may be suspended");
|
|
44
48
|
}
|
|
45
|
-
this.
|
|
49
|
+
const ev = this.cloneDeep(event);
|
|
50
|
+
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.preservesUnhandledEvents) && this.sendEventTrigger.length === 0) {
|
|
51
|
+
this.unhandledEvents.push(ev);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.sendEventTrigger.fire(ev);
|
|
55
|
+
}
|
|
56
|
+
onTick(handler) {
|
|
57
|
+
this.sendTickTrigger.add(handler);
|
|
58
|
+
}
|
|
59
|
+
offTick(handler) {
|
|
60
|
+
this.sendTickTrigger.remove(handler);
|
|
61
|
+
}
|
|
62
|
+
onEvent(handler) {
|
|
63
|
+
this.sendEventTrigger.add(handler);
|
|
64
|
+
if (0 < this.unhandledEvents.length) {
|
|
65
|
+
this.unhandledEvents.forEach((ev) => this.sendEventTrigger.fire(ev));
|
|
66
|
+
this.unhandledEvents = [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
offEvent(handler) {
|
|
70
|
+
this.sendEventTrigger.remove(handler);
|
|
46
71
|
}
|
|
47
72
|
getTickList(opts) {
|
|
48
73
|
if (!(this.unfilteredTickList && this.filteredTickList)) {
|
|
@@ -133,6 +158,9 @@ class AMFlowStore {
|
|
|
133
158
|
this.setTickList(dumped.tickList);
|
|
134
159
|
dumped.startPoints.forEach((sp) => this.putStartPoint(sp));
|
|
135
160
|
}
|
|
161
|
+
setOptions(options) {
|
|
162
|
+
this.options = options;
|
|
163
|
+
}
|
|
136
164
|
destroy() {
|
|
137
165
|
if (this.isDestroyed()) {
|
|
138
166
|
return;
|
|
@@ -143,6 +171,7 @@ class AMFlowStore {
|
|
|
143
171
|
this.sendTickTrigger = null;
|
|
144
172
|
this.permissionMap = null;
|
|
145
173
|
this.startPoints = null;
|
|
174
|
+
this.unhandledEvents = null;
|
|
146
175
|
this.putStartPointTrigger = null;
|
|
147
176
|
}
|
|
148
177
|
isDestroyed() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akashic/headless-driver",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "A library to execute contents using Akashic Engine headlessly",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"author": "DWANGO Co., Ltd.",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@akashic/trigger": "^1.0.1",
|
|
30
30
|
"engine-files-v1": "npm:@akashic/engine-files@1.2.1",
|
|
31
31
|
"engine-files-v2": "npm:@akashic/engine-files@2.2.2",
|
|
32
|
-
"engine-files-v3": "npm:@akashic/engine-files@3.6.
|
|
32
|
+
"engine-files-v3": "npm:@akashic/engine-files@3.6.7",
|
|
33
33
|
"js-sha256": "^0.9.0",
|
|
34
34
|
"lodash.clonedeep": "^4.5.0",
|
|
35
35
|
"node-fetch": "^2.6.7",
|