@akashic/headless-driver 1.9.2 → 1.9.6

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.
@@ -28,22 +28,9 @@ class PlayManager {
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 (playlog && playlog.tickList) {
31
+ if (playlog) {
32
32
  const amflow = this.createAMFlow(playId);
33
- const activePermission = {
34
- readTick: true,
35
- writeTick: true,
36
- sendEvent: true,
37
- subscribeEvent: true,
38
- subscribeTick: true,
39
- maxEventPriority: 2
40
- };
41
- const token = this.createPlayToken(playId, activePermission);
42
- // TODO: プレイ生成時に AMFlowStore 生成し playlog を渡して初期化できるようにし、 AMFlowClient 経由で playlog を渡さず済むようにする
43
- yield new Promise((resolve, reject) => amflow.open(playId, (e) => (e ? reject(e) : resolve())));
44
- yield new Promise((resolve, reject) => amflow.authenticate(token, (e) => (e ? reject(e) : resolve())));
45
- yield new Promise((resolve, reject) => amflow.putStartPoint(playlog.startPoints[0], (e) => (e ? reject(e) : resolve())));
46
- amflow.setTickList(playlog.tickList);
33
+ amflow.setDumpedPlaylog(playlog);
47
34
  }
48
35
  return playId;
49
36
  });
