feat(rpc): server-side validator (#3150)
This commit is contained in:
parent
1455cae974
commit
415e94f410
|
|
@ -1440,7 +1440,7 @@ export type RouteContinueParams = {
|
|||
name: string,
|
||||
value: string,
|
||||
}[],
|
||||
postData?: string,
|
||||
postData?: Binary,
|
||||
};
|
||||
export type RouteContinueResult = void;
|
||||
export type RouteFulfillParams = {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import { ChromiumBrowser } from './chromiumBrowser';
|
|||
import { ChromiumBrowserContext } from './chromiumBrowserContext';
|
||||
import { Selectors } from './selectors';
|
||||
import { Stream } from './stream';
|
||||
import { validateParams } from './validator';
|
||||
import { createScheme, Validator, ValidationError } from '../validator';
|
||||
|
||||
class Root extends ChannelOwner<Channel, {}> {
|
||||
constructor(connection: Connection) {
|
||||
|
|
@ -214,3 +214,20 @@ export class Connection {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const tChannel = (name: string): Validator => {
|
||||
return (arg: any, path: string) => {
|
||||
if (arg._object instanceof ChannelOwner && (name === '*' || arg._object._type === name))
|
||||
return { guid: arg._object._guid };
|
||||
throw new ValidationError(`${path}: expected ${name}`);
|
||||
};
|
||||
};
|
||||
|
||||
const scheme = createScheme(tChannel);
|
||||
|
||||
function validateParams(type: string, method: string, params: any): any {
|
||||
const name = type + method[0].toUpperCase() + method.substring(1) + 'Params';
|
||||
if (!scheme[name])
|
||||
throw new ValidationError(`Uknown scheme for ${type}.${method}`);
|
||||
return scheme[name](params, '');
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -18,6 +18,7 @@ import { EventEmitter } from 'events';
|
|||
import { helper, debugAssert, assert } from '../../helper';
|
||||
import { Channel } from '../channels';
|
||||
import { serializeError } from '../serializers';
|
||||
import { createScheme, Validator, ValidationError } from '../validator';
|
||||
|
||||
export const dispatcherSymbol = Symbol('dispatcher');
|
||||
|
||||
|
|
@ -114,6 +115,7 @@ export class DispatcherConnection {
|
|||
readonly _dispatchers = new Map<string, Dispatcher<any, any>>();
|
||||
private _rootDispatcher: Root;
|
||||
onmessage = (message: object) => {};
|
||||
private _validateParams: (type: string, method: string, params: any) => any;
|
||||
|
||||
async sendMessageToClient(guid: string, method: string, params: any): Promise<any> {
|
||||
this.onmessage({ guid, method, params: this._replaceDispatchersWithGuids(params) });
|
||||
|
|
@ -121,6 +123,28 @@ export class DispatcherConnection {
|
|||
|
||||
constructor() {
|
||||
this._rootDispatcher = new Root(this);
|
||||
|
||||
const tChannel = (name: string): Validator => {
|
||||
return (arg: any, path: string) => {
|
||||
if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
|
||||
const guid = arg.guid;
|
||||
const dispatcher = this._dispatchers.get(guid);
|
||||
if (!dispatcher)
|
||||
throw new ValidationError(`${path}: no object with guid ${guid}`);
|
||||
if (name !== '*' && dispatcher._type !== name)
|
||||
throw new ValidationError(`${path}: object with guid ${guid} has type ${dispatcher._type}, expected ${name}`);
|
||||
return dispatcher;
|
||||
}
|
||||
throw new ValidationError(`${path}: expected ${name}`);
|
||||
};
|
||||
};
|
||||
const scheme = createScheme(tChannel);
|
||||
this._validateParams = (type: string, method: string, params: any): any => {
|
||||
const name = type + method[0].toUpperCase() + method.substring(1) + 'Params';
|
||||
if (!scheme[name])
|
||||
throw new ValidationError(`Uknown scheme for ${type}.${method}`);
|
||||
return scheme[name](params, '');
|
||||
};
|
||||
}
|
||||
|
||||
rootDispatcher(): Dispatcher<any, any> {
|
||||
|
|
@ -139,7 +163,8 @@ export class DispatcherConnection {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
const result = await (dispatcher as any)[method](this._replaceGuidsWithDispatchers(params));
|
||||
const validated = this._validateParams(dispatcher._type, method, params);
|
||||
const result = await (dispatcher as any)[method](validated);
|
||||
this.onmessage({ id, result: this._replaceDispatchersWithGuids(result) });
|
||||
} catch (e) {
|
||||
this.onmessage({ id, error: serializeError(e) });
|
||||
|
|
@ -161,20 +186,4 @@ export class DispatcherConnection {
|
|||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
private _replaceGuidsWithDispatchers(payload: any): any {
|
||||
if (!payload)
|
||||
return payload;
|
||||
if (Array.isArray(payload))
|
||||
return payload.map(p => this._replaceGuidsWithDispatchers(p));
|
||||
if (payload.guid && this._dispatchers.has(payload.guid))
|
||||
return this._dispatchers.get(payload.guid);
|
||||
if (typeof payload === 'object') {
|
||||
const result: any = {};
|
||||
for (const key of Object.keys(payload))
|
||||
result[key] = this._replaceGuidsWithDispatchers(payload[key]);
|
||||
return result;
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
869
src/rpc/validator.ts
Normal file
869
src/rpc/validator.ts
Normal file
|
|
@ -0,0 +1,869 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// This file is generated by generate_channels.js, do not edit manually.
|
||||
|
||||
import { Validator, ValidationError, tOptional, tObject, tBoolean, tNumber, tString, tEnum, tArray, tBinary } from './validatorPrimitives';
|
||||
export { Validator, ValidationError } from './validatorPrimitives';
|
||||
|
||||
type Scheme = { [key: string]: Validator };
|
||||
|
||||
export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||
const scheme: Scheme = {};
|
||||
|
||||
const tType = (name: string): Validator => {
|
||||
return (arg: any, path: string) => {
|
||||
const v = scheme[name];
|
||||
if (!v)
|
||||
throw new ValidationError(path + ': unknown type "' + name + '"');
|
||||
return v(arg, path);
|
||||
};
|
||||
};
|
||||
|
||||
scheme.SerializedValue = tObject({
|
||||
n: tOptional(tNumber),
|
||||
b: tOptional(tBoolean),
|
||||
s: tOptional(tString),
|
||||
v: tOptional(tEnum(['null', 'undefined', 'NaN', 'Infinity', '-Infinity', '-0'])),
|
||||
d: tOptional(tString),
|
||||
r: tOptional(tObject({
|
||||
p: tString,
|
||||
f: tString,
|
||||
})),
|
||||
a: tOptional(tArray(tType('SerializedValue'))),
|
||||
o: tOptional(tArray(tObject({
|
||||
k: tString,
|
||||
v: tType('SerializedValue'),
|
||||
}))),
|
||||
h: tOptional(tNumber),
|
||||
});
|
||||
scheme.SerializedArgument = tObject({
|
||||
value: tType('SerializedValue'),
|
||||
handles: tArray(tChannel('*')),
|
||||
});
|
||||
scheme.AXNode = tObject({
|
||||
role: tString,
|
||||
name: tString,
|
||||
valueString: tOptional(tString),
|
||||
valueNumber: tOptional(tNumber),
|
||||
description: tOptional(tString),
|
||||
keyshortcuts: tOptional(tString),
|
||||
roledescription: tOptional(tString),
|
||||
valuetext: tOptional(tString),
|
||||
disabled: tOptional(tBoolean),
|
||||
expanded: tOptional(tBoolean),
|
||||
focused: tOptional(tBoolean),
|
||||
modal: tOptional(tBoolean),
|
||||
multiline: tOptional(tBoolean),
|
||||
multiselectable: tOptional(tBoolean),
|
||||
readonly: tOptional(tBoolean),
|
||||
required: tOptional(tBoolean),
|
||||
selected: tOptional(tBoolean),
|
||||
checked: tOptional(tEnum(['checked', 'unchecked', 'mixed'])),
|
||||
pressed: tOptional(tEnum(['pressed', 'released', 'mixed'])),
|
||||
level: tOptional(tNumber),
|
||||
valuemin: tOptional(tNumber),
|
||||
valuemax: tOptional(tNumber),
|
||||
autocomplete: tOptional(tString),
|
||||
haspopup: tOptional(tString),
|
||||
invalid: tOptional(tString),
|
||||
orientation: tOptional(tString),
|
||||
children: tOptional(tArray(tType('AXNode'))),
|
||||
});
|
||||
scheme.SerializedError = tObject({
|
||||
error: tOptional(tObject({
|
||||
message: tString,
|
||||
name: tString,
|
||||
stack: tOptional(tString),
|
||||
})),
|
||||
value: tOptional(tType('SerializedValue')),
|
||||
});
|
||||
scheme.SelectorsRegisterParams = tObject({
|
||||
name: tString,
|
||||
source: tString,
|
||||
contentScript: tOptional(tBoolean),
|
||||
});
|
||||
scheme.SelectorsCreateSelectorParams = tObject({
|
||||
name: tString,
|
||||
handle: tChannel('ElementHandle'),
|
||||
});
|
||||
scheme.BrowserTypeConnectParams = tObject({
|
||||
wsEndpoint: tString,
|
||||
slowMo: tOptional(tNumber),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.BrowserTypeLaunchParams = tObject({
|
||||
executablePath: tOptional(tString),
|
||||
args: tOptional(tArray(tString)),
|
||||
ignoreAllDefaultArgs: tOptional(tBoolean),
|
||||
ignoreDefaultArgs: tOptional(tArray(tString)),
|
||||
handleSIGINT: tOptional(tBoolean),
|
||||
handleSIGTERM: tOptional(tBoolean),
|
||||
handleSIGHUP: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
env: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
headless: tOptional(tBoolean),
|
||||
devtools: tOptional(tBoolean),
|
||||
proxy: tOptional(tObject({
|
||||
server: tString,
|
||||
bypass: tOptional(tString),
|
||||
username: tOptional(tString),
|
||||
password: tOptional(tString),
|
||||
})),
|
||||
downloadsPath: tOptional(tString),
|
||||
firefoxUserPrefs: tOptional(tType('SerializedValue')),
|
||||
slowMo: tOptional(tNumber),
|
||||
});
|
||||
scheme.BrowserTypeLaunchServerParams = tObject({
|
||||
executablePath: tOptional(tString),
|
||||
args: tOptional(tArray(tString)),
|
||||
ignoreAllDefaultArgs: tOptional(tBoolean),
|
||||
ignoreDefaultArgs: tOptional(tArray(tString)),
|
||||
handleSIGINT: tOptional(tBoolean),
|
||||
handleSIGTERM: tOptional(tBoolean),
|
||||
handleSIGHUP: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
env: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
headless: tOptional(tBoolean),
|
||||
devtools: tOptional(tBoolean),
|
||||
proxy: tOptional(tObject({
|
||||
server: tString,
|
||||
bypass: tOptional(tString),
|
||||
username: tOptional(tString),
|
||||
password: tOptional(tString),
|
||||
})),
|
||||
downloadsPath: tOptional(tString),
|
||||
firefoxUserPrefs: tOptional(tType('SerializedValue')),
|
||||
port: tOptional(tNumber),
|
||||
});
|
||||
scheme.BrowserTypeLaunchPersistentContextParams = tObject({
|
||||
userDataDir: tString,
|
||||
executablePath: tOptional(tString),
|
||||
args: tOptional(tArray(tString)),
|
||||
ignoreAllDefaultArgs: tOptional(tBoolean),
|
||||
ignoreDefaultArgs: tOptional(tArray(tString)),
|
||||
handleSIGINT: tOptional(tBoolean),
|
||||
handleSIGTERM: tOptional(tBoolean),
|
||||
handleSIGHUP: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
env: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
headless: tOptional(tBoolean),
|
||||
devtools: tOptional(tBoolean),
|
||||
proxy: tOptional(tObject({
|
||||
server: tString,
|
||||
bypass: tOptional(tString),
|
||||
username: tOptional(tString),
|
||||
password: tOptional(tString),
|
||||
})),
|
||||
downloadsPath: tOptional(tString),
|
||||
slowMo: tOptional(tNumber),
|
||||
noDefaultViewport: tOptional(tBoolean),
|
||||
viewport: tOptional(tObject({
|
||||
width: tNumber,
|
||||
height: tNumber,
|
||||
})),
|
||||
ignoreHTTPSErrors: tOptional(tBoolean),
|
||||
javaScriptEnabled: tOptional(tBoolean),
|
||||
bypassCSP: tOptional(tBoolean),
|
||||
userAgent: tOptional(tString),
|
||||
locale: tOptional(tString),
|
||||
timezoneId: tOptional(tString),
|
||||
geolocation: tOptional(tObject({
|
||||
longitude: tNumber,
|
||||
latitude: tNumber,
|
||||
accuracy: tOptional(tNumber),
|
||||
})),
|
||||
permissions: tOptional(tArray(tString)),
|
||||
extraHTTPHeaders: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
offline: tOptional(tBoolean),
|
||||
httpCredentials: tOptional(tObject({
|
||||
username: tString,
|
||||
password: tString,
|
||||
})),
|
||||
deviceScaleFactor: tOptional(tNumber),
|
||||
isMobile: tOptional(tBoolean),
|
||||
hasTouch: tOptional(tBoolean),
|
||||
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference'])),
|
||||
acceptDownloads: tOptional(tBoolean),
|
||||
});
|
||||
scheme.BrowserServerCloseParams = tOptional(tObject({}));
|
||||
scheme.BrowserServerKillParams = tOptional(tObject({}));
|
||||
scheme.BrowserCloseParams = tOptional(tObject({}));
|
||||
scheme.BrowserNewContextParams = tObject({
|
||||
noDefaultViewport: tOptional(tBoolean),
|
||||
viewport: tOptional(tObject({
|
||||
width: tNumber,
|
||||
height: tNumber,
|
||||
})),
|
||||
ignoreHTTPSErrors: tOptional(tBoolean),
|
||||
javaScriptEnabled: tOptional(tBoolean),
|
||||
bypassCSP: tOptional(tBoolean),
|
||||
userAgent: tOptional(tString),
|
||||
locale: tOptional(tString),
|
||||
timezoneId: tOptional(tString),
|
||||
geolocation: tOptional(tObject({
|
||||
longitude: tNumber,
|
||||
latitude: tNumber,
|
||||
accuracy: tOptional(tNumber),
|
||||
})),
|
||||
permissions: tOptional(tArray(tString)),
|
||||
extraHTTPHeaders: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
offline: tOptional(tBoolean),
|
||||
httpCredentials: tOptional(tObject({
|
||||
username: tString,
|
||||
password: tString,
|
||||
})),
|
||||
deviceScaleFactor: tOptional(tNumber),
|
||||
isMobile: tOptional(tBoolean),
|
||||
hasTouch: tOptional(tBoolean),
|
||||
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference'])),
|
||||
acceptDownloads: tOptional(tBoolean),
|
||||
});
|
||||
scheme.BrowserCrNewBrowserCDPSessionParams = tOptional(tObject({}));
|
||||
scheme.BrowserCrStartTracingParams = tObject({
|
||||
page: tOptional(tChannel('Page')),
|
||||
path: tOptional(tString),
|
||||
screenshots: tOptional(tBoolean),
|
||||
categories: tOptional(tArray(tString)),
|
||||
});
|
||||
scheme.BrowserCrStopTracingParams = tOptional(tObject({}));
|
||||
scheme.BrowserContextAddCookiesParams = tObject({
|
||||
cookies: tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
url: tOptional(tString),
|
||||
domain: tOptional(tString),
|
||||
path: tOptional(tString),
|
||||
expires: tOptional(tNumber),
|
||||
httpOnly: tOptional(tBoolean),
|
||||
secure: tOptional(tBoolean),
|
||||
sameSite: tOptional(tEnum(['Strict', 'Lax', 'None'])),
|
||||
})),
|
||||
});
|
||||
scheme.BrowserContextAddInitScriptParams = tObject({
|
||||
source: tString,
|
||||
});
|
||||
scheme.BrowserContextClearCookiesParams = tOptional(tObject({}));
|
||||
scheme.BrowserContextClearPermissionsParams = tOptional(tObject({}));
|
||||
scheme.BrowserContextCloseParams = tOptional(tObject({}));
|
||||
scheme.BrowserContextCookiesParams = tObject({
|
||||
urls: tArray(tString),
|
||||
});
|
||||
scheme.BrowserContextExposeBindingParams = tObject({
|
||||
name: tString,
|
||||
});
|
||||
scheme.BrowserContextGrantPermissionsParams = tObject({
|
||||
permissions: tArray(tString),
|
||||
origin: tOptional(tString),
|
||||
});
|
||||
scheme.BrowserContextNewPageParams = tOptional(tObject({}));
|
||||
scheme.BrowserContextSetDefaultNavigationTimeoutNoReplyParams = tObject({
|
||||
timeout: tNumber,
|
||||
});
|
||||
scheme.BrowserContextSetDefaultTimeoutNoReplyParams = tObject({
|
||||
timeout: tNumber,
|
||||
});
|
||||
scheme.BrowserContextSetExtraHTTPHeadersParams = tObject({
|
||||
headers: tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
})),
|
||||
});
|
||||
scheme.BrowserContextSetGeolocationParams = tObject({
|
||||
geolocation: tOptional(tObject({
|
||||
longitude: tNumber,
|
||||
latitude: tNumber,
|
||||
accuracy: tOptional(tNumber),
|
||||
})),
|
||||
});
|
||||
scheme.BrowserContextSetHTTPCredentialsParams = tObject({
|
||||
httpCredentials: tOptional(tObject({
|
||||
username: tString,
|
||||
password: tString,
|
||||
})),
|
||||
});
|
||||
scheme.BrowserContextSetNetworkInterceptionEnabledParams = tObject({
|
||||
enabled: tBoolean,
|
||||
});
|
||||
scheme.BrowserContextSetOfflineParams = tObject({
|
||||
offline: tBoolean,
|
||||
});
|
||||
scheme.BrowserContextCrNewCDPSessionParams = tObject({
|
||||
page: tChannel('Page'),
|
||||
});
|
||||
scheme.PageSetDefaultNavigationTimeoutNoReplyParams = tObject({
|
||||
timeout: tNumber,
|
||||
});
|
||||
scheme.PageSetDefaultTimeoutNoReplyParams = tObject({
|
||||
timeout: tNumber,
|
||||
});
|
||||
scheme.PageSetFileChooserInterceptedNoReplyParams = tObject({
|
||||
intercepted: tBoolean,
|
||||
});
|
||||
scheme.PageAddInitScriptParams = tObject({
|
||||
source: tString,
|
||||
});
|
||||
scheme.PageCloseParams = tObject({
|
||||
runBeforeUnload: tOptional(tBoolean),
|
||||
});
|
||||
scheme.PageEmulateMediaParams = tObject({
|
||||
media: tOptional(tEnum(['screen', 'print', 'null'])),
|
||||
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'null'])),
|
||||
});
|
||||
scheme.PageExposeBindingParams = tObject({
|
||||
name: tString,
|
||||
});
|
||||
scheme.PageGoBackParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
waitUntil: tOptional(tEnum(['load', 'domcontentloaded', 'networkidle'])),
|
||||
});
|
||||
scheme.PageGoForwardParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
waitUntil: tOptional(tEnum(['load', 'domcontentloaded', 'networkidle'])),
|
||||
});
|
||||
scheme.PageOpenerParams = tOptional(tObject({}));
|
||||
scheme.PageReloadParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
waitUntil: tOptional(tEnum(['load', 'domcontentloaded', 'networkidle'])),
|
||||
});
|
||||
scheme.PageScreenshotParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
type: tOptional(tEnum(['png', 'jpeg'])),
|
||||
path: tOptional(tString),
|
||||
quality: tOptional(tNumber),
|
||||
omitBackground: tOptional(tBoolean),
|
||||
fullPage: tOptional(tBoolean),
|
||||
clip: tOptional(tObject({
|
||||
width: tNumber,
|
||||
height: tNumber,
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
});
|
||||
scheme.PageSetExtraHTTPHeadersParams = tObject({
|
||||
headers: tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
})),
|
||||
});
|
||||
scheme.PageSetNetworkInterceptionEnabledParams = tObject({
|
||||
enabled: tBoolean,
|
||||
});
|
||||
scheme.PageSetViewportSizeParams = tObject({
|
||||
viewportSize: tObject({
|
||||
width: tNumber,
|
||||
height: tNumber,
|
||||
}),
|
||||
});
|
||||
scheme.PageKeyboardDownParams = tObject({
|
||||
key: tString,
|
||||
});
|
||||
scheme.PageKeyboardUpParams = tObject({
|
||||
key: tString,
|
||||
});
|
||||
scheme.PageKeyboardInsertTextParams = tObject({
|
||||
text: tString,
|
||||
});
|
||||
scheme.PageKeyboardTypeParams = tObject({
|
||||
text: tString,
|
||||
delay: tOptional(tNumber),
|
||||
});
|
||||
scheme.PageKeyboardPressParams = tObject({
|
||||
key: tString,
|
||||
delay: tOptional(tNumber),
|
||||
});
|
||||
scheme.PageMouseMoveParams = tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
steps: tOptional(tNumber),
|
||||
});
|
||||
scheme.PageMouseDownParams = tObject({
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
clickCount: tOptional(tNumber),
|
||||
});
|
||||
scheme.PageMouseUpParams = tObject({
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
clickCount: tOptional(tNumber),
|
||||
});
|
||||
scheme.PageMouseClickParams = tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
delay: tOptional(tNumber),
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
clickCount: tOptional(tNumber),
|
||||
});
|
||||
scheme.PageAccessibilitySnapshotParams = tObject({
|
||||
interestingOnly: tOptional(tBoolean),
|
||||
root: tOptional(tChannel('ElementHandle')),
|
||||
});
|
||||
scheme.PagePdfParams = tObject({
|
||||
scale: tOptional(tNumber),
|
||||
displayHeaderFooter: tOptional(tBoolean),
|
||||
headerTemplate: tOptional(tString),
|
||||
footerTemplate: tOptional(tString),
|
||||
printBackground: tOptional(tBoolean),
|
||||
landscape: tOptional(tBoolean),
|
||||
pageRanges: tOptional(tString),
|
||||
format: tOptional(tString),
|
||||
width: tOptional(tString),
|
||||
height: tOptional(tString),
|
||||
preferCSSPageSize: tOptional(tBoolean),
|
||||
margin: tOptional(tObject({
|
||||
top: tOptional(tString),
|
||||
bottom: tOptional(tString),
|
||||
left: tOptional(tString),
|
||||
right: tOptional(tString),
|
||||
})),
|
||||
});
|
||||
scheme.PageCrStartJSCoverageParams = tObject({
|
||||
resetOnNavigation: tOptional(tBoolean),
|
||||
reportAnonymousScripts: tOptional(tBoolean),
|
||||
});
|
||||
scheme.PageCrStopJSCoverageParams = tOptional(tObject({}));
|
||||
scheme.PageCrStartCSSCoverageParams = tObject({
|
||||
resetOnNavigation: tOptional(tBoolean),
|
||||
});
|
||||
scheme.PageCrStopCSSCoverageParams = tOptional(tObject({}));
|
||||
scheme.PageBringToFrontParams = tOptional(tObject({}));
|
||||
scheme.FrameEvalOnSelectorParams = tObject({
|
||||
selector: tString,
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.FrameEvalOnSelectorAllParams = tObject({
|
||||
selector: tString,
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.FrameAddScriptTagParams = tObject({
|
||||
url: tOptional(tString),
|
||||
content: tOptional(tString),
|
||||
type: tOptional(tString),
|
||||
});
|
||||
scheme.FrameAddStyleTagParams = tObject({
|
||||
url: tOptional(tString),
|
||||
content: tOptional(tString),
|
||||
});
|
||||
scheme.FrameCheckParams = tObject({
|
||||
selector: tString,
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameClickParams = tObject({
|
||||
selector: tString,
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
|
||||
position: tOptional(tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
delay: tOptional(tNumber),
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
clickCount: tOptional(tNumber),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameContentParams = tOptional(tObject({}));
|
||||
scheme.FrameDblclickParams = tObject({
|
||||
selector: tString,
|
||||
force: tOptional(tBoolean),
|
||||
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
|
||||
position: tOptional(tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
delay: tOptional(tNumber),
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameDispatchEventParams = tObject({
|
||||
selector: tString,
|
||||
type: tString,
|
||||
eventInit: tType('SerializedArgument'),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameEvaluateExpressionParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.FrameEvaluateExpressionHandleParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.FrameFillParams = tObject({
|
||||
selector: tString,
|
||||
value: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.FrameFocusParams = tObject({
|
||||
selector: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameFrameElementParams = tOptional(tObject({}));
|
||||
scheme.FrameGetAttributeParams = tObject({
|
||||
selector: tString,
|
||||
name: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameGotoParams = tObject({
|
||||
url: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
waitUntil: tOptional(tEnum(['load', 'domcontentloaded', 'networkidle'])),
|
||||
referer: tOptional(tString),
|
||||
});
|
||||
scheme.FrameHoverParams = tObject({
|
||||
selector: tString,
|
||||
force: tOptional(tBoolean),
|
||||
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
|
||||
position: tOptional(tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameInnerHTMLParams = tObject({
|
||||
selector: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameInnerTextParams = tObject({
|
||||
selector: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FramePressParams = tObject({
|
||||
selector: tString,
|
||||
key: tString,
|
||||
delay: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameQuerySelectorParams = tObject({
|
||||
selector: tString,
|
||||
});
|
||||
scheme.FrameQuerySelectorAllParams = tObject({
|
||||
selector: tString,
|
||||
});
|
||||
scheme.FrameSelectOptionParams = tObject({
|
||||
selector: tString,
|
||||
elements: tOptional(tArray(tChannel('ElementHandle'))),
|
||||
options: tOptional(tArray(tObject({
|
||||
value: tOptional(tString),
|
||||
label: tOptional(tString),
|
||||
index: tOptional(tNumber),
|
||||
}))),
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.FrameSetContentParams = tObject({
|
||||
html: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
waitUntil: tOptional(tEnum(['load', 'domcontentloaded', 'networkidle'])),
|
||||
});
|
||||
scheme.FrameSetInputFilesParams = tObject({
|
||||
selector: tString,
|
||||
files: tArray(tObject({
|
||||
name: tString,
|
||||
mimeType: tString,
|
||||
buffer: tString,
|
||||
})),
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.FrameTextContentParams = tObject({
|
||||
selector: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameTitleParams = tOptional(tObject({}));
|
||||
scheme.FrameTypeParams = tObject({
|
||||
selector: tString,
|
||||
text: tString,
|
||||
delay: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameUncheckParams = tObject({
|
||||
selector: tString,
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameWaitForFunctionParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
timeout: tOptional(tNumber),
|
||||
pollingInterval: tOptional(tNumber),
|
||||
});
|
||||
scheme.FrameWaitForSelectorParams = tObject({
|
||||
selector: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
|
||||
});
|
||||
scheme.WorkerEvaluateExpressionParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.WorkerEvaluateExpressionHandleParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.JSHandleDisposeParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleDisposeParams = tType('JSHandleDisposeParams');
|
||||
scheme.JSHandleEvaluateExpressionParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElementHandleEvaluateExpressionParams = tType('JSHandleEvaluateExpressionParams');
|
||||
scheme.JSHandleEvaluateExpressionHandleParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElementHandleEvaluateExpressionHandleParams = tType('JSHandleEvaluateExpressionHandleParams');
|
||||
scheme.JSHandleGetPropertyListParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleGetPropertyListParams = tType('JSHandleGetPropertyListParams');
|
||||
scheme.JSHandleGetPropertyParams = tObject({
|
||||
name: tString,
|
||||
});
|
||||
scheme.ElementHandleGetPropertyParams = tType('JSHandleGetPropertyParams');
|
||||
scheme.JSHandleJsonValueParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleJsonValueParams = tType('JSHandleJsonValueParams');
|
||||
scheme.ElementHandleEvalOnSelectorParams = tObject({
|
||||
selector: tString,
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElementHandleEvalOnSelectorAllParams = tObject({
|
||||
selector: tString,
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElementHandleBoundingBoxParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleCheckParams = tObject({
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleClickParams = tObject({
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
|
||||
position: tOptional(tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
delay: tOptional(tNumber),
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
clickCount: tOptional(tNumber),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleContentFrameParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleDblclickParams = tObject({
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
|
||||
position: tOptional(tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
delay: tOptional(tNumber),
|
||||
button: tOptional(tEnum(['left', 'right', 'middle'])),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleDispatchEventParams = tObject({
|
||||
type: tString,
|
||||
eventInit: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElementHandleFillParams = tObject({
|
||||
value: tString,
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.ElementHandleFocusParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleGetAttributeParams = tObject({
|
||||
name: tString,
|
||||
});
|
||||
scheme.ElementHandleHoverParams = tObject({
|
||||
force: tOptional(tBoolean),
|
||||
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
|
||||
position: tOptional(tObject({
|
||||
x: tNumber,
|
||||
y: tNumber,
|
||||
})),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleInnerHTMLParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleInnerTextParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleOwnerFrameParams = tOptional(tObject({}));
|
||||
scheme.ElementHandlePressParams = tObject({
|
||||
key: tString,
|
||||
delay: tOptional(tNumber),
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.ElementHandleQuerySelectorParams = tObject({
|
||||
selector: tString,
|
||||
});
|
||||
scheme.ElementHandleQuerySelectorAllParams = tObject({
|
||||
selector: tString,
|
||||
});
|
||||
scheme.ElementHandleScreenshotParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
type: tOptional(tEnum(['png', 'jpeg'])),
|
||||
path: tOptional(tString),
|
||||
quality: tOptional(tNumber),
|
||||
omitBackground: tOptional(tBoolean),
|
||||
});
|
||||
scheme.ElementHandleScrollIntoViewIfNeededParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleSelectOptionParams = tObject({
|
||||
elements: tOptional(tArray(tChannel('ElementHandle'))),
|
||||
options: tOptional(tArray(tObject({
|
||||
value: tOptional(tString),
|
||||
label: tOptional(tString),
|
||||
index: tOptional(tNumber),
|
||||
}))),
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.ElementHandleSelectTextParams = tObject({
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleSetInputFilesParams = tObject({
|
||||
files: tArray(tObject({
|
||||
name: tString,
|
||||
mimeType: tString,
|
||||
buffer: tString,
|
||||
})),
|
||||
timeout: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
});
|
||||
scheme.ElementHandleTextContentParams = tOptional(tObject({}));
|
||||
scheme.ElementHandleTypeParams = tObject({
|
||||
text: tString,
|
||||
delay: tOptional(tNumber),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElementHandleUncheckParams = tObject({
|
||||
force: tOptional(tBoolean),
|
||||
noWaitAfter: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.RequestResponseParams = tOptional(tObject({}));
|
||||
scheme.RouteAbortParams = tObject({
|
||||
errorCode: tString,
|
||||
});
|
||||
scheme.RouteContinueParams = tObject({
|
||||
method: tOptional(tString),
|
||||
headers: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
postData: tOptional(tBinary),
|
||||
});
|
||||
scheme.RouteFulfillParams = tObject({
|
||||
status: tNumber,
|
||||
headers: tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
})),
|
||||
body: tString,
|
||||
isBase64: tBoolean,
|
||||
});
|
||||
scheme.ResponseBodyParams = tOptional(tObject({}));
|
||||
scheme.ResponseFinishedParams = tOptional(tObject({}));
|
||||
scheme.BindingCallRejectParams = tObject({
|
||||
error: tType('SerializedError'),
|
||||
});
|
||||
scheme.BindingCallResolveParams = tObject({
|
||||
result: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.DialogAcceptParams = tObject({
|
||||
promptText: tOptional(tString),
|
||||
});
|
||||
scheme.DialogDismissParams = tOptional(tObject({}));
|
||||
scheme.DownloadPathParams = tOptional(tObject({}));
|
||||
scheme.DownloadSaveAsParams = tObject({
|
||||
path: tString,
|
||||
});
|
||||
scheme.DownloadFailureParams = tOptional(tObject({}));
|
||||
scheme.DownloadStreamParams = tOptional(tObject({}));
|
||||
scheme.DownloadDeleteParams = tOptional(tObject({}));
|
||||
scheme.StreamReadParams = tObject({
|
||||
size: tOptional(tNumber),
|
||||
});
|
||||
scheme.CDPSessionSendParams = tObject({
|
||||
method: tString,
|
||||
params: tOptional(tType('SerializedValue')),
|
||||
});
|
||||
scheme.CDPSessionDetachParams = tOptional(tObject({}));
|
||||
scheme.ElectronLaunchParams = tObject({
|
||||
executablePath: tString,
|
||||
args: tOptional(tArray(tString)),
|
||||
cwd: tOptional(tString),
|
||||
env: tOptional(tArray(tObject({
|
||||
name: tString,
|
||||
value: tString,
|
||||
}))),
|
||||
handleSIGINT: tOptional(tBoolean),
|
||||
handleSIGTERM: tOptional(tBoolean),
|
||||
handleSIGHUP: tOptional(tBoolean),
|
||||
timeout: tOptional(tNumber),
|
||||
});
|
||||
scheme.ElectronApplicationNewBrowserWindowParams = tObject({
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElectronApplicationEvaluateExpressionParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElectronApplicationEvaluateExpressionHandleParams = tObject({
|
||||
expression: tString,
|
||||
isFunction: tBoolean,
|
||||
arg: tType('SerializedArgument'),
|
||||
});
|
||||
scheme.ElectronApplicationCloseParams = tOptional(tObject({}));
|
||||
|
||||
return scheme;
|
||||
}
|
||||
|
|
@ -14,19 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { isUnderTest } from '../../helper';
|
||||
import { isUnderTest } from '../helper';
|
||||
|
||||
class ValidationError extends Error {}
|
||||
|
||||
export function validateParams(type: string, method: string, params: any): any {
|
||||
const name = type + method[0].toUpperCase() + method.substring(1) + 'Params';
|
||||
if (!scheme[name])
|
||||
throw new ValidationError(`Uknown scheme for ${type}.${method}`);
|
||||
return scheme[name](params, '');
|
||||
}
|
||||
|
||||
type Validator = (arg: any, path: string) => any;
|
||||
export class ValidationError extends Error {}
|
||||
export type Validator = (arg: any, path: string) => any;
|
||||
|
||||
export const tNumber: Validator = (arg: any, path: string) => {
|
||||
if (arg instanceof Number)
|
||||
|
|
@ -50,7 +41,6 @@ export const tString: Validator = (arg: any, path: string) => {
|
|||
throw new ValidationError(`${path}: expected string, got ${typeof arg}`);
|
||||
};
|
||||
export const tBinary: Validator = (arg: any, path: string) => {
|
||||
// TODO: convert from Buffer here.
|
||||
if (arg instanceof String)
|
||||
return arg.valueOf();
|
||||
if (typeof arg === 'string')
|
||||
|
|
@ -104,20 +94,3 @@ export const tEnum = (e: string[]): Validator => {
|
|||
return arg;
|
||||
};
|
||||
};
|
||||
export const tChannel = (name: string): Validator => {
|
||||
return (arg: any, path: string) => {
|
||||
if (arg._object instanceof ChannelOwner && (name === '*' || arg._object._type === name))
|
||||
return { guid: arg._object._guid };
|
||||
throw new ValidationError(`${path}: expected ${name}`);
|
||||
};
|
||||
};
|
||||
export const tType = (name: string): Validator => {
|
||||
return (arg: any, path: string) => {
|
||||
const v = scheme[name];
|
||||
if (!v)
|
||||
throw new ValidationError(`${path}: unknown type "${name}"`);
|
||||
return v(arg, path);
|
||||
};
|
||||
};
|
||||
|
||||
export const scheme: { [key: string]: Validator } = {};
|
||||
|
|
@ -116,7 +116,7 @@ export interface Channel extends EventEmitter {
|
|||
}
|
||||
`];
|
||||
|
||||
const client_validator_ts = [
|
||||
const validator_ts = [
|
||||
`/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
|
|
@ -135,15 +135,30 @@ const client_validator_ts = [
|
|||
|
||||
// This file is generated by ${path.basename(__filename)}, do not edit manually.
|
||||
|
||||
import { scheme, tOptional, tObject, tBoolean, tNumber, tString, tType, tEnum, tArray, tChannel, tUndefined, tBinary } from './validatorPrimitives';
|
||||
export { validateParams } from './validatorPrimitives';
|
||||
import { Validator, ValidationError, tOptional, tObject, tBoolean, tNumber, tString, tEnum, tArray, tBinary } from './validatorPrimitives';
|
||||
export { Validator, ValidationError } from './validatorPrimitives';
|
||||
|
||||
type Scheme = { [key: string]: Validator };
|
||||
|
||||
export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||
const scheme: Scheme = {};
|
||||
|
||||
const tType = (name: string): Validator => {
|
||||
return (arg: any, path: string) => {
|
||||
const v = scheme[name];
|
||||
if (!v)
|
||||
throw new ValidationError(path + ': unknown type "' + name + '"');
|
||||
return v(arg, path);
|
||||
};
|
||||
};
|
||||
`];
|
||||
|
||||
const yml = fs.readFileSync(path.join(__dirname, '..', 'src', 'rpc', 'protocol.yml'), 'utf-8');
|
||||
const protocol = yaml.parse(yml);
|
||||
|
||||
function addScheme(name, s) {
|
||||
client_validator_ts.push(`scheme.${name} = ${s};`);
|
||||
const lines = `scheme.${name} = ${s};`.split('\n');
|
||||
validator_ts.push(...lines.map(line => ' ' + line));
|
||||
}
|
||||
|
||||
const inherits = new Map();
|
||||
|
|
@ -162,7 +177,6 @@ for (const [name, item] of Object.entries(protocol)) {
|
|||
const init = objectType(item.initializer || {}, '');
|
||||
const initializerName = channelName + 'Initializer';
|
||||
channels_ts.push(`export type ${initializerName} = ${init.ts};`);
|
||||
addScheme(initializerName, init.scheme);
|
||||
|
||||
channels_ts.push(`export interface ${channelName}Channel extends ${(item.extends || '') + 'Channel'} {`);
|
||||
const ts_types = new Map();
|
||||
|
|
@ -173,13 +187,7 @@ for (const [name, item] of Object.entries(protocol)) {
|
|||
const parameters = objectType(event.parameters || {}, '');
|
||||
const paramsName = `${channelName}${titleCase(eventName)}Event`;
|
||||
ts_types.set(paramsName, parameters.ts);
|
||||
addScheme(paramsName, parameters.scheme);
|
||||
|
||||
channels_ts.push(` on(event: '${eventName}', callback: (params: ${paramsName}) => void): this;`);
|
||||
for (const key of inherits.keys()) {
|
||||
if (inherits.get(key) === channelName)
|
||||
addScheme(`${key}${titleCase(eventName)}Event`, `tType('${paramsName}')`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let [methodName, method] of Object.entries(item.commands || {})) {
|
||||
|
|
@ -189,19 +197,16 @@ for (const [name, item] of Object.entries(protocol)) {
|
|||
const paramsName = `${channelName}${titleCase(methodName)}Params`;
|
||||
ts_types.set(paramsName, parameters.ts);
|
||||
addScheme(paramsName, method.parameters ? parameters.scheme : `tOptional(tObject({}))`);
|
||||
for (const key of inherits.keys()) {
|
||||
if (inherits.get(key) === channelName)
|
||||
addScheme(`${key}${titleCase(methodName)}Params`, `tType('${paramsName}')`);
|
||||
}
|
||||
|
||||
const resultName = `${channelName}${titleCase(methodName)}Result`;
|
||||
const returns = objectType(method.returns || {}, '');
|
||||
ts_types.set(resultName, method.returns ? returns.ts : 'void');
|
||||
addScheme(resultName, method.returns ? returns.scheme : `tUndefined`);
|
||||
|
||||
channels_ts.push(` ${methodName}(params${method.parameters ? '' : '?'}: ${paramsName}): Promise<${resultName}>;`);
|
||||
for (const key of inherits.keys()) {
|
||||
if (inherits.get(key) === channelName) {
|
||||
addScheme(`${key}${titleCase(methodName)}Params`, `tType('${paramsName}')`);
|
||||
addScheme(`${key}${titleCase(methodName)}Result`, `tType('${resultName}')`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
channels_ts.push(`}`);
|
||||
|
|
@ -215,6 +220,10 @@ for (const [name, item] of Object.entries(protocol)) {
|
|||
channels_ts.push(``);
|
||||
}
|
||||
|
||||
client_validator_ts.push(``);
|
||||
validator_ts.push(`
|
||||
return scheme;
|
||||
}
|
||||
`);
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, '..', 'src', 'rpc', 'channels.ts'), channels_ts.join('\n'), 'utf-8');
|
||||
fs.writeFileSync(path.join(__dirname, '..', 'src', 'rpc', 'client', 'validator.ts'), client_validator_ts.join('\n'), 'utf-8');
|
||||
fs.writeFileSync(path.join(__dirname, '..', 'src', 'rpc', 'validator.ts'), validator_ts.join('\n'), 'utf-8');
|
||||
|
|
|
|||
Loading…
Reference in a new issue