From 8c54f41552b7352032120c95240f18f7191b3b19 Mon Sep 17 00:00:00 2001 From: JoelEinbinder Date: Fri, 6 Apr 2018 18:20:48 -0700 Subject: [PATCH] chore(types): generate a d.ts file for protocol types (#2325) This uses the `/json/protocol` endpoint to generate type definitions for the protocol. Currently it is lacking protocol events and commands, but I will add those later. --- .gitignore | 1 + .npmignore | 4 ++ lib/ElementHandle.js | 2 +- lib/ExecutionContext.js | 4 +- lib/FrameManager.js | 4 +- lib/NetworkManager.js | 6 +-- lib/Page.js | 2 +- lib/helper.js | 6 +-- package.json | 2 +- utils/protocol-types-generator/index.js | 54 +++++++++++++++++++++++++ 10 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 utils/protocol-types-generator/index.js diff --git a/.gitignore b/.gitignore index d4f86bce..fc65c93a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ package-lock.json yarn.lock /node6 +/lib/protocol.d.ts diff --git a/.npmignore b/.npmignore index e8eface1..babb1e7f 100644 --- a/.npmignore +++ b/.npmignore @@ -2,6 +2,10 @@ test utils/node6-transform +# exclude internal type definition files +/lib/*.d.ts +/node6/lib/*.d.ts + # repeats from .gitignore node_modules .local-chromium diff --git a/lib/ElementHandle.js b/lib/ElementHandle.js index 2d8c9999..d3572bfe 100644 --- a/lib/ElementHandle.js +++ b/lib/ElementHandle.js @@ -21,7 +21,7 @@ class ElementHandle extends JSHandle { /** * @param {!Puppeteer.ExecutionContext} context * @param {!Puppeteer.CDPSession} client - * @param {!Object} remoteObject + * @param {!Protocol.Runtime.RemoteObject} remoteObject * @param {!Puppeteer.Page} page * @param {!Puppeteer.FrameManager} frameManager */ diff --git a/lib/ExecutionContext.js b/lib/ExecutionContext.js index 2150924a..280f9b92 100644 --- a/lib/ExecutionContext.js +++ b/lib/ExecutionContext.js @@ -19,7 +19,7 @@ const {helper} = require('./helper'); class ExecutionContext { /** * @param {!Puppeteer.CDPSession} client - * @param {!Object} contextPayload + * @param {!Protocol.Runtime.ExecutionContextDescription} contextPayload * @param {function(*):!JSHandle} objectHandleFactory * @param {?Puppeteer.Frame} frame */ @@ -127,7 +127,7 @@ class JSHandle { /** * @param {!ExecutionContext} context * @param {!Puppeteer.CDPSession} client - * @param {!Object} remoteObject + * @param {!Protocol.Runtime.RemoteObject} remoteObject */ constructor(context, client, remoteObject) { this._context = context; diff --git a/lib/FrameManager.js b/lib/FrameManager.js index 81491c5e..d19d0551 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -111,7 +111,7 @@ class FrameManager extends EventEmitter { } /** - * @param {!Object} framePayload + * @param {!Protocol.Page.Frame} framePayload */ _onFrameNavigated(framePayload) { const isMainFrame = !framePayload.parentId; @@ -743,7 +743,7 @@ class Frame { } /** - * @param {!Object} framePayload + * @param {!Protocol.Page.Frame} framePayload */ _navigated(framePayload) { this._name = framePayload.name; diff --git a/lib/NetworkManager.js b/lib/NetworkManager.js index ddbd773a..a1aabd90 100644 --- a/lib/NetworkManager.js +++ b/lib/NetworkManager.js @@ -202,7 +202,7 @@ class NetworkManager extends EventEmitter { * @param {?string} interceptionId * @param {string} url * @param {string} resourceType - * @param {!Object} requestPayload + * @param {!Protocol.Network.Request} requestPayload * @param {?string} frameId * @param {!Array} redirectChain */ @@ -306,7 +306,7 @@ class Request { * @param {boolean} allowInterception * @param {string} url * @param {string} resourceType - * @param {!Object} payload + * @param {!Protocol.Network.Request} payload * @param {?Puppeteer.Frame} frame * @param {!Array} redirectChain */ @@ -630,7 +630,7 @@ class Response { helper.tracePublicAPI(Response); /** - * @param {!Object} request + * @param {!Protocol.Network.Request} request * @return {string} */ function generateRequestHash(request) { diff --git a/lib/Page.js b/lib/Page.js index 6f9ed28b..221d5277 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -391,7 +391,7 @@ class Page extends EventEmitter { } /** - * @param {?Array} metrics + * @param {?Array} metrics * @return {!Object} */ _buildMetricsObject(metrics) { diff --git a/lib/helper.js b/lib/helper.js index ccaf42b7..cfa6b637 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -56,7 +56,7 @@ class Helper { } /** - * @param {!Object} exceptionDetails + * @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails * @return {string} */ static getExceptionMessage(exceptionDetails) { @@ -74,7 +74,7 @@ class Helper { } /** - * @param {!Object} remoteObject + * @param {!Protocol.Runtime.RemoteObject} remoteObject * @return {*} */ static valueFromRemoteObject(remoteObject) { @@ -98,7 +98,7 @@ class Helper { /** * @param {!Puppeteer.CDPSession} client - * @param {!Object} remoteObject + * @param {!Protocol.Runtime.RemoteObject} remoteObject */ static async releaseObject(client, remoteObject) { if (!remoteObject.objectId) diff --git a/package.json b/package.json index 89d6998a..754df483 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "test-node6-transformer": "node utils/node6-transform/test/test.js", "build": "node utils/node6-transform/index.js", "unit-node6": "node node6/test/test.js", - "tsc": "tsc -p .", + "tsc": "node utils/protocol-types-generator && tsc -p .", "prepublishOnly": "npm run build", "apply-next-version": "node utils/apply_next_version.js" }, diff --git a/utils/protocol-types-generator/index.js b/utils/protocol-types-generator/index.js new file mode 100644 index 00000000..901c6259 --- /dev/null +++ b/utils/protocol-types-generator/index.js @@ -0,0 +1,54 @@ +const puppeteer = require('../..'); +puppeteer.launch({ + pipe: false, + executablePath: process.env.CHROME, + args: ['--no-sandbox', '--disable-dev-shm-usage'] +}).then(async browser => { + const origin = browser.wsEndpoint().match(/ws:\/\/([0-9A-Za-z:\.]*)\//)[1]; + const page = await browser.newPage(); + await page.goto(`http://${origin}/json/protocol`); + const json = JSON.parse(await page.evaluate(() => document.documentElement.innerText)); + await browser.close(); + const output = `// This is generated from /utils/protocol-types-generator/index.js +declare global { + module Protocol { + ${json.domains.map(domain => `${domain.description ? ` + /** + * ${domain.description} + */` : ''} + export module ${domain.domain} { + ${(domain.types || []).map(type => `${type.description ? ` + /** + * ${type.description} + */` : ''}${type.properties ? ` + export interface ${type.id} { + ${(type.properties || []).map(property => `${property.description ? ` + /** + * ${property.description} + */` : ''} + ${property.name}${property.optional ? '?' : ''}: ${typeOfProperty(property)}; + `).join(``)} + }` : ` + export type ${type.id} = ${typeOfProperty(type)};`} + `).join('')} + } + `).join('')} + } +} +// empty export to keep file a module +export {} +`; + require('fs').writeFileSync(require('path').join(__dirname, '..', '..', 'lib', 'protocol.d.ts'), output); +}); + +function typeOfProperty(property) { + if (property.$ref) return property.$ref; + if (property.enum) return property.enum.map(value => JSON.stringify(value)).join('|'); + switch (property.type) { + case 'array': + return typeOfProperty(property.items) + '[]'; + case 'integer': + return 'number'; + } + return property.type; +} \ No newline at end of file