@@ -20,7 +20,8 @@ export declare class AMFlowClient implements AMFlow {
20
20
  open(playId: string, callback?: (error: Error | null) => void): void;
21
21
  close(callback?: (error: Error | null) => void): void;
22
22
  authenticate(token: string, callback: (error: Error | null, permission?: Permission) => void): void;
23
- setTickList(tickList: TickList): void;
23
+ setTickList(tickList: TickList | null): void;
24
+ setDumpedPlaylog(dumped: DumpedPlaylog): void;
24
25
  sendTick(tick: Tick): void;
25
26
  onTick(handler: (tick: Tick) => void): void;
26
27
  offTick(handler: (tick: Tick) => void): void;
@@ -19,7 +19,7 @@ class AMFlowClient {
19
19
  this.store = store;
20
20
  }
21
21
  open(playId, callback) {
22
- Logger_1.getSystemLogger().info("AMFlowClient#open()", playId);
22
+ (0, Logger_1.getSystemLogger)().info("AMFlowClient#open()", playId);
23
23
  this.store.sendEventTrigger.add(this.handleSendEvent, this);
24
24
  this.store.sendTickTrigger.add(this.handleSendTick, this);
25
25
  this.store.putStartPointTrigger.add(this.handlePutStartPoint, this);
@@ -27,7 +27,7 @@ class AMFlowClient {
27
27
  if (callback) {
28
28
  setImmediate(() => {
29
29
  if (this.playId !== playId) {
30
- callback(ErrorFactory_1.createError("runtime_error", "Invalid PlayID"));
30
+ callback((0, ErrorFactory_1.createError)("runtime_error", "Invalid PlayID"));
31
31
  }
32
32
  else {
33
33
  callback(null);
@@ -36,10 +36,10 @@ class AMFlowClient {
36
36
  }
37
37
  }
38
38
  close(callback) {
39
- Logger_1.getSystemLogger().info("AMFlowClient#close()");
39
+ (0, Logger_1.getSystemLogger)().info("AMFlowClient#close()");
40
40
  if (this.state !== "open") {
41
41
  if (callback)
42
- callback(ErrorFactory_1.createError("invalid_status", "Client is not open"));
42
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Client is not open"));
43
43
  return;
44
44
  }
45
45
  this.destroy();
@@ -51,7 +51,7 @@ class AMFlowClient {
51
51
  authenticate(token, callback) {
52
52
  setImmediate(() => {
53
53
  if (this.state !== "open") {
54
- callback(ErrorFactory_1.createError("invalid_status", "Client is not open"), undefined);
54
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Client is not open"), undefined);
55
55
  return;
56
56
  }
57
57
  let permission;
@@ -63,60 +63,63 @@ class AMFlowClient {
63
63
  return;
64
64
  }
65
65
  this.permission = permission;
66
- Logger_1.getSystemLogger().info("AMFlowClient#authenticate()", this.playId, token, permission);
66
+ (0, Logger_1.getSystemLogger)().info("AMFlowClient#authenticate()", this.playId, token, permission);
67
67
  if (permission) {
68
68
  callback(null, permission);
69
69
  }
70
70
  else {
71
- callback(ErrorFactory_1.createError("invalid_status", "Invalid playToken"), undefined);
71
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Invalid playToken"), undefined);
72
72
  }
73
73
  });
74
74
  }
75
75
  setTickList(tickList) {
76
76
  this.store.setTickList(tickList);
77
77
  }
78
+ setDumpedPlaylog(dumped) {
79
+ this.store.setDumpedPlaylog(dumped);
80
+ }
78
81
  sendTick(tick) {
79
82
  if (this.state !== "open") {
80
- throw ErrorFactory_1.createError("invalid_status", "Client is not open");
83
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Client is not open");
81
84
  }
82
85
  if (this.permission == null) {
83
- throw ErrorFactory_1.createError("invalid_status", "Not authenticated");
86
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
84
87
  }
85
88
  if (!this.permission.writeTick) {
86
- throw ErrorFactory_1.createError("permission_error", "Permission denied");
89
+ throw (0, ErrorFactory_1.createError)("permission_error", "Permission denied");
87
90
  }
88
91
  this.store.sendTick(tick);
89
92
  }
90
93
  onTick(handler) {
91
94
  if (this.state !== "open") {
92
- throw ErrorFactory_1.createError("invalid_status", "Client is not open");
95
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Client is not open");
93
96
  }
94
97
  if (this.permission == null) {
95
- throw ErrorFactory_1.createError("invalid_status", "Not authenticated");
98
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
96
99
  }
97
100
  if (!this.permission.subscribeTick) {
98
- throw ErrorFactory_1.createError("permission_error", "Permission denied");
101
+ throw (0, ErrorFactory_1.createError)("permission_error", "Permission denied");
99
102
  }
100
103
  this.tickHandlers.push(handler);
101
104
  }
102
105
  offTick(handler) {
103
106
  if (this.state !== "open") {
104
- throw ErrorFactory_1.createError("invalid_status", "Client is not open");
107
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Client is not open");
105
108
  }
106
109
  if (this.permission == null) {
107
- throw ErrorFactory_1.createError("invalid_status", "Not authenticated");
110
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
108
111
  }
109
112
  this.tickHandlers = this.tickHandlers.filter((h) => h !== handler);
110
113
  }
111
114
  sendEvent(event) {
112
115
  if (this.state !== "open") {
113
- throw ErrorFactory_1.createError("invalid_status", "Client is not open");
116
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Client is not open");
114
117
  }
115
118
  if (this.permission == null) {
116
- throw ErrorFactory_1.createError("invalid_status", "Not authenticated");
119
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
117
120
  }
118
121
  if (!this.permission.sendEvent) {
119
- throw ErrorFactory_1.createError("permission_error", "Permission denied");
122
+ throw (0, ErrorFactory_1.createError)("permission_error", "Permission denied");
120
123
  }
121
124
  // Max Priority
122
125
  const prio = event[1 /* EventFlags */] & 3 /* Priority */;
@@ -126,13 +129,13 @@ class AMFlowClient {
126
129
  }
127
130
  onEvent(handler) {
128
131
  if (this.state !== "open") {
129
- throw ErrorFactory_1.createError("invalid_status", "Client is not open");
132
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Client is not open");
130
133
  }
131
134
  if (this.permission == null) {
132
- throw ErrorFactory_1.createError("invalid_status", "Not authenticated");
135
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
133
136
  }
134
137
  if (!this.permission.subscribeEvent) {
135
- throw ErrorFactory_1.createError("permission_error", "Permission denied");
138
+ throw (0, ErrorFactory_1.createError)("permission_error", "Permission denied");
136
139
  }
137
140
  this.eventHandlers.push(handler);
138
141
  if (0 < this.unconsumedEvents.length) {
@@ -144,10 +147,10 @@ class AMFlowClient {
144
147
  }
145
148
  offEvent(handler) {
146
149
  if (this.state !== "open") {
147
- throw ErrorFactory_1.createError("invalid_status", "Client is not open");
150
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Client is not open");
148
151
  }
149
152
  if (this.permission == null) {
150
- throw ErrorFactory_1.createError("invalid_status", "Not authenticated");
153
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Not authenticated");
151
154
  }
152
155
  this.eventHandlers = this.eventHandlers.filter((h) => h !== handler);
153
156
  }
@@ -169,18 +172,18 @@ class AMFlowClient {
169
172
  callback = endOrCallback;
170
173
  }
171
174
  if (!callback) {
172
- throw ErrorFactory_1.createError("runtime_error", "Callback is undefined");
175
+ throw (0, ErrorFactory_1.createError)("runtime_error", "Callback is undefined");
173
176
  }
174
177
  if (this.state !== "open") {
175
- callback(ErrorFactory_1.createError("invalid_status", "Client is not open"), undefined);
178
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Client is not open"), undefined);
176
179
  return;
177
180
  }
178
181
  if (this.permission == null) {
179
- callback(ErrorFactory_1.createError("invalid_status", "Not authenticated"), undefined);
182
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Not authenticated"), undefined);
180
183
  return;
181
184
  }
182
185
  if (!this.permission.readTick) {
183
- callback(ErrorFactory_1.createError("permission_error", "Permission denied"), undefined);
186
+ callback((0, ErrorFactory_1.createError)("permission_error", "Permission denied"), undefined);
184
187
  return;
185
188
  }
186
189
  const tickList = this.store.getTickList(opts);
@@ -188,22 +191,22 @@ class AMFlowClient {
188
191
  callback(null, tickList);
189
192
  }
190
193
  else {
191
- callback(ErrorFactory_1.createError("runtime_error", "No tick list"), undefined);
194
+ callback((0, ErrorFactory_1.createError)("runtime_error", "No tick list"), undefined);
192
195
  }
193
196
  });
194
197
  }
195
198
  putStartPoint(startPoint, callback) {
196
199
  setImmediate(() => {
197
200
  if (this.state !== "open") {
198
- callback(ErrorFactory_1.createError("invalid_status", "Client is not open"));
201
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Client is not open"));
199
202
  return;
200
203
  }
201
204
  if (this.permission == null) {
202
- callback(ErrorFactory_1.createError("invalid_status", "Not authenticated"));
205
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Not authenticated"));
203
206
  return;
204
207
  }
205
208
  if (!this.permission.writeTick) {
206
- callback(ErrorFactory_1.createError("permission_error", "Permission denied"));
209
+ callback((0, ErrorFactory_1.createError)("permission_error", "Permission denied"));
207
210
  return;
208
211
  }
209
212
  try {
@@ -219,15 +222,15 @@ class AMFlowClient {
219
222
  getStartPoint(opts, callback) {
220
223
  setImmediate(() => {
221
224
  if (this.state !== "open") {
222
- callback(ErrorFactory_1.createError("invalid_status", "Client is not open"), undefined);
225
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Client is not open"), undefined);
223
226
  return;
224
227
  }
225
228
  if (this.permission == null) {
226
- callback(ErrorFactory_1.createError("invalid_status", "Not authenticated"), undefined);
229
+ callback((0, ErrorFactory_1.createError)("invalid_status", "Not authenticated"), undefined);
227
230
  return;
228
231
  }
229
232
  if (!this.permission.readTick) {
230
- callback(ErrorFactory_1.createError("permission_error", "Permission denied"), undefined);
233
+ callback((0, ErrorFactory_1.createError)("permission_error", "Permission denied"), undefined);
231
234
  return;
232
235
  }
233
236
  const startPoint = this.store.getStartPoint(opts);
@@ -235,7 +238,7 @@ class AMFlowClient {
235
238
  callback(null, startPoint);
236
239
  }
237
240
  else {
238
- callback(ErrorFactory_1.createError("runtime_error", "No start point"), undefined);
241
+ callback((0, ErrorFactory_1.createError)("runtime_error", "No start point"), undefined);
239
242
  }
240
243
  });
241
244
  }
@@ -243,12 +246,12 @@ class AMFlowClient {
243
246
  // 未実装の状態のため未使用の lint エラーを無効とする
244
247
  putStorageData(key, value, options, callback) {
245
248
  setImmediate(() => {
246
- callback(ErrorFactory_1.createError("not_implemented", "Not implemented"));
249
+ callback((0, ErrorFactory_1.createError)("not_implemented", "Not implemented"));
247
250
  });
248
251
  }
249
252
  getStorageData(keys, callback) {
250
253
  setImmediate(() => {
251
- callback(ErrorFactory_1.createError("not_implemented", "Not implemented"), undefined);
254
+ callback((0, ErrorFactory_1.createError)("not_implemented", "Not implemented"), undefined);
252
255
  });
253
256
  }
254
257
  /* eslint-enable */
@@ -39,7 +39,8 @@ export declare class AMFlowStore {
39
39
  * この AMFlowStore を再開する。
40
40
  */
41
41
  resume(): void;
42
- setTickList(tickList: TickList): void;
42
+ setTickList(tickList: TickList | null): void;
43
+ setDumpedPlaylog(dumped: DumpedPlaylog): void;
43
44
  destroy(): void;
44
45
  isDestroyed(): boolean;
45
46
  createPlayToken(permission: Permission): string;
@@ -24,23 +24,23 @@ class AMFlowStore {
24
24
  authenticate(token, revoke) {
25
25
  const permission = this.authenticatePlayToken(token, revoke);
26
26
  if (!permission) {
27
- throw ErrorFactory_1.createError("invalid_status", "Cannot call AMFlowStore#authenticate without authenticated token");
27
+ throw (0, ErrorFactory_1.createError)("invalid_status", "Cannot call AMFlowStore#authenticate without authenticated token");
28
28
  }
29
29
  if (this.isSuspended() && (permission.sendEvent || permission.writeTick)) {
30
- throw ErrorFactory_1.createError("permission_error", "Play may be suspended");
30
+ throw (0, ErrorFactory_1.createError)("permission_error", "Play may be suspended");
31
31
  }
32
32
  return permission;
33
33
  }
34
34
  sendTick(tick) {
35
35
  if (this.isSuspended()) {
36
- throw ErrorFactory_1.createError("bad_request", "Play may be suspended");
36
+ throw (0, ErrorFactory_1.createError)("bad_request", "Play may be suspended");
37
37
  }
38
38
  this.pushTick(tick);
39
39
  this.sendTickTrigger.fire(tick);
40
40
  }
41
41
  sendEvent(event) {
42
42
  if (this.isSuspended()) {
43
- throw ErrorFactory_1.createError("bad_request", "Play may be suspended");
43
+ throw (0, ErrorFactory_1.createError)("bad_request", "Play may be suspended");
44
44
  }
45
45
  this.sendEventTrigger.fire(this.cloneDeep(event));
46
46
  }
@@ -63,7 +63,7 @@ class AMFlowStore {
63
63
  }
64
64
  putStartPoint(startPoint) {
65
65
  if (this.isSuspended()) {
66
- throw ErrorFactory_1.createError("bad_request", "Play may be suspended");
66
+ throw (0, ErrorFactory_1.createError)("bad_request", "Play may be suspended");
67
67
  }
68
68
  this.putStartPointTrigger.fire(startPoint);
69
69
  // NOTE: frame: 0 のみ第0要素に保持する
@@ -123,8 +123,12 @@ class AMFlowStore {
123
123
  this.suspended = false;
124
124
  }
125
125
  setTickList(tickList) {
126
- this.unfilteredTickList = this.cloneDeep(tickList);
127
- this.filteredTickList = this.cloneDeep(tickList);
126
+ this.unfilteredTickList = tickList ? this.cloneDeep(tickList) : null;
127
+ this.filteredTickList = tickList ? this.cloneDeep(tickList) : null;
128
+ }
129
+ setDumpedPlaylog(dumped) {
130
+ this.setTickList(dumped.tickList);
131
+ dumped.startPoints.forEach((sp) => this.putStartPoint(sp));
128
132
  }
129
133
  destroy() {
130
134
  if (this.isDestroyed()) {
@@ -143,7 +147,7 @@ class AMFlowStore {
143
147
  }
144
148
  createPlayToken(permission) {
145
149
  const str = this.createRandomString(10);
146
- const token = js_sha256_1.sha256(str);
150
+ const token = (0, js_sha256_1.sha256)(str);
147
151
  this.permissionMap.set(token, permission);
148
152
  return token;
149
153
  }
@@ -120,28 +120,28 @@ class RunnerManager {
120
120
  externalValue: params.externalValue
121
121
  };
122
122
  if (version === "3") {
123
- Logger_1.getSystemLogger().info("v3 content");
123
+ (0, Logger_1.getSystemLogger)().info("v3 content");
124
124
  const filePath = ExecVmScriptV3.getFilePath();
125
125
  const str = fs.readFileSync(filePath, { encoding: "utf8" });
126
126
  const script = new vm2_1.VMScript(str, filePath);
127
127
  runner = nvm.run(script).createRunnerV3(runnerParameter);
128
128
  }
129
129
  else if (version === "2") {
130
- Logger_1.getSystemLogger().info("v2 content");
130
+ (0, Logger_1.getSystemLogger)().info("v2 content");
131
131
  const filePath = ExecVmScriptV2.getFilePath();
132
132
  const str = fs.readFileSync(filePath, { encoding: "utf8" });
133
133
  const script = new vm2_1.VMScript(str, filePath);
134
134
  runner = nvm.run(script).createRunnerV2(runnerParameter);
135
135
  }
136
136
  else {
137
- Logger_1.getSystemLogger().info("v1 content");
137
+ (0, Logger_1.getSystemLogger)().info("v1 content");
138
138
  const filePath = ExecVmScriptV1.getFilePath();
139
139
  const str = fs.readFileSync(filePath, { encoding: "utf8" });
140
140
  const script = new vm2_1.VMScript(str, filePath);
141
141
  runner = nvm.run(script).createRunnerV1(runnerParameter);
142
142
  }
143
143
  runner.errorTrigger.add((err) => {
144
- Logger_1.getSystemLogger().error(err.message);
144
+ (0, Logger_1.getSystemLogger)().error(err.message);
145
145
  this.stopRunner(runnerId);
146
146
  return true;
147
147
  });
@@ -257,7 +257,7 @@ class RunnerManager {
257
257
  }
258
258
  loadJSON(contentUrl) {
259
259
  return __awaiter(this, void 0, void 0, function* () {
260
- return utils_1.loadFile(contentUrl).then((text) => JSON.parse(text));
260
+ return (0, utils_1.loadFile)(contentUrl).then((text) => JSON.parse(text));
261
261
  });
262
262
  }
263
263
  createLoadFileHandler(allowedUrls) {
@@ -276,7 +276,7 @@ class RunnerManager {
276
276
  return void callback(new Error(`Not allowed to read this URL. ${url}`));
277
277
  }
278
278
  }
279
- utils_1.loadFile(url)
279
+ (0, utils_1.loadFile)(url)
280
280
  .then((text) => {
281
281
  callback(null, text);
282
282
  })
@@ -290,7 +290,7 @@ class RunnerManager {
290
290
  sandbox: {
291
291
  trustedFunctions: {
292
292
  engineFiles: () => {
293
- return requireEngineFiles_1.requireEngineFiles();
293
+ return (0, requireEngineFiles_1.requireEngineFiles)();
294
294
  }
295
295
  }
296
296
  },
package/lib/utils.js CHANGED
@@ -21,7 +21,7 @@ const node_fetch_1 = require("node-fetch");
21
21
  function loadFile(url) {
22
22
  return __awaiter(this, void 0, void 0, function* () {
23
23
  if (isHttpProtocol(url)) {
24
- const res = yield node_fetch_1.default(url, { method: "GET" });
24
+ const res = yield (0, node_fetch_1.default)(url, { method: "GET" });
25
25
  return res.text();
26
26
  }
27
27
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akashic/headless-driver",
3
- "version": "1.9.2",
3
+ "version": "1.9.6",
4
4
  "description": "A library to execute contents using Akashic Engine headlessly",
5
5
  "main": "lib/index.js",
6
6
  "author": "DWANGO Co., Ltd.",
@@ -23,15 +23,15 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@akashic/amflow": "~3.1.0",
26
- "@akashic/headless-driver-runner": "1.9.2",
27
- "@akashic/headless-driver-runner-v1": "1.9.2",
28
- "@akashic/headless-driver-runner-v2": "1.9.2",
29
- "@akashic/headless-driver-runner-v3": "1.9.2",
26
+ "@akashic/headless-driver-runner": "1.9.6",
27
+ "@akashic/headless-driver-runner-v1": "1.9.6",
28
+ "@akashic/headless-driver-runner-v2": "1.9.6",
29
+ "@akashic/headless-driver-runner-v3": "1.9.6",
30
30
  "@akashic/playlog": "~3.1.0",
31
31
  "@akashic/trigger": "~1.0.0",
32
32
  "js-sha256": "0.9.0",
33
33
  "lodash.clonedeep": "4.5.0",
34
- "node-fetch": "2.6.1",
34
+ "node-fetch": "2.6.2",
35
35
  "vm2": "3.9.1"
36
36
  },
37
37
  "devDependencies": {
@@ -40,24 +40,24 @@
40
40
  "@types/get-port": "4.0.1",
41
41
  "@types/jest": "27.0.1",
42
42
  "@types/lodash.clonedeep": "4.5.6",
43
- "@types/node": "14.17.12",
43
+ "@types/node": "14.17.15",
44
44
  "@types/node-fetch": "2.5.12",
45
45
  "@types/pixelmatch": "5.2.4",
46
46
  "@types/pngjs": "6.0.1",
47
- "@typescript-eslint/eslint-plugin": "4.29.3",
47
+ "@typescript-eslint/eslint-plugin": "4.31.0",
48
48
  "eslint": "7.32.0",
49
49
  "eslint-config-prettier": "8.3.0",
50
50
  "eslint-plugin-import": "2.24.2",
51
51
  "eslint-plugin-jest": "24.4.0",
52
52
  "get-port": "5.1.1",
53
- "jest": "26.6.3",
53
+ "jest": "27.1.1",
54
54
  "pixelmatch": "5.2.1",
55
55
  "pngjs": "6.0.0",
56
- "prettier": "2.3.2",
56
+ "prettier": "2.4.0",
57
57
  "rimraf": "3.0.2",
58
58
  "serve-handler": "6.1.3",
59
- "ts-jest": "26.5.6",
60
- "typescript": "4.3.5"
59
+ "ts-jest": "27.0.5",
60
+ "typescript": "4.4.3"
61
61
  },
62
62
  "optionalDependencies": {
63
63
  "canvas": "2.8.0"
@@ -81,5 +81,5 @@
81
81
  "globalSetup": "<rootDir>/src/__tests__/setup.ts",
82
82
  "globalTeardown": "<rootDir>/src/__tests__/teardown.ts"
83
83
  },
84
- "gitHead": "cce8652f35d9be2b045a9c597b34edfe771116ee"
84
+ "gitHead": "f9cf6266b0750e5560267e520092730717c526ed"
85
85
  }