-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[🔥AUDIT🔥] [rg.audit.1] Add custom flow file for render-environment-js…
…dom to work around flowgen issue (#616) 🖍 _This is an audit!_ 🖍 ## Summary: - Add the faster flowgen script from Wonder Blocks, and include the "custom overrides" support. - Fix some flow type issues for core and render-environment-jsdom. Issue: FEI-4960 ## Test plan: `yarn clean && yarn build && yarn build:types && yarn build:flowtypes` Also check that the types will work for the usages I have to hand. Author: somewhatabstract Auditors: somewhatabstract, #typescript, #frontend-infra Required Reviewers: Approved By: Checks: ⌛ Lint, typecheck, and coverage check (ubuntu-latest, 16.x), ✅ gerald, ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 16.x), ⌛ Analyze (javascript), ⏭ dependabot Pull Request URL: #616
- Loading branch information
1 parent
7a3ba71
commit 0299cc9
Showing
4 changed files
with
198 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@khanacademy/wonder-stuff-render-environment-jsdom": patch | ||
"@khanacademy/wonder-stuff-core": patch | ||
--- | ||
|
||
Fix some errors in the generated flow types |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,70 @@ | ||
import {execFileSync} from "child_process"; | ||
import * as fs from "fs"; | ||
import * as path from "path"; | ||
import * as fglob from "fast-glob"; | ||
import {compiler, beautify} from "flowgen"; | ||
|
||
const rootDir = path.join(__dirname, ".."); | ||
const files = fglob.sync("packages/wonder-stuff-*/dist/**/*.d.ts", { | ||
cwd: rootDir, | ||
}); | ||
|
||
if (files.length) { | ||
console.log(`found ${files.length} files`); | ||
} else { | ||
throw new Error("no typescript type definitions found"); | ||
} | ||
|
||
// The node API for `flowgen` doesn't have an option to add a flow header | ||
// so we need to do it ourselves. | ||
const HEADER = `/** | ||
* Flowtype definitions for data | ||
* Generated by Flowgen from a Typescript Definition | ||
* Flowgen v1.21.0 | ||
* @flow | ||
*/ | ||
`; | ||
|
||
let errorCount = 0; | ||
for (const inFile of files) { | ||
const outFile = inFile.replace(".d.ts", ".js.flow"); | ||
const args = ["flowgen", inFile, "-o", outFile, "--add-flow-header"]; | ||
|
||
const overrideFile = outFile.replace("/dist/", "/src/"); | ||
if (fs.existsSync(overrideFile)) { | ||
console.log(`copying\nfrom: ${overrideFile}\nto: ${outFile}`); | ||
fs.cpSync( | ||
path.join(rootDir, overrideFile), | ||
path.join(rootDir, outFile), | ||
); | ||
continue; | ||
} | ||
|
||
try { | ||
execFileSync("yarn", args, {cwd: rootDir}); | ||
console.log(`✅ wrote: ${outFile}`); | ||
const source = fs.readFileSync(path.join(rootDir, inFile), "utf-8"); | ||
const options = {inexact: false}; | ||
let contents: string = compiler.compileDefinitionString( | ||
source, | ||
options, | ||
); | ||
contents = beautify(contents); | ||
|
||
// `flowgen` sometimes outputs code that uses `mixins` instead of `extends` | ||
// so we do some post-processing on the files to clean that up. | ||
const contents = fs.readFileSync(path.join(rootDir, outFile), "utf-8"); | ||
if (contents.includes(" mixins ")) { | ||
contents = contents.replace(/ mixins /g, " extends "); | ||
console.log("replacing 'mixins' with 'extends'"); | ||
fs.writeFileSync( | ||
path.join(rootDir, outFile), | ||
contents.replace(/ mixins /g, " extends "), | ||
"utf-8", | ||
); | ||
} | ||
|
||
fs.writeFileSync( | ||
path.join(rootDir, outFile), | ||
HEADER + contents, | ||
"utf-8", | ||
); | ||
console.log(`✅ wrote: ${outFile}`); | ||
} catch (e) { | ||
errorCount += 1; | ||
console.log(`❌ error processing: ${inFile}: ${e}`); | ||
} | ||
} | ||
|
||
// Fail the build step if there were any files we couldn't process | ||
process.exit(errorCount); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* Flowtype definitions for data | ||
* Generated by Flowgen from a Typescript Definition | ||
* Flowgen v1.21.0 | ||
* @flow | ||
*/ | ||
export type MetadataPrimitive = string | number | boolean | null | void; | ||
export type MetadataArray<T> = Array<T | MetadataArray<T>>; | ||
/** | ||
* A collection of data. | ||
*/ | ||
export type Metadata = { | ||
[name: string]: | ||
| Metadata | ||
| MetadataPrimitive | ||
| MetadataArray<MetadataPrimitive | Metadata>, | ||
}; | ||
/** | ||
* A secret that is a string. | ||
* | ||
* This opaque type makes it clearer when secrets are being used and enforces | ||
* the need for explicit casting if they must be used as a string. | ||
*/ | ||
export opaque type SecretString = string; | ||
/** | ||
* A collection of secrets keyed by their names. | ||
*/ | ||
export type Secrets = { | ||
+[key: string]: SecretString, | ||
}; | ||
/** | ||
* Make a read-only type mutable. | ||
*/ | ||
export type Mutable<T> = $ObjMapi<T, <P>(P) => $ElementType<T, P>>; |
111 changes: 111 additions & 0 deletions
111
packages/wonder-stuff-render-environment-jsdom/src/types.js.flow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/** | ||
* Flowtype definitions for types | ||
* Generated by Flowgen from a Typescript Definition | ||
* Flowgen v1.21.0 | ||
* @flow | ||
*/ | ||
|
||
import type { ResourceLoader } from "jsdom"; | ||
import type { | ||
RenderAPI, | ||
ICloseable, | ||
} from "@khanacademy/wonder-stuff-render-server"; | ||
|
||
/** | ||
* Gate API for control flow. | ||
*/ | ||
export type IGate = { | ||
/** | ||
* Open the gate. | ||
*/ | ||
open(): void, | ||
|
||
/** | ||
* Close the gate. | ||
*/ | ||
close: () => Promise<void> | void, | ||
|
||
/** | ||
* True, if the gate is open; otherwise, false. | ||
*/ | ||
isOpen: boolean, | ||
... | ||
} & ICloseable; | ||
|
||
/** | ||
* Standard timer API as implemented by Node's global or a browser window. | ||
*/ | ||
export interface ITimerAPI { | ||
setTimeout: $PropertyType<typeof window, "setTimeout">; | ||
setInterval: $PropertyType<typeof window, "setInterval">; | ||
requestAnimationFrame: $PropertyType<typeof window, "requestAnimationFrame">; | ||
} | ||
/** | ||
* A resource loader for use with JSDOM that can also have a close method for | ||
* tidying up resources deterministically. | ||
*/ | ||
export interface CloseableResourceLoader extends ICloseable, ResourceLoader { | ||
/** | ||
* Close the resource loader and tidy up resources. | ||
* | ||
* This is optional. | ||
*/ | ||
+close?: () => void; | ||
}; | ||
|
||
/** | ||
* Configuration for a JSDOM environment. | ||
*/ | ||
export interface IJSDOMConfiguration { | ||
/** | ||
* The name of the callback function that should be exposed by the | ||
* environment for renderable code to use when registering for rendering. | ||
*/ | ||
registrationCallbackName: string; | ||
|
||
/** | ||
* Get a JSDOM resource loader for the given render request. | ||
* @param {string} url The URL that is to be rendered. | ||
* @param {RenderAPI} renderAPI An API of utilities for assisting with the | ||
* render operation. | ||
* @returns {CloseableResourceLoader} A ResourceLoader instance for use | ||
* with JSDOM that can optionally have a close() method, which will be | ||
* invoked when the render completes. | ||
*/ | ||
getResourceLoader(url: string, renderAPI: RenderAPI): CloseableResourceLoader; | ||
|
||
/** | ||
* Get the list of file URLs to retrieve and execute for the given request. | ||
* @param {string} url The URL that is to be rendered. | ||
* @param {RenderAPI} renderAPI An API of utilities for assisting with the | ||
* render operation. | ||
* @param {(url: string) => ?Promise<Buffer>} fetchFn Function to fetch a URL. Using this ensures proper tidy-up of associated | ||
* sockets and agents. | ||
* @returns {Promise<Array<string>>} An ordered array of absolute URLs for | ||
* the JavaScript files that are to be executed. These are exectued in the | ||
* same order as the array. | ||
*/ | ||
getFileList( | ||
url: string, | ||
renderAPI: RenderAPI, | ||
fetchFn: (url: string) => Promise<Buffer> | null | void | ||
): Promise<Array<string>>; | ||
|
||
/** | ||
* Perform any additional environment setup. | ||
* | ||
* This method gets access to the actual environment in which code will | ||
* execute. Be careful what you do. | ||
* @param {string} url The URL that is to be rendered. | ||
* @param {RenderAPI} renderAPI An API of utilities for assisting with the | ||
* render operation. | ||
* @param {any} vmContext The actual environment that is being setup. | ||
* @returns {?Promise<void>} A promise that the additional setup is done. | ||
*/ | ||
afterEnvSetup( | ||
url: string, | ||
fileURLs: $ReadOnlyArray<string>, | ||
renderAPI: RenderAPI, | ||
vmContext?: any | ||
): Promise<ICloseable | null | void>; | ||
} |