@appium/base-driver 10.0.0-beta.2 → 10.0.0-rc.2
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/build/lib/basedriver/capabilities.d.ts +1 -1
- package/build/lib/basedriver/capabilities.d.ts.map +1 -1
- package/build/lib/basedriver/capabilities.js +1 -1
- package/build/lib/basedriver/capabilities.js.map +1 -1
- package/build/lib/basedriver/commands/timeout.js +2 -2
- package/build/lib/basedriver/commands/timeout.js.map +1 -1
- package/build/lib/basedriver/core.d.ts +2 -1
- package/build/lib/basedriver/core.d.ts.map +1 -1
- package/build/lib/basedriver/core.js +2 -2
- package/build/lib/basedriver/core.js.map +1 -1
- package/build/lib/basedriver/driver.d.ts +3 -3
- package/build/lib/basedriver/driver.d.ts.map +1 -1
- package/build/lib/basedriver/driver.js +15 -11
- package/build/lib/basedriver/driver.js.map +1 -1
- package/build/lib/basedriver/extension-core.js +1 -1
- package/build/lib/basedriver/extension-core.js.map +1 -1
- package/build/lib/basedriver/helpers.js +7 -7
- package/build/lib/basedriver/helpers.js.map +1 -1
- package/build/lib/express/express-logging.d.ts.map +1 -1
- package/build/lib/express/express-logging.js +2 -1
- package/build/lib/express/express-logging.js.map +1 -1
- package/build/lib/express/server.js +2 -2
- package/build/lib/express/server.js.map +1 -1
- package/build/lib/helpers/extension-command-name.d.ts +11 -0
- package/build/lib/helpers/extension-command-name.d.ts.map +1 -0
- package/build/lib/helpers/extension-command-name.js +26 -0
- package/build/lib/helpers/extension-command-name.js.map +1 -0
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.js +7 -6
- package/build/lib/jsonwp-proxy/protocol-converter.js.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.js +5 -5
- package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
- package/build/lib/protocol/protocol.js +4 -6
- package/build/lib/protocol/protocol.js.map +1 -1
- package/build/lib/protocol/routes.d.ts +2 -0
- package/build/lib/protocol/routes.d.ts.map +1 -1
- package/build/lib/protocol/routes.js +10 -3
- package/build/lib/protocol/routes.js.map +1 -1
- package/lib/basedriver/capabilities.ts +2 -2
- package/lib/basedriver/commands/timeout.ts +2 -2
- package/lib/basedriver/core.ts +4 -2
- package/lib/basedriver/driver.ts +19 -14
- package/lib/basedriver/extension-core.ts +1 -1
- package/lib/basedriver/helpers.js +8 -8
- package/lib/express/express-logging.js +2 -1
- package/lib/express/server.js +2 -2
- package/lib/helpers/extension-command-name.ts +27 -0
- package/lib/jsonwp-proxy/protocol-converter.js +7 -8
- package/lib/jsonwp-proxy/proxy.js +9 -5
- package/lib/protocol/protocol.ts +6 -6
- package/lib/protocol/routes.js +10 -3
- package/package.json +13 -13
package/lib/basedriver/driver.ts
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
type Driver,
|
|
10
10
|
type DriverCaps,
|
|
11
11
|
type DriverData,
|
|
12
|
-
type MultiSessionData,
|
|
13
12
|
type ServerArgs,
|
|
14
13
|
type StringRecord,
|
|
15
14
|
type W3CDriverCaps,
|
|
@@ -26,6 +25,7 @@ import {DELETE_SESSION_COMMAND, determineProtocol, errors} from '../protocol';
|
|
|
26
25
|
import {processCapabilities, validateCaps} from './capabilities';
|
|
27
26
|
import {DriverCore} from './core';
|
|
28
27
|
import * as helpers from './helpers';
|
|
28
|
+
import {resolveExecuteExtensionName} from '../helpers/extension-command-name';
|
|
29
29
|
|
|
30
30
|
const EVENT_SESSION_INIT = 'newSessionRequested';
|
|
31
31
|
const EVENT_SESSION_START = 'newSessionStarted';
|
|
@@ -162,6 +162,11 @@ export class BaseDriver<
|
|
|
162
162
|
|
|
163
163
|
// log timing information about this command
|
|
164
164
|
const endTime = Date.now();
|
|
165
|
+
|
|
166
|
+
if (this.clarifyCommandName) {
|
|
167
|
+
cmd = this.clarifyCommandName(cmd, args);
|
|
168
|
+
}
|
|
169
|
+
|
|
165
170
|
this._eventHistory.commands.push({cmd, startTime, endTime});
|
|
166
171
|
if (cmd === 'createSession') {
|
|
167
172
|
this.logEvent(EVENT_SESSION_START);
|
|
@@ -172,6 +177,17 @@ export class BaseDriver<
|
|
|
172
177
|
return res;
|
|
173
178
|
}
|
|
174
179
|
|
|
180
|
+
clarifyCommandName(cmd: string, args: string[]): string {
|
|
181
|
+
if (cmd === 'execute') {
|
|
182
|
+
const firstArg = args?.[0];
|
|
183
|
+
if (_.isString(firstArg) && firstArg.trim().length > 0) {
|
|
184
|
+
return resolveExecuteExtensionName.call(this, firstArg);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return cmd;
|
|
189
|
+
}
|
|
190
|
+
|
|
175
191
|
async startUnexpectedShutdown(
|
|
176
192
|
err: Error = new errors.NoSuchDriverError('The driver was unexpectedly shut down!'),
|
|
177
193
|
) {
|
|
@@ -302,6 +318,7 @@ export class BaseDriver<
|
|
|
302
318
|
this.validateDesiredCaps(caps);
|
|
303
319
|
|
|
304
320
|
this.sessionId = util.uuidV4();
|
|
321
|
+
this.sessionCreationTimestampMs = Date.now();
|
|
305
322
|
this.caps = caps;
|
|
306
323
|
// merge caps onto opts so we don't need to worry about what's where
|
|
307
324
|
this.opts = {..._.cloneDeep(this.initialOpts), ...this.caps};
|
|
@@ -345,22 +362,10 @@ export class BaseDriver<
|
|
|
345
362
|
|
|
346
363
|
return [this.sessionId, caps] as CreateResult;
|
|
347
364
|
}
|
|
348
|
-
async getSessions() {
|
|
349
|
-
const ret: MultiSessionData<C>[] = [];
|
|
350
|
-
|
|
351
|
-
if (this.sessionId) {
|
|
352
|
-
ret.push({
|
|
353
|
-
id: this.sessionId,
|
|
354
|
-
capabilities: this.caps,
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return ret;
|
|
359
|
-
}
|
|
360
365
|
|
|
361
366
|
/**
|
|
362
367
|
* Returns capabilities for the session and event history (if applicable)
|
|
363
|
-
* @deprecated Use {@linkcode
|
|
368
|
+
* @deprecated Use {@linkcode getAppiumSessionCapabilities} instead for getting the capabilities.
|
|
364
369
|
* Use {@linkcode EventCommands.getLogEvents} instead to get the event history.
|
|
365
370
|
*/
|
|
366
371
|
async getSession() {
|
|
@@ -71,7 +71,7 @@ export class ExtensionCore {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// if the command module or method isn't part of our spec, reject
|
|
74
|
-
if (!this.bidiCommands[moduleName]
|
|
74
|
+
if (!(this.bidiCommands[moduleName]?.[methodName])) {
|
|
75
75
|
throw new errors.UnknownCommandError();
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -101,7 +101,7 @@ export async function configureApp(
|
|
|
101
101
|
const originalAppLink = app;
|
|
102
102
|
let packageHash = null;
|
|
103
103
|
/** @type {import('axios').AxiosResponse['headers']|undefined} */
|
|
104
|
-
let headers
|
|
104
|
+
let headers;
|
|
105
105
|
/** @type {RemoteAppProps} */
|
|
106
106
|
const remoteAppProps = {
|
|
107
107
|
lastModified: null,
|
|
@@ -121,12 +121,12 @@ export async function configureApp(
|
|
|
121
121
|
}
|
|
122
122
|
const appCacheKey = toCacheKey(app);
|
|
123
123
|
|
|
124
|
-
const cachedAppInfo = APPLICATIONS_CACHE.get(appCacheKey);
|
|
125
|
-
if (cachedAppInfo) {
|
|
126
|
-
logger.debug(`Cached app data: ${JSON.stringify(cachedAppInfo, null, 2)}`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
124
|
return await APPLICATIONS_CACHE_GUARD.acquire(appCacheKey, async () => {
|
|
125
|
+
const cachedAppInfo = APPLICATIONS_CACHE.get(appCacheKey);
|
|
126
|
+
if (cachedAppInfo) {
|
|
127
|
+
logger.debug(`Cached app data: ${JSON.stringify(cachedAppInfo, null, 2)}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
130
|
if (isUrl) {
|
|
131
131
|
// Use the app from remote URL
|
|
132
132
|
logger.info(`Using downloadable app '${newApp}'`);
|
|
@@ -434,7 +434,7 @@ async function fetchApp(srcStream, dstPath) {
|
|
|
434
434
|
*
|
|
435
435
|
* @param {string} app App link.
|
|
436
436
|
* @returns {string} Transformed app link or the original arg if
|
|
437
|
-
* no
|
|
437
|
+
* no transformation is needed.
|
|
438
438
|
*/
|
|
439
439
|
function toCacheKey(app) {
|
|
440
440
|
if (!isEnvOptionEnabled('APPIUM_APPS_CACHE_IGNORE_URL_QUERY') || !isSupportedUrl(app)) {
|
|
@@ -529,7 +529,7 @@ function isSupportedUrl(app) {
|
|
|
529
529
|
*
|
|
530
530
|
* @param {string} optionName Option name
|
|
531
531
|
* @param {boolean|null} [defaultValue=null] The value to return if the given env value
|
|
532
|
-
* is not set
|
|
532
|
+
* is not set explicitly
|
|
533
533
|
* @returns {boolean} True if the option is enabled
|
|
534
534
|
*/
|
|
535
535
|
function isEnvOptionEnabled(optionName, defaultValue = null) {
|
|
@@ -3,6 +3,7 @@ import '@colors/colors';
|
|
|
3
3
|
import morgan from 'morgan';
|
|
4
4
|
import log from './logger';
|
|
5
5
|
import {MAX_LOG_BODY_LENGTH} from '../constants';
|
|
6
|
+
import {logger} from '@appium/support';
|
|
6
7
|
|
|
7
8
|
// Copied the morgan compile function over so that cooler formats
|
|
8
9
|
// may be configured
|
|
@@ -51,7 +52,7 @@ const startLogFormatter = morgan(
|
|
|
51
52
|
});
|
|
52
53
|
} catch {}
|
|
53
54
|
}
|
|
54
|
-
log.info(requestStartLoggingFormat(tokens, req, res), reqBody.grey);
|
|
55
|
+
log.info(requestStartLoggingFormat(tokens, req, res), logger.markSensitive(reqBody.grey));
|
|
55
56
|
},
|
|
56
57
|
{immediate: true}
|
|
57
58
|
);
|
package/lib/express/server.js
CHANGED
|
@@ -231,7 +231,7 @@ function configureHttp({httpServer, reject, keepAliveTimeout, gracefulShutdownTi
|
|
|
231
231
|
}, gracefulShutdownTimeout);
|
|
232
232
|
httpServer.once('close', () => {
|
|
233
233
|
log.info(
|
|
234
|
-
`Appium HTTP server has been
|
|
234
|
+
`Appium HTTP server has been successfully closed after ` +
|
|
235
235
|
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms`
|
|
236
236
|
);
|
|
237
237
|
clearTimeout(onTimeout);
|
|
@@ -309,7 +309,7 @@ export function normalizeBasePath(basePath) {
|
|
|
309
309
|
|
|
310
310
|
// likewise, ensure the path prefix does always START with /, unless the path
|
|
311
311
|
// is empty meaning no base path at all
|
|
312
|
-
if (basePath !== '' && basePath
|
|
312
|
+
if (basePath !== '' && !basePath.startsWith('/')) {
|
|
313
313
|
basePath = `/${basePath}`;
|
|
314
314
|
}
|
|
315
315
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import type {Constraints, Driver, DriverClass} from '@appium/types';
|
|
3
|
+
import type {BaseDriver} from '../basedriver/driver';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the name of extension method corresponding to an `execute` command string
|
|
7
|
+
* based on the driver's `executeMethodMap`.
|
|
8
|
+
*
|
|
9
|
+
* @param commandName - The command name to resolve.
|
|
10
|
+
* @returns The resolved extension command name if a mapping exists. Otherwise, the original command name.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveExecuteExtensionName<C extends Constraints>(
|
|
13
|
+
this: BaseDriver<C>,
|
|
14
|
+
commandName: string
|
|
15
|
+
): string {
|
|
16
|
+
const Driver = this.constructor as DriverClass<Driver<C>>;
|
|
17
|
+
const methodMap = Driver.executeMethodMap;
|
|
18
|
+
|
|
19
|
+
if (methodMap && _.isPlainObject(methodMap) && commandName in methodMap) {
|
|
20
|
+
const command = methodMap[commandName]?.command;
|
|
21
|
+
if (typeof command === 'string') {
|
|
22
|
+
return command;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return commandName;
|
|
27
|
+
}
|
|
@@ -19,12 +19,12 @@ export const COMMAND_URLS_CONFLICTS = [
|
|
|
19
19
|
{
|
|
20
20
|
commandNames: ['getWindowHandles', 'getWindowHandle'],
|
|
21
21
|
jsonwpConverter(url) {
|
|
22
|
-
return
|
|
22
|
+
return url.endsWith('/window')
|
|
23
23
|
? url.replace(/\/window$/, '/window_handle')
|
|
24
24
|
: url.replace(/\/window\/handle(s?)$/, '/window_handle$1');
|
|
25
25
|
},
|
|
26
26
|
w3cConverter(url) {
|
|
27
|
-
return
|
|
27
|
+
return url.endsWith('/window_handle')
|
|
28
28
|
? url.replace(/\/window_handle$/, '/window')
|
|
29
29
|
: url.replace(/\/window_handles$/, '/window/handles');
|
|
30
30
|
},
|
|
@@ -186,20 +186,19 @@ class ProtocolConverter {
|
|
|
186
186
|
let {text, value} = bodyObj;
|
|
187
187
|
if (util.hasValue(text) && !util.hasValue(value)) {
|
|
188
188
|
value = _.isString(text) ? [...text] : _.isArray(text) ? text : [];
|
|
189
|
-
this.log.debug(
|
|
190
|
-
`Added 'value' property ${JSON.stringify(value)} to 'setValue' request body`
|
|
191
|
-
);
|
|
189
|
+
this.log.debug(`Added 'value' property to 'setValue' request body`);
|
|
192
190
|
} else if (!util.hasValue(text) && util.hasValue(value)) {
|
|
193
191
|
text = _.isArray(value) ? value.join('') : _.isString(value) ? value : '';
|
|
194
|
-
this.log.debug(`Added 'text' property
|
|
192
|
+
this.log.debug(`Added 'text' property to 'setValue' request body`);
|
|
195
193
|
}
|
|
196
194
|
return await this.proxyFunc(
|
|
197
195
|
url,
|
|
198
196
|
method,
|
|
199
|
-
|
|
197
|
+
{
|
|
198
|
+
...bodyObj,
|
|
200
199
|
text,
|
|
201
200
|
value,
|
|
202
|
-
}
|
|
201
|
+
}
|
|
203
202
|
);
|
|
204
203
|
}
|
|
205
204
|
|
|
@@ -203,8 +203,11 @@ export class JWProxy {
|
|
|
203
203
|
if (typeof body !== 'object') {
|
|
204
204
|
try {
|
|
205
205
|
reqOpts.data = JSON.parse(body);
|
|
206
|
-
} catch {
|
|
207
|
-
|
|
206
|
+
} catch (error) {
|
|
207
|
+
this.log.warn('Invalid body payload (%s): %s', error.message, logger.markSensitive(truncateBody(body)));
|
|
208
|
+
throw new Error(
|
|
209
|
+
'Cannot interpret the request body as valid JSON. Check the server log for more details.'
|
|
210
|
+
);
|
|
208
211
|
}
|
|
209
212
|
} else {
|
|
210
213
|
reqOpts.data = body;
|
|
@@ -212,8 +215,9 @@ export class JWProxy {
|
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
this.log.debug(
|
|
215
|
-
`Proxying [
|
|
216
|
-
|
|
218
|
+
`Proxying [%s %s] to [%s %s] with ${reqOpts.data ? 'body: %s' : '%s body'}`,
|
|
219
|
+
method, url || '/', method, newUrl,
|
|
220
|
+
reqOpts.data ? logger.markSensitive(truncateBody(reqOpts.data)) : 'no'
|
|
217
221
|
);
|
|
218
222
|
|
|
219
223
|
const throwProxyError = (error) => {
|
|
@@ -236,7 +240,7 @@ export class JWProxy {
|
|
|
236
240
|
}
|
|
237
241
|
this.log.debug(`Got response with status ${status}: ${truncateBody(data)}`);
|
|
238
242
|
isResponseLogged = true;
|
|
239
|
-
const isSessionCreationRequest =
|
|
243
|
+
const isSessionCreationRequest = url.endsWith('/session') && method === 'POST';
|
|
240
244
|
if (isSessionCreationRequest) {
|
|
241
245
|
if (status === 200) {
|
|
242
246
|
this.sessionId = data.sessionId || (data.value || {}).sessionId;
|
package/lib/protocol/protocol.ts
CHANGED
|
@@ -317,9 +317,9 @@ function buildHandler(
|
|
|
317
317
|
if (spec.deprecated && spec.command && !deprecatedCommandsLogged.has(spec.command)) {
|
|
318
318
|
deprecatedCommandsLogged.add(spec.command);
|
|
319
319
|
getLogger(driver, req.params.sessionId).warn(
|
|
320
|
-
`
|
|
321
|
-
`version of Appium or your driver/plugin. Please use a different
|
|
322
|
-
`driver/plugin author to add explicit support for the
|
|
320
|
+
`The ${method} ${path} endpoint has been deprecated and will be removed in a future ` +
|
|
321
|
+
`version of Appium or your driver/plugin. Please use a different endpoint or contact the ` +
|
|
322
|
+
`driver/plugin author to add explicit support for the endpoint before it is removed`
|
|
323
323
|
);
|
|
324
324
|
}
|
|
325
325
|
|
|
@@ -394,9 +394,9 @@ function buildHandler(
|
|
|
394
394
|
|
|
395
395
|
// run the driver command wrapped inside the argument validators
|
|
396
396
|
getLogger(driver, req.params.sessionId).debug(
|
|
397
|
-
`Calling
|
|
398
|
-
|
|
399
|
-
|
|
397
|
+
`Calling %s.%s() with args: %s`,
|
|
398
|
+
driver.constructor.name, spec.command,
|
|
399
|
+
logger.markSensitive(_.truncate(JSON.stringify(args), {length: MAX_LOG_BODY_LENGTH}))
|
|
400
400
|
);
|
|
401
401
|
|
|
402
402
|
if (didPluginOverrideProxy) {
|
package/lib/protocol/routes.js
CHANGED
|
@@ -269,8 +269,15 @@ export const METHOD_MAP = /** @type {const} */ ({
|
|
|
269
269
|
POST: {command: 'setRotation', payloadParams: {required: ['x', 'y', 'z']}},
|
|
270
270
|
},
|
|
271
271
|
'/session/:sessionId/location': {
|
|
272
|
-
GET: {
|
|
273
|
-
|
|
272
|
+
GET: {
|
|
273
|
+
command: 'getGeoLocation',
|
|
274
|
+
deprecated: true,
|
|
275
|
+
},
|
|
276
|
+
POST: {
|
|
277
|
+
command: 'setGeoLocation',
|
|
278
|
+
payloadParams: {required: ['location']},
|
|
279
|
+
deprecated: true,
|
|
280
|
+
},
|
|
274
281
|
},
|
|
275
282
|
'/session/:sessionId/orientation': {
|
|
276
283
|
GET: {command: 'getOrientation'},
|
|
@@ -406,7 +413,7 @@ export const METHOD_MAP = /** @type {const} */ ({
|
|
|
406
413
|
// #endregion
|
|
407
414
|
|
|
408
415
|
//
|
|
409
|
-
// 3rd party vendor/
|
|
416
|
+
// 3rd party vendor/protocol support
|
|
410
417
|
//
|
|
411
418
|
// #region Selenium/Chromium browsers
|
|
412
419
|
'/session/:sessionId/se/log': {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appium/base-driver",
|
|
3
|
-
"version": "10.0.0-
|
|
3
|
+
"version": "10.0.0-rc.2",
|
|
4
4
|
"description": "Base driver class for Appium drivers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -44,38 +44,38 @@
|
|
|
44
44
|
"test:types": "tsd"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@appium/support": "^
|
|
48
|
-
"@appium/types": "^0.
|
|
47
|
+
"@appium/support": "^7.0.0-rc.1",
|
|
48
|
+
"@appium/types": "^1.0.0-rc.1",
|
|
49
49
|
"@colors/colors": "1.6.0",
|
|
50
50
|
"async-lock": "1.4.1",
|
|
51
51
|
"asyncbox": "3.0.0",
|
|
52
|
-
"axios": "1.
|
|
52
|
+
"axios": "1.11.0",
|
|
53
53
|
"bluebird": "3.7.2",
|
|
54
|
-
"body-parser": "
|
|
55
|
-
"express": "5.0
|
|
54
|
+
"body-parser": "2.2.0",
|
|
55
|
+
"express": "5.1.0",
|
|
56
56
|
"fastest-levenshtein": "1.0.16",
|
|
57
57
|
"http-status-codes": "2.3.0",
|
|
58
58
|
"lodash": "4.17.21",
|
|
59
|
-
"lru-cache": "
|
|
59
|
+
"lru-cache": "11.1.0",
|
|
60
60
|
"method-override": "3.0.0",
|
|
61
|
-
"morgan": "1.10.
|
|
61
|
+
"morgan": "1.10.1",
|
|
62
62
|
"path-to-regexp": "8.2.0",
|
|
63
|
-
"serve-favicon": "2.5.
|
|
63
|
+
"serve-favicon": "2.5.1",
|
|
64
64
|
"source-map-support": "0.5.21",
|
|
65
|
-
"type-fest": "4.
|
|
65
|
+
"type-fest": "4.41.0"
|
|
66
66
|
},
|
|
67
67
|
"optionalDependencies": {
|
|
68
68
|
"spdy": "4.0.2"
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
|
-
"node": "^20.
|
|
71
|
+
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
|
|
72
72
|
"npm": ">=10"
|
|
73
73
|
},
|
|
74
74
|
"publishConfig": {
|
|
75
75
|
"access": "public",
|
|
76
|
-
"tag": "
|
|
76
|
+
"tag": "rc"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "157425ce6aa01c009533f5bf6a56b14570222b00",
|
|
79
79
|
"tsd": {
|
|
80
80
|
"directory": "test/types"
|
|
81
81
|
}
|