From d841e1331f6694b5e83175440a2bec2064ae0aa3 Mon Sep 17 00:00:00 2001 From: Tim Griesser Date: Mon, 11 Oct 2021 12:13:41 -0400 Subject: [PATCH] refactor: Data context cleanup & IPC bindings for data push (#18357) --- .gitignore | 22 ++- npm/angular/package.json | 2 +- npm/design-system/package.json | 2 +- npm/webpack-preprocessor/package.json | 2 +- package.json | 6 +- packages/app/cypress.json | 6 +- .../app/cypress/e2e/integration/basic.spec.ts | 39 ++++ .../cypress/e2e/plugins/index.ts} | 9 +- .../app/cypress/e2e/support/e2eSupport.ts | 2 + .../app/cypress/integration/basic.spec.ts | 7 - packages/app/package.json | 19 +- packages/app/src/Basic.spec.tsx | 5 - packages/app/src/main.ts | 2 +- packages/app/src/pages/NewSpec.vue | 10 +- packages/app/src/router/router.ts | 7 +- packages/data-context/package.json | 5 +- packages/data-context/src/DataContext.ts | 42 +++- packages/data-context/src/DataContextShell.ts | 43 ++++ .../src/actions/DataEmitterActions.ts | 29 +++ .../src/actions/ProjectActions.ts | 25 ++- packages/data-context/src/actions/index.ts | 1 + packages/data-context/src/data/DataEmitter.ts | 5 - packages/data-context/src/data/index.ts | 1 - packages/data-context/src/index.ts | 7 +- packages/data-context/src/makeDataContext.ts | 14 -- packages/data-context/tsconfig.json | 1 - packages/driver/tsconfig.json | 1 + packages/electron/lib/electron.js | 3 +- packages/frontend-shared/cypress.json | 2 +- .../cypress/e2e/e2ePluginSetup.ts | 31 +++ .../cypress/e2e/support/e2eSupport.ts | 27 +++ .../support/mock-graphql/stubgql-Project.ts | 2 +- .../support/mock-graphql}/testStubSpecs.ts | 0 packages/frontend-shared/env.d.ts | 4 - .../frontend-shared/src/graphql/urqlClient.ts | 71 ++++++- .../src/graphql/urqlExchangePubsub.ts | 40 ++++ packages/frontend-shared/src/utils/env.ts | 6 - packages/frontend-shared/tsconfig.json | 2 +- packages/graphql/package.json | 3 +- packages/graphql/schemas/schema.graphql | 2 + .../schemaTypes/objectTypes/gql-Mutation.ts | 21 ++ packages/graphql/src/server.ts | 74 +------ packages/graphql/tsconfig.json | 2 - packages/launchpad/cypress.json | 1 - .../fixtures/browsers/long-browsers-list.ts | 1 - .../cypress/integration/basic.spec.ts | 10 +- packages/launchpad/cypress/plugins/index.ts | 23 +++ packages/launchpad/package.json | 1 + packages/launchpad/src/Main.vue | 6 +- packages/launchpad/src/main.ts | 2 +- .../src/setup/OpenBrowserList.spec.tsx | 2 +- packages/network/lib/client-certificates.ts | 2 +- packages/network/package.json | 2 +- packages/network/test/unit/agent_spec.ts | 2 +- .../proxy/lib/http/response-middleware.ts | 1 + packages/proxy/package.json | 1 + packages/resolve-dist/lib/index.ts | 20 +- packages/resolve-dist/package.json | 2 +- packages/rewriter/lib/threads/index.ts | 2 +- packages/rewriter/package.json | 1 + .../{lib/threads => script}/worker-shim.js | 3 +- packages/runner-ct/package.json | 2 +- packages/runner-shared/src/event-manager.ts | 12 +- packages/runner-shared/test/helper.js | 8 +- packages/runner-shared/tsconfig.json | 2 +- packages/runner/test/helper.js | 8 +- packages/server/lib/gui/auth.ts | 3 +- packages/server/lib/gui/events.ts | 87 +------- packages/server/lib/gui/links.ts | 1 + packages/server/lib/gui/makeGraphQLServer.ts | 64 ++++++ packages/server/lib/gui/windows.ts | 19 +- packages/server/lib/makeDataContext.ts | 71 +++++++ .../server/lib/modes/{index.js => index.ts} | 2 +- ...{interactive-e2e.js => interactive-e2e.ts} | 58 +++--- packages/server/lib/modes/internal-server.ts | 31 +++ packages/server/lib/open_project.ts | 13 +- packages/server/lib/plugins/index.js | 4 +- packages/server/lib/project-base.ts | 27 ++- packages/server/lib/routes-ct.ts | 45 ++++- packages/server/lib/routes.ts | 2 + packages/server/lib/server-base.ts | 9 +- packages/server/lib/server-e2e.ts | 6 +- packages/server/lib/specs-store.ts | 6 +- packages/server/lib/util/ts_node.js | 14 +- packages/server/lib/util/validation.js | 2 + packages/server/package.json | 8 +- .../test/integration/websockets_spec.js | 2 +- .../non-proxied/cypress/plugins/index.js | 2 +- packages/server/test/unit/gui/events_spec.js | 4 +- packages/server/test/unit/gui/windows_spec.ts | 2 +- packages/server/test/unit/socket_spec.js | 2 +- packages/server/tsconfig.json | 2 - packages/socket/README.md | 6 +- packages/socket/index.js | 19 +- packages/socket/index.ts | 1 - packages/socket/lib/browser.js | 11 -- packages/socket/lib/browser.ts | 2 + packages/socket/lib/socket.js | 83 -------- packages/socket/lib/socket.ts | 2 - packages/socket/package.json | 4 +- packages/socket/test/socket_spec.js | 5 +- packages/socket/tsconfig.json | 2 - packages/ts/package.json | 3 +- packages/ts/patches/ts-node+5.0.1.patch | 13 -- packages/ts/register.js | 21 +- packages/ts/tsconfig.dom.json | 9 + packages/ts/tsconfig.json | 4 +- packages/types/src/browser.ts | 2 - packages/types/src/index.ts | 2 + packages/types/src/platform.ts | 9 + packages/types/src/server.ts | 15 +- packages/types/tsconfig.json | 5 +- scripts/gulp/gulpConstants.ts | 14 -- scripts/gulp/gulpfile.ts | 132 ++++++------- scripts/gulp/tasks/gulpCypress.ts | 71 ++----- scripts/gulp/tasks/gulpMakePackage.ts | 6 +- scripts/gulp/tasks/gulpRegistry.ts | 14 ++ scripts/gulp/tasks/gulpVite.ts | 111 ++--------- scripts/gulp/tasks/gulpWebpack.ts | 70 +++++++ yarn.lock | 185 ++++++++++++------ 120 files changed, 1211 insertions(+), 814 deletions(-) create mode 100644 packages/app/cypress/e2e/integration/basic.spec.ts rename packages/{launchpad/cypress/plugins/index.js => app/cypress/e2e/plugins/index.ts} (68%) create mode 100644 packages/app/cypress/e2e/support/e2eSupport.ts delete mode 100644 packages/app/cypress/integration/basic.spec.ts delete mode 100644 packages/app/src/Basic.spec.tsx create mode 100644 packages/data-context/src/DataContextShell.ts create mode 100644 packages/data-context/src/actions/DataEmitterActions.ts delete mode 100644 packages/data-context/src/data/DataEmitter.ts delete mode 100644 packages/data-context/src/makeDataContext.ts create mode 100644 packages/frontend-shared/cypress/e2e/e2ePluginSetup.ts create mode 100644 packages/frontend-shared/cypress/e2e/support/e2eSupport.ts rename packages/frontend-shared/{src/graphql/specs => cypress/support/mock-graphql}/testStubSpecs.ts (100%) delete mode 100644 packages/frontend-shared/env.d.ts create mode 100644 packages/frontend-shared/src/graphql/urqlExchangePubsub.ts delete mode 100644 packages/frontend-shared/src/utils/env.ts delete mode 100644 packages/launchpad/cypress/fixtures/browsers/long-browsers-list.ts create mode 100644 packages/launchpad/cypress/plugins/index.ts rename packages/rewriter/{lib/threads => script}/worker-shim.js (58%) create mode 100644 packages/server/lib/gui/makeGraphQLServer.ts create mode 100644 packages/server/lib/makeDataContext.ts rename packages/server/lib/modes/{index.js => index.ts} (94%) rename packages/server/lib/modes/{interactive-e2e.js => interactive-e2e.ts} (72%) create mode 100644 packages/server/lib/modes/internal-server.ts delete mode 100644 packages/socket/index.ts delete mode 100644 packages/socket/lib/browser.js delete mode 100644 packages/socket/lib/socket.js delete mode 100644 packages/ts/patches/ts-node+5.0.1.patch create mode 100644 packages/ts/tsconfig.dom.json create mode 100644 packages/types/src/platform.ts create mode 100644 scripts/gulp/tasks/gulpWebpack.ts diff --git a/.gitignore b/.gitignore index 3087f9c587..15727e63ba 100644 --- a/.gitignore +++ b/.gitignore @@ -13,18 +13,35 @@ cypress.zip Cached Theme.pak Cached Theme Material Design.pak +# from data-context, compiled .js files +packages/data-context/src/**/*.js + # from desktop-gui packages/desktop-gui/cypress/videos packages/desktop-gui/src/jsconfig.json + # from driver packages/driver/cypress/videos packages/driver/cypress/screenshots +# from launcher, compiled .js files +packages/launcher/index.js +packages/launcher/lib/**/*.js + +# from network, compiled .js files +packages/network/lib/**/*.js + +# from net-stubbing, compiled .js files +packages/net-stubbing/lib/**/*.js + # from runner packages/runner/cypress/videos packages/runner/cypress/screenshots +# from proxy, compiled .js files +packages/proxy/lib/**/*.js + # npm packages npm/**/cypress/screenshots @@ -40,6 +57,9 @@ packages/server/support packages/server/test/support/fixtures/server/imgs packages/server/test/support/fixtures/server/libs +# from socket, dist built files +packages/socket/lib/*.js + # from npm/react /npm/react/bin/* /npm/react/cypress/videos @@ -347,4 +367,4 @@ globbed_node_modules # Autogenerated files, typically from graphql-code-generator *.gen.ts -*.gen.json \ No newline at end of file +*.gen.json diff --git a/npm/angular/package.json b/npm/angular/package.json index d7868fcad1..3f3d06aa6e 100644 --- a/npm/angular/package.json +++ b/npm/angular/package.json @@ -59,7 +59,7 @@ "semantic-release": "17.4.2", "to-string-loader": "1.1.6", "ts-loader": "8.1.0", - "ts-node": "9.1.1", + "ts-node": "^10.2.1", "tslib": "^2.2.0", "tslint": "5.20.1", "typescript": "4.2.4", diff --git a/npm/design-system/package.json b/npm/design-system/package.json index 9b28636e77..60a32bcc14 100644 --- a/npm/design-system/package.json +++ b/npm/design-system/package.json @@ -79,7 +79,7 @@ "sass-loader": "10.1.1", "style-loader": "^2.0.0", "svg-url-loader": "3.0.3", - "ts-node": "^9.1.1", + "ts-node": "^10.2.1", "tsc-alias": "^1.2.9", "tsconfig-paths-webpack-plugin": "^3.5.1", "typed-scss-modules": "^4.1.1", diff --git a/npm/webpack-preprocessor/package.json b/npm/webpack-preprocessor/package.json index a080748b96..e82b534fb2 100644 --- a/npm/webpack-preprocessor/package.json +++ b/npm/webpack-preprocessor/package.json @@ -57,7 +57,7 @@ "sinon": "^9.0.0", "sinon-chai": "^3.5.0", "snap-shot-it": "7.9.2", - "ts-node": "8.10.1", + "ts-node": "^10.2.1", "webpack": "^4.41.12" }, "peerDependencies": { diff --git a/package.json b/package.json index bbf1aa5cd1..add41b9232 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "cypress:run:debug": "node ./scripts/debug.js cypress:run", "cypress:verify": "cypress verify --dev", "dev": "gulp dev", + "dev:no-watch": "gulp dev:no-watch", + "dev:clean": "gulp dev:clean", "gulp:debug": "node --inspect-brk ./node_modules/.bin/gulp", "dev-debug": "node ./scripts/debug.js dev", "docker": "./scripts/run-docker-local.sh", @@ -116,6 +118,7 @@ "@types/react": "16.9.50", "@types/react-dom": "16.9.8", "@types/request-promise": "4.1.45", + "@types/send": "^0.17.1", "@types/sinon-chai": "3.2.3", "@types/through2": "^2.0.36", "@typescript-eslint/eslint-plugin": "4.18.0", @@ -129,6 +132,7 @@ "babel-eslint": "10.1.0", "bluebird": "3.5.3", "bluebird-retry": "0.11.0", + "c8": "^7.10.0", "chai": "4.2.0", "chai-as-promised": "7.1.1", "chalk": "2.4.2", @@ -217,7 +221,7 @@ "through": "2.3.8", "through2": "^4.0.2", "tree-kill": "1.2.2", - "ts-node": "8.3.0", + "ts-node": "^10.2.1", "typescript": "^4.2.3", "yarn-deduplicate": "3.1.0" }, diff --git a/packages/app/cypress.json b/packages/app/cypress.json index e8db560fab..116aee5068 100644 --- a/packages/app/cypress.json +++ b/packages/app/cypress.json @@ -1,6 +1,5 @@ { "projectId": "sehy69", - "baseUrl": "http://localhost:5556", "viewportWidth": 800, "viewportHeight": 850, "fixturesFolder": false, @@ -14,11 +13,16 @@ "reporterOptions": { "configFile": "../../mocha-reporter-config.json" }, + "integrationFolder": "cypress/e2e/integration", "componentFolder": "src", "supportFile": false, "component": { "testFiles": "**/*.spec.{js,ts,tsx,jsx}", "supportFile": "cypress/component/support/index.ts", "pluginsFile": "cypress/component/plugins/index.js" + }, + "e2e": { + "pluginsFile": "cypress/e2e/plugins/index.ts", + "supportFile": "cypress/e2e/support/e2eSupport.ts" } } diff --git a/packages/app/cypress/e2e/integration/basic.spec.ts b/packages/app/cypress/e2e/integration/basic.spec.ts new file mode 100644 index 0000000000..9da75f0621 --- /dev/null +++ b/packages/app/cypress/e2e/integration/basic.spec.ts @@ -0,0 +1,39 @@ +let GQL_PORT +let SERVER_PORT + +describe('App', () => { + beforeEach(() => { + cy.withCtx(async (ctx) => { + await ctx.dispose() + await ctx.actions.project.setActiveProject(ctx.launchArgs.projectRoot) + ctx.actions.wizard.setTestingType('e2e') + await ctx.actions.project.initializeActiveProject({ + skipPluginIntializeForTesting: true, + }) + + await ctx.actions.project.launchProject({ + skipBrowserOpenForTest: true, + }) + + return [ + ctx.gqlServerPort, + ctx.appServerPort, + ] + }).then(([gqlPort, serverPort]) => { + GQL_PORT = gqlPort + SERVER_PORT = serverPort + }) + }) + + it('resolves the home page', () => { + cy.visit(`dist/index.html?serverPort=${SERVER_PORT}&gqlPort=${GQL_PORT}`) + cy.get('[href="#/runner"]').click() + cy.get('[href="#/settings"]').click() + }) + + it('resolves the home page, with a different server port?', () => { + cy.visit(`dist/index.html?serverPort=${SERVER_PORT}&gqlPort=${GQL_PORT}`) + cy.get('[href="#/runner"]').click() + cy.get('[href="#/settings"]').click() + }) +}) diff --git a/packages/launchpad/cypress/plugins/index.js b/packages/app/cypress/e2e/plugins/index.ts similarity index 68% rename from packages/launchpad/cypress/plugins/index.js rename to packages/app/cypress/e2e/plugins/index.ts index 59b2bab6e4..81d30abbd3 100644 --- a/packages/launchpad/cypress/plugins/index.js +++ b/packages/app/cypress/e2e/plugins/index.ts @@ -1,4 +1,7 @@ /// +const { monorepoPaths } = require('../../../../../scripts/gulp/monorepoPaths') +import { e2ePluginSetup } from '@packages/frontend-shared/cypress/e2e/e2ePluginSetup' + // *********************************************************** // This example plugins/index.js can be used to load plugins // @@ -15,8 +18,6 @@ /** * @type {Cypress.PluginConfig} */ -// eslint-disable-next-line no-unused-vars -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config +module.exports = async (on, config) => { + return await e2ePluginSetup(monorepoPaths.pkgApp, on, config) } diff --git a/packages/app/cypress/e2e/support/e2eSupport.ts b/packages/app/cypress/e2e/support/e2eSupport.ts new file mode 100644 index 0000000000..4b448145df --- /dev/null +++ b/packages/app/cypress/e2e/support/e2eSupport.ts @@ -0,0 +1,2 @@ +/// +require('../../../../frontend-shared/cypress/e2e/support/e2eSupport') diff --git a/packages/app/cypress/integration/basic.spec.ts b/packages/app/cypress/integration/basic.spec.ts deleted file mode 100644 index 498ba0f4d4..0000000000 --- a/packages/app/cypress/integration/basic.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -describe('App', () => { - it('resolves the home page', () => { - cy.visit('http://localhost:5556') - cy.get('[data-e2e-href="/runner"]').click() - cy.get('[data-e2e-href="/settings"]').click() - }) -}) diff --git a/packages/app/package.json b/packages/app/package.json index 311dea2b8a..58fa78f261 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -14,10 +14,7 @@ "debug": "gulp debug --project ${PWD}", "dev": "gulp dev --project ${PWD}", "start": "echo \"run 'yarn dev' from the root\" && exit 1", - "watch": "echo \"run 'yarn dev' from the root\" && exit 1", - "vite:dev": "vite", - "vite:build": "vite build", - "vite:preview": "yarn vite:build && vite preview" + "watch": "echo \"run 'yarn dev' from the root\" && exit 1" }, "dependencies": {}, "devDependencies": { @@ -76,13 +73,25 @@ "vite": { "optimizeDeps": { "include": [ + "@iconify/iconify", + "@testing-library/cypress/add-commands", + "@urql/exchange-execute", "@urql/vue", "@vueuse/core", + "cypress-file-upload", + "dedent", + "fake-uuid", + "graphql", + "graphql-relay", + "graphql/jsutils/Path", "lodash", "mobx", "nanoid", + "path", + "socket.io-client", "vue", - "vue-toast-notification" + "vue-toast-notification", + "wonka" ] } } diff --git a/packages/app/src/Basic.spec.tsx b/packages/app/src/Basic.spec.tsx deleted file mode 100644 index ff119dfe1b..0000000000 --- a/packages/app/src/Basic.spec.tsx +++ /dev/null @@ -1,5 +0,0 @@ -describe('hello', () => { - it('works', () => { - expect(1).to.eq(1) - }) -}) diff --git a/packages/app/src/main.ts b/packages/app/src/main.ts index 662a8ff113..a044c19410 100644 --- a/packages/app/src/main.ts +++ b/packages/app/src/main.ts @@ -9,7 +9,7 @@ import { createRouter } from './router/router' const app = createApp(App) -app.use(urql, makeUrqlClient()) +app.use(urql, makeUrqlClient('app')) app.use(createRouter()) app.use(createI18n()) diff --git a/packages/app/src/pages/NewSpec.vue b/packages/app/src/pages/NewSpec.vue index 77fbdc881d..a9c1a77e8a 100644 --- a/packages/app/src/pages/NewSpec.vue +++ b/packages/app/src/pages/NewSpec.vue @@ -25,10 +25,10 @@ diff --git a/packages/launchpad/src/main.ts b/packages/launchpad/src/main.ts index 2666cf77ad..7525469014 100644 --- a/packages/launchpad/src/main.ts +++ b/packages/launchpad/src/main.ts @@ -9,7 +9,7 @@ import { createI18n } from '@cy/i18n' const app = createApp(App) app.use(VueToast) -app.use(urql, makeUrqlClient()) +app.use(urql, makeUrqlClient('launchpad')) app.use(createI18n()) window.$app = app.mount('#app') diff --git a/packages/launchpad/src/setup/OpenBrowserList.spec.tsx b/packages/launchpad/src/setup/OpenBrowserList.spec.tsx index 118542c915..2c9cbc3c48 100644 --- a/packages/launchpad/src/setup/OpenBrowserList.spec.tsx +++ b/packages/launchpad/src/setup/OpenBrowserList.spec.tsx @@ -1,6 +1,6 @@ import { OpenBrowserListFragmentDoc } from '../generated/graphql-test' import OpenBrowserList from './OpenBrowserList.vue' -import { longBrowsersList } from '../../cypress/fixtures/browsers/long-browsers-list' +import { longBrowsersList } from '@packages/frontend-shared/cypress/support/mock-graphql/stubgql-App' const launchButtonSelector = 'button[data-testid=launch-button]' diff --git a/packages/network/lib/client-certificates.ts b/packages/network/lib/client-certificates.ts index b65ebefd09..b2e7539a19 100644 --- a/packages/network/lib/client-certificates.ts +++ b/packages/network/lib/client-certificates.ts @@ -1,4 +1,4 @@ -import type { Url } from 'url' +import { URL, Url } from 'url' import debugModule from 'debug' import minimatch from 'minimatch' import Forge from 'node-forge' diff --git a/packages/network/package.json b/packages/network/package.json index b66a409b45..12e4bab115 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "build-prod": "tsc --project .", - "clean": "rimraf lib/*.js || echo 'cleaned'", + "clean": "rimraf 'lib/**/*.js'", "clean-deps": "rimraf node_modules", "test": "yarn test-unit", "test-debug": "yarn test-unit --inspect-brk=5566", diff --git a/packages/network/test/unit/agent_spec.ts b/packages/network/test/unit/agent_spec.ts index eb3264434f..4a692f1eab 100644 --- a/packages/network/test/unit/agent_spec.ts +++ b/packages/network/test/unit/agent_spec.ts @@ -9,7 +9,7 @@ import tls from 'tls' import url from 'url' import DebuggingProxy from '@cypress/debugging-proxy' import request from '@cypress/request-promise' -import * as socketIo from '@packages/socket' +import * as socketIo from '@packages/socket/lib/browser' import { buildConnectReqHead, createProxySock, diff --git a/packages/proxy/lib/http/response-middleware.ts b/packages/proxy/lib/http/response-middleware.ts index 6cff648159..f2bd4cfb79 100644 --- a/packages/proxy/lib/http/response-middleware.ts +++ b/packages/proxy/lib/http/response-middleware.ts @@ -11,6 +11,7 @@ import { InterceptResponse } from '@packages/net-stubbing' import { PassThrough, Readable } from 'stream' import * as rewriter from './util/rewriter' import zlib from 'zlib' +import { URL } from 'url' export type ResponseMiddleware = HttpMiddleware<{ /** diff --git a/packages/proxy/package.json b/packages/proxy/package.json index dc58a185fa..9ea4766505 100644 --- a/packages/proxy/package.json +++ b/packages/proxy/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "build-prod": "tsc --project .", + "clean": "rimraf 'lib/**/*.js'", "clean-deps": "rimraf node_modules", "run-mocha": "mocha -r @packages/ts/register -r test/pretest.ts --reporter mocha-multi-reporters --reporter-options configFile=../../mocha-reporter-config.json", "test": "yarn run-mocha \"test/integration/*.spec.ts\" \"test/unit/**/*.spec.ts\"", diff --git a/packages/resolve-dist/lib/index.ts b/packages/resolve-dist/lib/index.ts index 0ce0d0aec1..371db5f666 100644 --- a/packages/resolve-dist/lib/index.ts +++ b/packages/resolve-dist/lib/index.ts @@ -7,13 +7,7 @@ export type RunnerPkg = 'app' | 'runner' | 'runner-ct' type FoldersWithDist = 'static' | 'driver' | RunnerPkg export const getPathToDist = (folder: FoldersWithDist, ...args: string[]) => { - let distDir = 'dist' - - if (process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF) { - distDir = 'dist-e2e' - } - - return path.join(...[__dirname, '..', '..', folder, distDir, ...args]) + return path.join(...[__dirname, '..', '..', folder, 'dist', ...args]) } export const getRunnerInjectionContents = () => { @@ -26,18 +20,12 @@ export const getPathToIndex = (pkg: RunnerPkg) => { return getPathToDist(pkg, 'index.html') } -export const getPathToDesktopIndex = (pkg: 'desktop-gui' | 'launchpad') => { - let distDir = 'dist' - +export const getPathToDesktopIndex = (pkg: 'desktop-gui' | 'launchpad', graphqlPort?: number) => { // For now, if we see that there's a CYPRESS_INTERNAL_VITE_LAUNCHPAD_PORT // we assume we're running Cypress targeting that (dev server) if (pkg === 'launchpad' && process.env.CYPRESS_INTERNAL_VITE_LAUNCHPAD_PORT) { - return `http://localhost:${process.env.CYPRESS_INTERNAL_VITE_LAUNCHPAD_PORT}` + return `http://localhost:${process.env.CYPRESS_INTERNAL_VITE_LAUNCHPAD_PORT}?gqlPort=${graphqlPort}` } - if (process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF) { - distDir = 'dist-e2e' - } - - return `file://${path.join(__dirname, '..', '..', pkg, distDir, 'index.html')}` + return `file://${path.join(__dirname, '..', '..', pkg, 'dist', 'index.html')}?gqlPort=${graphqlPort}` } diff --git a/packages/resolve-dist/package.json b/packages/resolve-dist/package.json index 413f6d83f0..e4ddb37d33 100644 --- a/packages/resolve-dist/package.json +++ b/packages/resolve-dist/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "build-prod": "tsc --project .", - "clean": "rimraf lib/*.js || echo 'cleaned'", + "clean": "rimraf 'lib/**/*.js'", "clean-deps": "rimraf node_modules", "test": "yarn test-unit", "test-debug": "yarn test-unit --inspect-brk=5566", diff --git a/packages/rewriter/lib/threads/index.ts b/packages/rewriter/lib/threads/index.ts index 7bada92d5f..04da581704 100644 --- a/packages/rewriter/lib/threads/index.ts +++ b/packages/rewriter/lib/threads/index.ts @@ -21,7 +21,7 @@ const _debugOpts = !debug.enabled ? _.noop : (opts: RewriteOpts) => { // because it does not require importing @packages/ts like development does. // this has a huge performance impact, bringing the `responsiveMs` for threads // from ~1s to about ~300ms on my system -const WORKER_FILENAME = process.env.CYPRESS_INTERNAL_ENV === 'production' ? 'worker.js' : 'worker-shim.js' +const WORKER_FILENAME = process.env.CYPRESS_INTERNAL_ENV === 'production' ? 'worker.js' : '../../script/worker-shim.js' const WORKER_PATH = path.join(__dirname, WORKER_FILENAME) diff --git a/packages/rewriter/package.json b/packages/rewriter/package.json index dba83191f2..ab86938a03 100644 --- a/packages/rewriter/package.json +++ b/packages/rewriter/package.json @@ -6,6 +6,7 @@ "scripts": { "build-prod": "tsc --project .", "build-test": "yarn build-prod --noEmit", + "clean": "rimraf 'lib/**/*.js'", "clean-deps": "rimraf node_modules", "test": "mocha --reporter mocha-multi-reporters --reporter-options configFile=../../mocha-reporter-config.json" }, diff --git a/packages/rewriter/lib/threads/worker-shim.js b/packages/rewriter/script/worker-shim.js similarity index 58% rename from packages/rewriter/lib/threads/worker-shim.js rename to packages/rewriter/script/worker-shim.js index 0407ad7524..4ee39b3b16 100644 --- a/packages/rewriter/lib/threads/worker-shim.js +++ b/packages/rewriter/script/worker-shim.js @@ -1,6 +1,7 @@ +// Moved outside of /lib so we can rm -rf "lib/**/*.js" without deleting this if (process.env.CYPRESS_INTERNAL_ENV === 'production') { throw new Error(`${__filename} should only run outside of prod`) } require('@packages/ts/register') -require('./worker.ts') +require('../lib/threads/worker.ts') diff --git a/packages/runner-ct/package.json b/packages/runner-ct/package.json index a0f2e33a5f..aeaedb7bb2 100644 --- a/packages/runner-ct/package.json +++ b/packages/runner-ct/package.json @@ -57,7 +57,7 @@ "sockjs-client": "^1.5.0", "strip-ansi": "6.0.0", "ts-loader": "^8.0.5", - "ts-node": "8.3.0", + "ts-node": "^10.2.1", "watch": "^1.0.2", "webpack": "4.44.2" }, diff --git a/packages/runner-shared/src/event-manager.ts b/packages/runner-shared/src/event-manager.ts index 0881219605..59ba989c64 100644 --- a/packages/runner-shared/src/event-manager.ts +++ b/packages/runner-shared/src/event-manager.ts @@ -3,7 +3,7 @@ import { EventEmitter } from 'events' import Promise from 'bluebird' import { action } from 'mobx' -import { client } from '@packages/socket' +import { client } from '@packages/socket/lib/browser' import type { BaseStore } from './store' import { studioRecorder } from './studio' @@ -14,11 +14,15 @@ import { selectorPlaygroundModel } from './selector-playground' import $Cypress from '@packages/driver' import type { automationElementId } from './automation-element' -const $ = $Cypress.$ -const ws = client.connect({ +const PORT_MATCH = /serverPort=(\d+)/.exec(window.location.search) + +const socketConfig = { path: '/__socket.io', transports: ['websocket'], -}) +} + +const $ = $Cypress.$ +const ws = PORT_MATCH ? client(`http://localhost:${PORT_MATCH[1]}`, socketConfig) : client(socketConfig) ws.on('connect', () => { ws.emit('runner:connected') diff --git a/packages/runner-shared/test/helper.js b/packages/runner-shared/test/helper.js index 60faa3a3e1..bcd8fb1863 100644 --- a/packages/runner-shared/test/helper.js +++ b/packages/runner-shared/test/helper.js @@ -19,9 +19,11 @@ register({ }, }) -const io = returnMockRequire('@packages/socket/lib/browser', { client: {} }) - -io.client.connect = sinon.stub().returns({ emit: () => {}, on: () => {} }) +returnMockRequire('@packages/socket/lib/browser', { + client () { + return { emit: () => {}, on: () => {} } + }, +}) const _useFakeTimers = sinon.useFakeTimers let timers = [] diff --git a/packages/runner-shared/tsconfig.json b/packages/runner-shared/tsconfig.json index 0c3d8b6a65..dedbeae405 100644 --- a/packages/runner-shared/tsconfig.json +++ b/packages/runner-shared/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../ts/tsconfig.json", + "extends": "../ts/tsconfig.dom.json", "compilerOptions": { "jsx": "react", "experimentalDecorators": true diff --git a/packages/runner/test/helper.js b/packages/runner/test/helper.js index 60faa3a3e1..bcd8fb1863 100644 --- a/packages/runner/test/helper.js +++ b/packages/runner/test/helper.js @@ -19,9 +19,11 @@ register({ }, }) -const io = returnMockRequire('@packages/socket/lib/browser', { client: {} }) - -io.client.connect = sinon.stub().returns({ emit: () => {}, on: () => {} }) +returnMockRequire('@packages/socket/lib/browser', { + client () { + return { emit: () => {}, on: () => {} } + }, +}) const _useFakeTimers = sinon.useFakeTimers let timers = [] diff --git a/packages/server/lib/gui/auth.ts b/packages/server/lib/gui/auth.ts index f639343b8b..2aa76eb2a9 100644 --- a/packages/server/lib/gui/auth.ts +++ b/packages/server/lib/gui/auth.ts @@ -11,7 +11,6 @@ const errors = require('../errors') const machineId = require('../util/machine_id') const random = require('../util/random') const user = require('../user') -const windows = require('./windows') let app let authCallback @@ -101,7 +100,7 @@ const start = (onMessage, utmCode) => { }) .finally(() => { _stopServer() - windows.focusMainWindow() + require('./windows').focusMainWindow() }) } diff --git a/packages/server/lib/gui/events.ts b/packages/server/lib/gui/events.ts index a7e71cd171..341f4fb42d 100644 --- a/packages/server/lib/gui/events.ts +++ b/packages/server/lib/gui/events.ts @@ -6,6 +6,7 @@ const { clipboard } = require('electron') const debug = require('debug')('cypress:server:events') const pluralize = require('pluralize') const stripAnsi = require('strip-ansi') + const dialog = require('./dialog') const pkg = require('./package') const logs = require('./logs') @@ -26,21 +27,11 @@ const fileOpener = require('../util/file-opener') const api = require('../api') const savedState = require('../saved_state') -import * as config from '../config' import auth from './auth' import user from '../user' import { openProject } from '../open_project' -import specsUtil from '../util/specs' - -import { setDataContext, startGraphQLServer } from '@packages/graphql/src/server' -import { getProjectRoots, insertProject, removeLatestProjects, removeProject } from '@packages/server/lib/cache' -import { checkAuthQuery } from '@packages/graphql/src/stitching/remoteGraphQLCalls' -import type { FindSpecs, FoundBrowser, LaunchArgs, LaunchOpts, OpenProjectLaunchOptions } from '@packages/types' +import type { LaunchArgs } from '@packages/types' import type { EventEmitter } from 'events' -import { makeDataContext } from '@packages/data-context' -import browserUtils from '../browsers/utils' - -const { getBrowsers } = browserUtils const nullifyUnserializableValues = (obj) => { // nullify values that cannot be cloned @@ -167,7 +158,7 @@ const handleEvent = function (options, bus, event, id, type, arg) { }) return openProject.launch(arg.browser, fullSpec, { - // TODO: Tim see why this + // TODO: Tim see why this "projectRoot" is passed along projectRoot: options.projectRoot, onBrowserOpen () { return send({ browserOpened: true }) @@ -495,7 +486,11 @@ const handleEvent = function (options, bus, event, id, type, arg) { } } -module.exports = { +interface EventsStartArgs extends LaunchArgs { + onFocusTests: () => void +} + +export = { nullifyUnserializableValues, handleEvent, @@ -504,72 +499,8 @@ module.exports = { return ipc.removeAllListeners() }, - async start (options: LaunchArgs, bus: EventEmitter, { startGraphQL } = { startGraphQL: true }) { + async start (options: EventsStartArgs, bus: EventEmitter) { // curry left options ipc.on('request', _.partial(this.handleEvent, options, bus)) - - // support not starting server for testing purposes. - if (!startGraphQL) { - return - } - - // TODO: Figure out how we want to cleanup & juggle the config, so it's not jammed - // into the projects - startGraphQLServer() - - const ctx = await makeDataContext({ - launchArgs: options, - launchOptions: {}, - appApi: { - getBrowsers () { - return getBrowsers() - }, - }, - authApi: { - logIn () { - return auth.start(() => {}, 'launchpad') - }, - logOut () { - return user.logOut() - }, - checkAuth (context) { - return checkAuthQuery(context) - }, - }, - projectApi: { - getConfig (projectRoot: string) { - return config.get(projectRoot) - }, - launchProject (browser: FoundBrowser, spec: Cypress.Spec, options?: LaunchOpts) { - return openProject.launch({ ...browser }, spec, options) - }, - initializeProject (args: LaunchArgs, options: OpenProjectLaunchOptions, browsers: FoundBrowser[]) { - return openProject.create(args.projectRoot, args, options, browsers) - }, - insertProjectToCache (projectRoot: string) { - insertProject(projectRoot) - }, - removeProjectFromCache (projectRoot: string) { - removeProject(projectRoot) - }, - getProjectRootsFromCache () { - return getProjectRoots() - }, - findSpecs (payload: FindSpecs) { - return specsUtil.findSpecs(payload) - }, - clearLatestProjectsCache () { - return removeLatestProjects() - }, - }, - }) - - // Fetch the browsers when the app starts, so we have some by - // the time we're continuing. - ctx.actions.app.refreshBrowsers() - // load projects from cache on start - ctx.actions.project.loadProjects() - - setDataContext(ctx) }, } diff --git a/packages/server/lib/gui/links.ts b/packages/server/lib/gui/links.ts index eeb08e8234..ccef46951c 100644 --- a/packages/server/lib/gui/links.ts +++ b/packages/server/lib/gui/links.ts @@ -1,5 +1,6 @@ import _ from 'lodash' import { shell } from 'electron' +import { URL, URLSearchParams } from 'url' // NOTE: in order for query params to be passed through on links // forwardQueryParams: true must be set for that slug in the on package diff --git a/packages/server/lib/gui/makeGraphQLServer.ts b/packages/server/lib/gui/makeGraphQLServer.ts new file mode 100644 index 0000000000..8088c02d94 --- /dev/null +++ b/packages/server/lib/gui/makeGraphQLServer.ts @@ -0,0 +1,64 @@ +import express from 'express' +import { addGraphQLHTTP } from '@packages/graphql/src/server' +import type { AddressInfo } from 'net' +import type { DataContext } from '@packages/data-context' +import pDefer from 'p-defer' +import cors from 'cors' +import type { Server } from 'http' +import { SocketIOServer } from '@packages/socket' + +let graphqlServer: Server | undefined + +export async function closeGraphQLServer () { + if (!graphqlServer) { + return + } + + const dfd = pDefer() + + graphqlServer.close((err) => { + if (err) { + dfd.reject() + } + + dfd.resolve() + }) + + graphqlServer = undefined + + dfd.promise +} + +export async function makeGraphQLServer (ctx: DataContext) { + const dfd = pDefer() + const app = express() + + app.use(cors()) + + // TODO: Figure out how we want to cleanup & juggle the config, so + // it's not jammed into the projects + addGraphQLHTTP(app, ctx) + + const srv = graphqlServer = app.listen(() => { + const port = (srv.address() as AddressInfo).port + const endpoint = `http://localhost:${port}/graphql` + + if (process.env.NODE_ENV === 'development') { + /* eslint-disable-next-line no-console */ + console.log(`GraphQL server is running at ${endpoint}`) + } + + ctx.debug(`GraphQL Server at ${endpoint}`) + + dfd.resolve(port) + }) + + const socketServer = new SocketIOServer(srv, { + path: '/__gqlSocket', + transports: ['websocket'], + }) + + ctx.emitter.setLaunchpadSocketServer(socketServer) + + return dfd.promise +} diff --git a/packages/server/lib/gui/windows.ts b/packages/server/lib/gui/windows.ts index cb9aefe33e..b879e0f474 100644 --- a/packages/server/lib/gui/windows.ts +++ b/packages/server/lib/gui/windows.ts @@ -13,19 +13,20 @@ export type WindowOptions = Electron.BrowserWindowConstructorOptions & { type?: 'INDEX' url?: string devTools?: boolean + graphqlPort?: number } let windows = {} let recentlyCreatedWindow = false -const getUrl = function (type) { +const getUrl = function (type, port?: number) { switch (type) { case 'INDEX': if (process.env.LAUNCHPAD) { - return getPathToDesktopIndex('launchpad') + return getPathToDesktopIndex('launchpad', port) } - return getPathToDesktopIndex('desktop-gui') + return getPathToDesktopIndex('desktop-gui', port) default: throw new Error(`No acceptable window type found for: '${type}'`) @@ -158,14 +159,6 @@ export function create (projectRoot, _options: WindowOptions = {}, newBrowserWin options.webPreferences.partition = options.partition } - // When we're E2E testing the launchpad or app, we want to stand up a real Cy server. - // It's best to do this without rendering the launchpad, so we won't visually render the electron window. - // TODO(jess): Is it better to stub the electron window? The server is pretty coupled to it. - if (process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF) { - options.frame = false - options.show = false - } - const win = newBrowserWindow(options) win.on('blur', function (...args) { @@ -223,7 +216,7 @@ export function create (projectRoot, _options: WindowOptions = {}, newBrowserWin } // open desktop-gui BrowserWindow -export function open (projectRoot, options: WindowOptions = {}, newBrowserWindow = _newBrowserWindow) { +export function open (projectRoot, graphqlPort: number | undefined, options: WindowOptions = {}, newBrowserWindow = _newBrowserWindow): Bluebird { // if we already have a window open based // on that type then just show + focus it! let win @@ -249,7 +242,7 @@ export function open (projectRoot, options: WindowOptions = {}, newBrowserWindow }) if (!options.url) { - options.url = getUrl(options.type) + options.url = getUrl(options.type, graphqlPort) } win = create(projectRoot, options, newBrowserWindow) diff --git a/packages/server/lib/makeDataContext.ts b/packages/server/lib/makeDataContext.ts new file mode 100644 index 0000000000..0a921d3d63 --- /dev/null +++ b/packages/server/lib/makeDataContext.ts @@ -0,0 +1,71 @@ +import { DataContext } from '@packages/data-context' +import specsUtil from './util/specs' +import type { FindSpecs, FoundBrowser, LaunchArgs, LaunchOpts, OpenProjectLaunchOptions, PlatformName } from '@packages/types' +import { checkAuthQuery } from '@packages/graphql/src/stitching/remoteGraphQLCalls' +import browserUtils from './browsers/utils' +import auth from './gui/auth' +import user from './user' +import * as config from './config' +import type { EventEmitter } from 'events' +import { openProject } from './open_project' +import cache from './cache' + +const { getBrowsers } = browserUtils + +interface MakeDataContextOptions { + os: PlatformName + rootBus: EventEmitter + launchArgs: LaunchArgs +} + +export function makeDataContext (options: MakeDataContextOptions) { + return new DataContext({ + ...options, + launchOptions: {}, + appApi: { + getBrowsers () { + return getBrowsers() + }, + }, + authApi: { + logIn () { + return auth.start(() => {}, 'launchpad') + }, + logOut () { + return user.logOut() + }, + checkAuth (context) { + return checkAuthQuery(context) + }, + }, + projectApi: { + getConfig (projectRoot: string) { + return config.get(projectRoot) + }, + launchProject (browser: FoundBrowser, spec: Cypress.Spec, options?: LaunchOpts) { + return openProject.launch({ ...browser }, spec, options) + }, + initializeProject (args: LaunchArgs, options: OpenProjectLaunchOptions, browsers: FoundBrowser[]) { + return openProject.create(args.projectRoot, args, options, browsers) + }, + insertProjectToCache (projectRoot: string) { + cache.insertProject(projectRoot) + }, + getProjectRootsFromCache () { + return cache.getProjectRoots() + }, + findSpecs (payload: FindSpecs) { + return specsUtil.findSpecs(payload) + }, + clearLatestProjectsCache () { + return cache.removeLatestProjects() + }, + removeProjectFromCache (path: string) { + return cache.removeProject(path) + }, + closeActiveProject () { + return openProject.closeOpenProjectAndBrowsers() + }, + }, + }) +} diff --git a/packages/server/lib/modes/index.js b/packages/server/lib/modes/index.ts similarity index 94% rename from packages/server/lib/modes/index.js rename to packages/server/lib/modes/index.ts index 657dc1ceff..b9b09c9cf6 100644 --- a/packages/server/lib/modes/index.js +++ b/packages/server/lib/modes/index.ts @@ -1,4 +1,4 @@ -module.exports = (mode, options) => { +export = (mode, options) => { if (mode === 'record') { return require('./record').run(options) } diff --git a/packages/server/lib/modes/interactive-e2e.js b/packages/server/lib/modes/interactive-e2e.ts similarity index 72% rename from packages/server/lib/modes/interactive-e2e.js rename to packages/server/lib/modes/interactive-e2e.ts index f1f031adae..6ca6dcc327 100644 --- a/packages/server/lib/modes/interactive-e2e.js +++ b/packages/server/lib/modes/interactive-e2e.ts @@ -1,19 +1,22 @@ -const _ = require('lodash') -const os = require('os') -const EE = require('events') -const { app } = require('electron') -const image = require('electron').nativeImage -const cyIcons = require('@cypress/icons') -const savedState = require('../saved_state') -const menu = require('../gui/menu') -const Events = require('../gui/events') -const Windows = require('../gui/windows') +import _ from 'lodash' +import os from 'os' +import { app, nativeImage as image } from 'electron' +// eslint-disable-next-line no-duplicate-imports +import type { WebContents } from 'electron' +import cyIcons from '@cypress/icons' +import savedState from '../saved_state' +import menu from '../gui/menu' +import Events from '../gui/events' +import * as Windows from '../gui/windows' +import { runInternalServer } from './internal-server' +import type { LaunchArgs, PlatformName } from '@packages/types' +import EventEmitter from 'events' const isDev = () => { return process.env['CYPRESS_INTERNAL_ENV'] === 'development' } -module.exports = { +export = { isMac () { return os.platform() === 'darwin' }, @@ -80,7 +83,7 @@ module.exports = { y: 'appY', devTools: 'isAppDevToolsOpen', }, - onBlur () { + onBlur (this: {webContents: WebContents}) { if (this.webContents.isDevToolsOpened()) { return } @@ -121,10 +124,15 @@ module.exports = { return args[os.platform()] }, - ready (options = {}) { - const bus = new EE - + /** + * @param {import('@packages/types').LaunchArgs} options + * @returns + */ + ready (options: {projectRoot?: string} = {}) { const { projectRoot } = options + const { serverPortPromise, bus } = process.env.LAUNCHPAD + ? runInternalServer(options) + : { bus: new EventEmitter, serverPortPromise: Promise.resolve(undefined) } // TODO: potentially just pass an event emitter // instance here instead of callback functions @@ -135,19 +143,21 @@ module.exports = { }, }) - return savedState.create(projectRoot, false) - .then((state) => { - return state.get() - }) - .then((state) => { - return Windows.open(projectRoot, this.getWindowArgs(state, options)) + return Promise.all([ + serverPortPromise, + savedState.create(projectRoot, false).then((state) => state.get()), + ]) + .then(([port, state]) => { + return Windows.open(projectRoot, port, this.getWindowArgs(state)) .then((win) => { - Events.start(_.extend({}, options, { + Events.start({ + ...(options as LaunchArgs), onFocusTests () { + // @ts-ignore return app.focus({ steal: true }) || win.focus() }, - os: os.platform(), - }), bus) + os: os.platform() as PlatformName, + }, bus) return win }) diff --git a/packages/server/lib/modes/internal-server.ts b/packages/server/lib/modes/internal-server.ts new file mode 100644 index 0000000000..4abefb0565 --- /dev/null +++ b/packages/server/lib/modes/internal-server.ts @@ -0,0 +1,31 @@ +import os from 'os' +import { EventEmitter } from 'events' + +import { makeDataContext } from '../makeDataContext' +import { makeGraphQLServer } from '../gui/makeGraphQLServer' +import { assertValidPlatform } from '@packages/types/src/platform' + +export function runInternalServer (options) { + const bus = new EventEmitter() + const platform = os.platform() + + assertValidPlatform(platform) + + const ctx = makeDataContext({ + os: platform, + rootBus: bus, + launchArgs: options, + }) + + // Initializing the data context, loading browsers, etc. + ctx.initializeData() + ctx.emitter.init() + + const serverPortPromise = makeGraphQLServer(ctx) + + serverPortPromise.then((port) => { + ctx.setGqlServerPort(port) + }) + + return { ctx, bus, serverPortPromise } +} diff --git a/packages/server/lib/open_project.ts b/packages/server/lib/open_project.ts index cfec1684ab..6c6b4a3157 100644 --- a/packages/server/lib/open_project.ts +++ b/packages/server/lib/open_project.ts @@ -13,10 +13,10 @@ import * as session from './session' import { getSpecUrl } from './project_utils' import errors from './errors' import type { LaunchOpts, LaunchArgs, OpenProjectLaunchOptions, FoundBrowser } from '@packages/types' -import { closeGraphQLServer } from '@packages/graphql/src/server' import { fs } from './util/fs' import path from 'path' import os from 'os' +import { closeGraphQLServer } from './gui/makeGraphQLServer' const debug = Debug('cypress:server:open_project') @@ -229,6 +229,10 @@ export class OpenProject { session.clearSessions() }) .then(() => { + if (options.skipBrowserOpenForTest) { + return + } + return browsers.open(browser, options, automation) }) } @@ -380,8 +384,6 @@ export class OpenProject { this.componentSpecsWatcher.close() this.componentSpecsWatcher = null } - - return closeGraphQLServer() } closeBrowser () { @@ -405,7 +407,10 @@ export class OpenProject { this.stopSpecsWatcher() - return this.closeOpenProjectAndBrowsers() + return Promise.all([ + closeGraphQLServer(), + this.closeOpenProjectAndBrowsers(), + ]).then(() => null) } async create (path: string, args: LaunchArgs, options: OpenProjectLaunchOptions, browsers: FoundBrowser[] = []) { diff --git a/packages/server/lib/plugins/index.js b/packages/server/lib/plugins/index.js index 24d12a5f9c..d950ffa5ad 100644 --- a/packages/server/lib/plugins/index.js +++ b/packages/server/lib/plugins/index.js @@ -98,9 +98,11 @@ const init = (config, options) => { debug('forking to run %s', childIndexFilename) if (inspector.url()) { + const inspectType = process.argv.some((a) => a.startsWith('--inspect-brk')) ? '--inspect-brk' : '--inspect' + childOptions.execArgv = _.chain(process.execArgv.slice(0)) .remove('--inspect-brk') - .push(`--inspect=${process.debugPort + 1}`) + .push(`${inspectType}=${process.debugPort + 1}`) .value() } diff --git a/packages/server/lib/project-base.ts b/packages/server/lib/project-base.ts index fc3a9c13aa..aa132f6e8e 100644 --- a/packages/server/lib/project-base.ts +++ b/packages/server/lib/project-base.ts @@ -33,6 +33,7 @@ import preprocessor from './plugins/preprocessor' import { SpecsStore } from './specs-store' import { checkSupportFile, getDefaultConfigFilePath } from './project_utils' import type { FoundBrowser, OpenProjectLaunchOptions } from '@packages/types' +import { DataContextShell } from '@packages/data-context/src/DataContextShell' // Cannot just use RuntimeConfigOptions as is because some types are not complete. // Instead, this is an interface of values that have been manually validated to exist @@ -65,6 +66,7 @@ export class ProjectBase extends EE { public id: string protected watchers: Watchers + protected ctx: DataContextShell protected _cfg?: Cfg protected _server?: TServer protected _automation?: Automation @@ -82,7 +84,7 @@ export class ProjectBase extends EE { constructor ({ projectRoot, testingType, - options, + options = {}, }: { projectRoot: string testingType: Cypress.TestingType @@ -104,6 +106,7 @@ export class ProjectBase extends EE { this.spec = null this.browser = null this.id = createHmac('sha256', 'secret-key').update(projectRoot).digest('hex') + this.ctx = options.ctx ?? new DataContextShell() debug('Project created %o', { testingType: this.testingType, @@ -162,8 +165,8 @@ export class ProjectBase extends EE { createServer (testingType: Cypress.TestingType) { return testingType === 'e2e' - ? new ServerE2E() as TServer - : new ServerCt() as TServer + ? new ServerE2E(this.ctx) as TServer + : new ServerCt(this.ctx) as TServer } async open () { @@ -186,7 +189,9 @@ export class ProjectBase extends EE { this._server = this.createServer(this.testingType) - cfg = await this.initializePlugins(cfg, this.options) + if (!this.options.skipPluginIntializeForTesting) { + cfg = await this.initializePlugins(cfg, this.options) + } const { specsStore, @@ -209,6 +214,7 @@ export class ProjectBase extends EE { specsStore, }) + this.ctx.setAppServerPort(port) this._isServerOpen = true // if we didnt have a cfg.port @@ -337,7 +343,10 @@ export class ProjectBase extends EE { return } - const closePreprocessor = (this.testingType === 'e2e' && preprocessor.close) ?? undefined + const closePreprocessor = this.testingType === 'e2e' ? preprocessor.close : undefined + + this.ctx.setAppServerPort(undefined) + this.ctx.emitter.setAppSocketServer(undefined) await Promise.all([ this.server?.close(), @@ -436,7 +445,7 @@ export class ProjectBase extends EE { config, }: { specs: Cypress.Cypress['spec'][] - config: any + config: Cfg }) { const specsStore = new SpecsStore(config, this.testingType) @@ -458,7 +467,7 @@ export class ProjectBase extends EE { let ctDevServerPort: number | undefined - if (this.testingType === 'component') { + if (this.testingType === 'component' && !this.options.skipPluginIntializeForTesting) { const { port } = await this.startCtDevServer(specs, config) ctDevServerPort = port @@ -595,7 +604,7 @@ export class ProjectBase extends EE { this._automation = new Automation(namespace, socketIoCookie, screenshotsFolder, onBrowserPreRequest, onRequestEvent) - this.server.startWebsockets(this.automation, this.cfg, { + const io = this.server.startWebsockets(this.automation, this.cfg, { onReloadBrowser: options.onReloadBrowser, onFocusTests: options.onFocusTests, onSpecChanged: options.onSpecChanged, @@ -651,6 +660,8 @@ export class ProjectBase extends EE { return }, }) + + this.ctx.emitter.setAppSocketServer(io) } changeToUrl (url) { diff --git a/packages/server/lib/routes-ct.ts b/packages/server/lib/routes-ct.ts index d7c7b49acd..6c551ef15b 100644 --- a/packages/server/lib/routes-ct.ts +++ b/packages/server/lib/routes-ct.ts @@ -5,6 +5,8 @@ import { Request, Response, Router } from 'express' import send from 'send' import { getPathToDist } from '@packages/resolve-dist' import type { InitializeRoutes } from './routes' +import { fs } from './util/fs' +import type { DataContextShell } from '@packages/data-context/src/DataContextShell' const debug = Debug('cypress:server:routes-ct') @@ -15,6 +17,7 @@ const serveChunk = (req: Request, res: Response, clientRoute: string) => { } export const createRoutesCT = ({ + ctx, config, nodeProxy, getCurrentBrowser, @@ -23,20 +26,52 @@ export const createRoutesCT = ({ const routesCt = Router() if (process.env.CYPRESS_INTERNAL_VITE_APP_PORT) { - const myProxy = httpProxy.createProxyServer({ + const proxy = httpProxy.createProxyServer({ target: `http://localhost:${process.env.CYPRESS_INTERNAL_VITE_APP_PORT}/`, }) + const proxyIndex = httpProxy.createProxyServer({ + target: `http://localhost:${process.env.CYPRESS_INTERNAL_VITE_APP_PORT}/`, + selfHandleResponse: true, + }) + + proxyIndex.on('proxyRes', function (proxyRes, _req, _res) { + const body: any[] = [] + + proxyRes.on('data', function (chunk) { + let chunkData = String(chunk) + + if (chunkData.includes('')) { + chunkData = chunkData.replace('', replaceBody(ctx)) + } + + body.push(chunkData) + }) + + proxyRes.on('end', function () { + (_res as Response).send(body.join('')) + }) + }) // TODO: can namespace this onto a "unified" route like __app-unified__ // make sure to update the generated routes inside of vite.config.ts routesCt.get('/__vite__/*', (req, res) => { - myProxy.web(req, res, {}, (e) => { - }) + if (req.params[0] === '') { + proxyIndex.web(req, res, {}, (e) => {}) + } else { + proxy.web(req, res, {}, (e) => {}) + } }) } else { routesCt.get('/__vite__/*', (req, res) => { const pathToFile = getPathToDist('app', req.params[0]) + if (req.params[0] === '') { + return fs.readFile(pathToFile, 'utf8') + .then((file) => { + res.send(file.replace('', replaceBody(ctx))) + }) + } + return send(req, pathToFile).pipe(res) }) } @@ -122,3 +157,7 @@ export const createRoutesCT = ({ return routesCt } + +function replaceBody (ctx: DataContextShell) { + return `\n` +} diff --git a/packages/server/lib/routes.ts b/packages/server/lib/routes.ts index 96afe4c83f..e8463c4ea0 100644 --- a/packages/server/lib/routes.ts +++ b/packages/server/lib/routes.ts @@ -9,10 +9,12 @@ import type { Cfg } from './project-base' import xhrs from './controllers/xhrs' import { runner } from './controllers/runner' import { iframesController } from './controllers/iframes' +import type { DataContextShell } from '@packages/data-context/src/DataContextShell' const debug = Debug('cypress:server:routes') export interface InitializeRoutes { + ctx: DataContextShell specsStore: SpecsStore config: Cfg getSpec: () => Cypress.Spec | null diff --git a/packages/server/lib/server-base.ts b/packages/server/lib/server-base.ts index 80bc4a6c19..bc86585625 100644 --- a/packages/server/lib/server-base.ts +++ b/packages/server/lib/server-base.ts @@ -31,6 +31,7 @@ import type { Browser } from '@packages/server/lib/browsers/types' import { InitializeRoutes, createCommonRoutes } from './routes' import { createRoutesE2E } from './routes-e2e' import { createRoutesCT } from './routes-ct' +import type { DataContextShell } from '@packages/data-context/src/DataContextShell' const ALLOWED_PROXY_BYPASS_URLS = [ '/', @@ -126,7 +127,7 @@ export abstract class ServerBase { protected _remoteDomainName: unknown protected _remoteFileServer: unknown - constructor () { + constructor (private ctx: DataContextShell) { this.isListening = false // @ts-ignore this.request = Request() @@ -211,6 +212,7 @@ export abstract class ServerBase { this.createHosts(config.hosts) const routeOptions: InitializeRoutes = { + ctx: this.ctx, config, specsStore, getRemoteState, @@ -621,9 +623,4 @@ export abstract class ServerBase { sendSpecList (specs: Cypress.Cypress['spec'][], testingType: Cypress.TestingType) { return this.socket.sendSpecList(specs, testingType) } - - // used for testing - __setMiddleware (middleware: any) { - this._middleware = middleware - } } diff --git a/packages/server/lib/server-e2e.ts b/packages/server/lib/server-e2e.ts index 531962cedc..10b83d5cd9 100644 --- a/packages/server/lib/server-e2e.ts +++ b/packages/server/lib/server-e2e.ts @@ -3,6 +3,7 @@ import Debug from 'debug' import isHtml from 'is-html' import _ from 'lodash' import stream from 'stream' +import { EventEmitter } from 'events' import url from 'url' import httpsProxy from '@packages/https-proxy' import { getRouteForRequest } from '@packages/net-stubbing' @@ -16,6 +17,7 @@ import * as ensureUrl from './util/ensure-url' import headersUtil from './util/headers' import statusCode from './util/status_code' import type { Cfg } from './project-base' +import { DataContextShell } from '@packages/data-context/src/DataContextShell' type WarningErr = Record @@ -44,8 +46,8 @@ const isResponseHtml = function (contentType, responseBuffer) { export class ServerE2E extends ServerBase { private _urlResolver: Bluebird> | null - constructor () { - super() + constructor (ctx: DataContextShell = new DataContextShell({ rootBus: new EventEmitter })) { + super(ctx) this._urlResolver = null } diff --git a/packages/server/lib/specs-store.ts b/packages/server/lib/specs-store.ts index fab8991565..6eafe7ab87 100644 --- a/packages/server/lib/specs-store.ts +++ b/packages/server/lib/specs-store.ts @@ -21,15 +21,15 @@ export class SpecsStore { constructor ( private cypressConfig: Record, - private runner: Cypress.TestingType, + private testingType: Cypress.TestingType, ) {} get specDirectory () { - if (this.runner === 'e2e') { + if (this.testingType === 'e2e') { return this.cypressConfig.resolved.integrationFolder.value } - if (this.runner === 'component') { + if (this.testingType === 'component') { return this.cypressConfig.resolved.componentFolder.value } } diff --git a/packages/server/lib/util/ts_node.js b/packages/server/lib/util/ts_node.js index cc9306dce3..10b8f5dc2d 100644 --- a/packages/server/lib/util/ts_node.js +++ b/packages/server/lib/util/ts_node.js @@ -1,11 +1,17 @@ -const debug = require('debug')('cypress:server:ts-node') +// @ts-check +const debugLib = require('debug') const path = require('path') const tsnode = require('ts-node') const resolve = require('./resolve') +const debug = debugLib('cypress:server:ts-node') + const getTsNodeOptions = (tsPath, registeredFile) => { - return { - compiler: tsPath, // use the user's installed typescript + /** + * @type {import('ts-node').RegisterOptions} + */ + const opts = { + compiler: process.env.TS_NODE_COMPILER || tsPath, // use the user's installed typescript compilerOptions: { module: 'CommonJS', }, @@ -14,6 +20,8 @@ const getTsNodeOptions = (tsPath, registeredFile) => { dir: path.dirname(registeredFile), transpileOnly: true, // transpile only (no type-check) for speed } + + return opts } const register = (projectRoot, registeredFile) => { diff --git a/packages/server/lib/util/validation.js b/packages/server/lib/util/validation.js index 14830fe802..c0e20bbde8 100644 --- a/packages/server/lib/util/validation.js +++ b/packages/server/lib/util/validation.js @@ -2,6 +2,8 @@ const _ = require('lodash') const debug = require('debug')('cypress:server:validation') const is = require('check-more-types') const { commaListsOr } = require('common-tags') +const { URL } = require('url') + const configOptions = require('../config_options') const path = require('path') diff --git a/packages/server/package.json b/packages/server/package.json index b73af185b3..69a2cb53b5 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -49,6 +49,7 @@ "compression": "1.7.4", "content-type": "1.0.4", "cookie-parser": "1.4.5", + "cors": "2.8.5", "data-uri-to-buffer": "2.0.1", "dayjs": "^1.9.3", "debug": "4.3.2", @@ -65,6 +66,7 @@ "fluent-ffmpeg": "2.1.2", "fs-extra": "8.1.0", "get-port": "5.1.1", + "getenv": "1.0.0", "getos": "3.2.1", "glob": "7.1.3", "graceful-fs": "4.2.0", @@ -94,6 +96,7 @@ "node-machine-id": "1.1.12", "opn": "cypress-io/opn#2f4e9a216ca7bdb95dfae9d46d99ddf004b3cbb5", "ospath": "1.2.2", + "p-defer": "^3.0.0", "p-queue": "6.1.0", "pluralize": "8.0.0", "ramda": "0.27.1", @@ -115,7 +118,7 @@ "tough-cookie": "4.0.0", "trash": "5.2.0", "tree-kill": "1.2.2", - "ts-node": "8.5.4", + "ts-node": "^10.2.1", "tslib": "2.3.0", "underscore.string": "3.3.5", "url-parse": "1.5.2", @@ -131,10 +134,12 @@ "@cypress/json-schemas": "5.39.0", "@cypress/sinon-chai": "2.9.1", "@ffprobe-installer/ffprobe": "1.1.0", + "@packages/data-context": "0.0.0-development", "@packages/desktop-gui": "0.0.0-development", "@packages/electron": "0.0.0-development", "@packages/example": "0.0.0-development", "@packages/extension": "0.0.0-development", + "@packages/graphql": "0.0.0-development", "@packages/https-proxy": "0.0.0-development", "@packages/launcher": "0.0.0-development", "@packages/net-stubbing": "0.0.0-development", @@ -156,7 +161,6 @@ "chai-uuid": "1.0.6", "chokidar-cli": "2.1.0", "chrome-har-capturer": "0.13.4", - "cors": "2.8.5", "cross-env": "6.0.3", "devtools-protocol": "0.0.839267", "eol": "0.9.1", diff --git a/packages/server/test/integration/websockets_spec.js b/packages/server/test/integration/websockets_spec.js index 915ac4c9de..f71838bc1c 100644 --- a/packages/server/test/integration/websockets_spec.js +++ b/packages/server/test/integration/websockets_spec.js @@ -5,7 +5,7 @@ const ws = require('ws') const httpsProxyAgent = require('https-proxy-agent') const evilDns = require('evil-dns') const Promise = require('bluebird') -const socketIo = require(`${root}../socket`) +const socketIo = require(`${root}../socket/lib/browser`) const httpsServer = require(`${root}../https-proxy/test/helpers/https_server`) const config = require(`${root}lib/config`) const { ServerE2E } = require(`${root}lib/server-e2e`) diff --git a/packages/server/test/support/fixtures/projects/non-proxied/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/non-proxied/cypress/plugins/index.js index b3bc9e5bd9..e6996e5fe2 100644 --- a/packages/server/test/support/fixtures/projects/non-proxied/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/non-proxied/cypress/plugins/index.js @@ -1,7 +1,7 @@ const { expect } = require('chai') const HttpsProxyAgent = require('https-proxy-agent') const os = require('os') -const socketIo = require('@packages/socket') +const socketIo = require('@packages/socket/lib/browser') module.exports = (on) => { on('task', { diff --git a/packages/server/test/unit/gui/events_spec.js b/packages/server/test/unit/gui/events_spec.js index 9e135fe5a3..8c4002cb14 100644 --- a/packages/server/test/unit/gui/events_spec.js +++ b/packages/server/test/unit/gui/events_spec.js @@ -79,7 +79,7 @@ describe('lib/gui/events', () => { it('ipc attaches callback on request', () => { sinon.stub(events, 'handleEvent') - events.start({ foo: 'bar' }, {}, { startGraphQL: false }) + events.start({ foo: 'bar' }, {}) expect(electron.ipcMain.on).to.be.calledWith('request') }) @@ -88,7 +88,7 @@ describe('lib/gui/events', () => { electron.ipcMain.on.yields('arg1', 'arg2') const handleEvent = sinon.stub(events, 'handleEvent') - events.start({ foo: 'bar' }, {}, { startGraphQL: false }) + events.start({ foo: 'bar' }, {}) expect(handleEvent).to.be.calledWith({ foo: 'bar' }, {}, 'arg1', 'arg2') }) diff --git a/packages/server/test/unit/gui/windows_spec.ts b/packages/server/test/unit/gui/windows_spec.ts index 21400ed5d8..92bd909df1 100644 --- a/packages/server/test/unit/gui/windows_spec.ts +++ b/packages/server/test/unit/gui/windows_spec.ts @@ -47,7 +47,7 @@ describe('lib/gui/windows', () => { type: 'INDEX', } - return Windows.open('/path/to/project', options, () => this.win) + return Windows.open('/path/to/project', undefined, options, () => this.win) .then((win) => { expect(options).to.include({ height: 500, diff --git a/packages/server/test/unit/socket_spec.js b/packages/server/test/unit/socket_spec.js index 6b537d6943..f03e49646d 100644 --- a/packages/server/test/unit/socket_spec.js +++ b/packages/server/test/unit/socket_spec.js @@ -3,7 +3,7 @@ require('../spec_helper') const _ = require('lodash') const path = require('path') const Promise = require('bluebird') -const socketIo = require('@packages/socket') +const socketIo = require('@packages/socket/lib/browser') const httpsAgent = require('https-proxy-agent') const errors = require(`${root}lib/errors`) const config = require(`${root}lib/config`) diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json index 7e30aed0df..6ccf4a1085 100644 --- a/packages/server/tsconfig.json +++ b/packages/server/tsconfig.json @@ -8,9 +8,7 @@ "./../ts/index.d.ts" ], "compilerOptions": { - "lib": ["ES2020"], "types": ["mocha", "node"], - "importHelpers": true, "resolveJsonModule": true, "noUnusedLocals": false, } diff --git a/packages/socket/README.md b/packages/socket/README.md index e7160863c3..037fbdd846 100644 --- a/packages/socket/README.md +++ b/packages/socket/README.md @@ -5,12 +5,11 @@ This is a shared lib for holding both the `socket.io` server and client. ## Using ```javascript -const socket = require("packages/socket") +const socket = require("@packages/socket") // returns { server: require("socket.io"), - client: require("socket.io-client"), getPathToClientSource: function () { // returns path to the client 'socket.io.js' file // for use in the browser @@ -19,7 +18,7 @@ const socket = require("packages/socket") ``` ```javascript -const socket = require("packages/socket") +const socket = require("@packages/socket") // server usage const srv = require("http").createServer() @@ -27,6 +26,7 @@ const io = socket.server(srv) io.on("connection", function(){}) // client usage +const { client } = require("@packages/socket/lib/client") const client = socket.client("http://localhost:2020") client.on("connect", function(){}) client.on("event", function(){}) diff --git a/packages/socket/index.js b/packages/socket/index.js index be42ab367a..bd97e75545 100644 --- a/packages/socket/index.js +++ b/packages/socket/index.js @@ -1,18 +1,5 @@ -'use strict' -let __createBinding = (this && this.__createBinding) || (Object.create ? (function (o, m, k, k2) { - if (k2 === undefined) k2 = k - - Object.defineProperty(o, k2, { enumerable: true, get () { - return m[k] - } }) -}) : (function (o, m, k, k2) { - if (k2 === undefined) k2 = k - - o[k2] = m[k] -})) -let __exportStar = (this && this.__exportStar) || function (m, exports) { - for (let p in m) if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p) +if (process.env.CYPRESS_INTERNAL_ENV !== 'production') { + require('@packages/ts/register') } -Object.defineProperty(exports, '__esModule', { value: true }) -__exportStar(require('./lib/socket'), exports) +module.exports = require('./lib/socket') diff --git a/packages/socket/index.ts b/packages/socket/index.ts deleted file mode 100644 index 5892e6490c..0000000000 --- a/packages/socket/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './lib/socket' diff --git a/packages/socket/lib/browser.js b/packages/socket/lib/browser.js deleted file mode 100644 index ff4805cd5b..0000000000 --- a/packages/socket/lib/browser.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' -let __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { 'default': mod } -} - -Object.defineProperty(exports, '__esModule', { value: true }) -exports.client = void 0 - -const socket_io_client_1 = __importDefault(require('socket.io-client')) - -exports.client = socket_io_client_1.default diff --git a/packages/socket/lib/browser.ts b/packages/socket/lib/browser.ts index f1a4db4b9c..82c85f81f0 100644 --- a/packages/socket/lib/browser.ts +++ b/packages/socket/lib/browser.ts @@ -1,5 +1,7 @@ import io from 'socket.io-client' +export type { Socket } from 'socket.io-client' + export { io as client, } diff --git a/packages/socket/lib/socket.js b/packages/socket/lib/socket.js deleted file mode 100644 index 3b049dfbcc..0000000000 --- a/packages/socket/lib/socket.js +++ /dev/null @@ -1,83 +0,0 @@ -'use strict' -let __createBinding = (this && this.__createBinding) || (Object.create ? (function (o, m, k, k2) { - if (k2 === undefined) k2 = k - - Object.defineProperty(o, k2, { enumerable: true, get () { - return m[k] - } }) -}) : (function (o, m, k, k2) { - if (k2 === undefined) k2 = k - - o[k2] = m[k] -})) -let __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function (o, v) { - Object.defineProperty(o, 'default', { enumerable: true, value: v }) -}) : function (o, v) { - o['default'] = v -}) -let __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod - - let result = {} - - if (mod != null) for (let k in mod) if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k) - - __setModuleDefault(result, mod) - - return result -} -let __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { 'default': mod } -} - -Object.defineProperty(exports, '__esModule', { value: true }) -exports.getClientSource = exports.getClientVersion = exports.getPathToClientSource = exports.SocketIOServer = exports.server = exports.client = void 0 - -const fs_1 = __importDefault(require('fs')) -const socket_io_1 = __importStar(require('socket.io')) - -exports.server = socket_io_1.default - -const browser_1 = require('./browser') - -Object.defineProperty(exports, 'client', { enumerable: true, get () { - return browser_1.client -} }) - -const HUNDRED_MEGABYTES = 1e8 // 100000000 -const { version } = require('socket.io-client/package.json') -const clientSource = require.resolve('socket.io-client/dist/socket.io.js') - -class SocketIOServer extends socket_io_1.Server { - constructor (srv, opts) { - let _a - - // in socket.io v3, they reduced down the max buffer size - // from 100mb to 1mb, so we reset it back to the previous value - // - // previous commit for reference: - // https://github.com/socketio/engine.io/blame/61b949259ed966ef6fc8bfd61f14d1a2ef06d319/lib/server.js#L29 - opts = opts !== null && opts !== void 0 ? opts : {} - opts.maxHttpBufferSize = (_a = opts.maxHttpBufferSize) !== null && _a !== void 0 ? _a : HUNDRED_MEGABYTES - super(srv, opts) - } -} -exports.SocketIOServer = SocketIOServer - -const getPathToClientSource = () => { - return clientSource -} - -exports.getPathToClientSource = getPathToClientSource - -const getClientVersion = () => { - return version -} - -exports.getClientVersion = getClientVersion - -const getClientSource = () => { - return fs_1.default.readFileSync(exports.getPathToClientSource(), 'utf8') -} - -exports.getClientSource = getClientSource diff --git a/packages/socket/lib/socket.ts b/packages/socket/lib/socket.ts index f88980be5a..5f20e732f5 100644 --- a/packages/socket/lib/socket.ts +++ b/packages/socket/lib/socket.ts @@ -1,7 +1,6 @@ import fs from 'fs' import type http from 'http' import server, { Server as SocketIOBaseServer, ServerOptions, Socket } from 'socket.io' -import { client } from './browser' export type { Socket } @@ -30,7 +29,6 @@ class SocketIOServer extends SocketIOBaseServer { } export { - client, server, SocketIOServer, } diff --git a/packages/socket/package.json b/packages/socket/package.json index c797c774ae..5de0cdcbc3 100644 --- a/packages/socket/package.json +++ b/packages/socket/package.json @@ -5,7 +5,8 @@ "main": "index.js", "browser": "lib/browser.ts", "scripts": { - "build-prod": "tsc || echo 'built, with type errors'", + "build-prod": "tsc || echo 'built, with type errors' && rm lib/browser.js", + "clean": "rimraf lib/*.js", "check-ts": "tsc --noEmit", "clean-deps": "rimraf node_modules", "postinstall": "patch-package", @@ -30,6 +31,7 @@ "lib", "patches" ], + "types": "lib/socket.ts", "workspaces": { "nohoist": [ "socket.io", diff --git a/packages/socket/test/socket_spec.js b/packages/socket/test/socket_spec.js index deb3a572d1..b3ef357cf1 100644 --- a/packages/socket/test/socket_spec.js +++ b/packages/socket/test/socket_spec.js @@ -7,6 +7,7 @@ const { hasBinary } = require('socket.io-parser/dist/is-binary') const expect = require('chai').expect const pkg = require('../package.json') const lib = require('../index') +const browserLib = require('../lib/browser') const resolvePkg = require('resolve-pkg') const { PacketType } = parser @@ -16,8 +17,8 @@ describe('Socket', function () { expect(lib.server).to.eq(server) }) - it('exports client', function () { - expect(lib.client).to.eq(client) + it('exports client from lib/browser', function () { + expect(browserLib.client).to.eq(client) }) context('.getPathToClientSource', function () { diff --git a/packages/socket/tsconfig.json b/packages/socket/tsconfig.json index 0eaa807d13..071d0eb424 100644 --- a/packages/socket/tsconfig.json +++ b/packages/socket/tsconfig.json @@ -2,10 +2,8 @@ "extends": "./../ts/tsconfig.json", "include": [ "lib/*.ts", - "./lib/**/*.ts" ], "files": [ - "index.ts", "./../ts/index.d.ts" ] } diff --git a/packages/ts/package.json b/packages/ts/package.json index 08dcb9956d..16b8415875 100644 --- a/packages/ts/package.json +++ b/packages/ts/package.json @@ -15,7 +15,8 @@ }, "devDependencies": { "rimraf": "3.0.2", - "ts-node": "5.0.1" + "ts-node": "^10.2.1", + "typescript-cached-transpile": "^0.0.6" }, "files": [ "register.js" diff --git a/packages/ts/patches/ts-node+5.0.1.patch b/packages/ts/patches/ts-node+5.0.1.patch deleted file mode 100644 index b53b150ae8..0000000000 --- a/packages/ts/patches/ts-node+5.0.1.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/ts-node/dist/index.js b/node_modules/ts-node/dist/index.js -index 2dfd704..c00aa39 100644 ---- a/node_modules/ts-node/dist/index.js -+++ b/node_modules/ts-node/dist/index.js -@@ -298,7 +298,7 @@ function readThrough(cachedir, shouldCache, memoryCache, compile, getExtension) - }; - } - function updateOutput(outputText, fileName, sourceMap, getExtension) { -- var base64Map = new Buffer(updateSourceMap(sourceMap, fileName), 'utf8').toString('base64'); -+ var base64Map = Buffer.from(updateSourceMap(sourceMap, fileName), 'utf8').toString('base64'); - var sourceMapContent = "data:application/json;charset=utf-8;base64," + base64Map; - var sourceMapLength = (path_1.basename(fileName) + ".map").length + (getExtension(fileName).length - path_1.extname(fileName).length); - return outputText.slice(0, -sourceMapLength) + sourceMapContent; diff --git a/packages/ts/register.js b/packages/ts/register.js index 0b5b67a0bb..6c59f5eb2d 100644 --- a/packages/ts/register.js +++ b/packages/ts/register.js @@ -1,5 +1,6 @@ +// @ts-check const log = require('debug')('cypress:ts') -let tsNode +const path = require('path') // in development we should have TypeScript hook installed // in production or staging we are likely to be running @@ -7,21 +8,25 @@ let tsNode // build has been done correctly try { - tsNode = require('ts-node') + // Prevent double-compiling if we're testing the app and already have ts-node hook installed + // TODO(tim): e2e testing does not like this, I guess b/c it's currently using the tsconfig + // for the app project? + if (require.extensions['.ts']) { + // debugger + } + const tsNode = require('ts-node') // register TypeScript Node require hook // https://github.com/TypeStrong/ts-node#programmatic-usage const project = require('path').join(__dirname, 'tsconfig.json') - // transpile TypeScript without checking types by default - // set environment variable when you want to actually verify types - const fast = Boolean(process.env.TS_CHECK_TYPES) === false - - log('register TypeScript project %s fast? %s', project, fast) + process.env.TS_CACHED_TRANSPILE_CACHE = path.join(__dirname, 'node_modules', '.ts-cache') tsNode.register({ + compiler: 'typescript-cached-transpile', project, - fast, + transpileOnly: true, + preferTsExts: true, // Helps when the files are compiled locally, resolves the TS file }) // do we need to prevent any other TypeScript hooks? diff --git a/packages/ts/tsconfig.dom.json b/packages/ts/tsconfig.dom.json new file mode 100644 index 0000000000..b35965c1b3 --- /dev/null +++ b/packages/ts/tsconfig.dom.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "lib": [ + "ESNext", + "DOM" + ] + } +} \ No newline at end of file diff --git a/packages/ts/tsconfig.json b/packages/ts/tsconfig.json index 53e8f22574..bf4c449794 100644 --- a/packages/ts/tsconfig.json +++ b/packages/ts/tsconfig.json @@ -3,7 +3,7 @@ /* Basic Options */ "target": "ES2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ - // "lib": [], /* Specify library files to be included in the compilation: */ + "lib": ["es2018", "ES2020.Promise"], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ @@ -27,7 +27,7 @@ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ /* Additional Checks */ - "noUnusedLocals": true, /* Report errors on unused locals. */ + "noUnusedLocals": false, /* Report errors on unused locals. */ "noUnusedParameters": false, /* Report errors on unused parameters. */ "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ diff --git a/packages/types/src/browser.ts b/packages/types/src/browser.ts index ffba10135d..c79bf4c293 100644 --- a/packages/types/src/browser.ts +++ b/packages/types/src/browser.ts @@ -6,8 +6,6 @@ export type BrowserChannel = 'stable' | 'canary' | 'beta' | 'dev' | 'nightly' | export type BrowserFamily = typeof BROWSER_FAMILY[number] -export type PlatformName = 'darwin' | 'linux' | 'win32' - /** * Represents a typical browser to try to detect and turn into a `FoundBrowser`. */ diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 6adc8ffe66..6a979982ba 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -9,6 +9,8 @@ export type { export * from './browser' +export type { PlatformName } from './platform' + export { BROWSER_FAMILY, MIN_CHROME_VERSION, diff --git a/packages/types/src/platform.ts b/packages/types/src/platform.ts new file mode 100644 index 0000000000..bcd4591436 --- /dev/null +++ b/packages/types/src/platform.ts @@ -0,0 +1,9 @@ +export const SUPPORTED_PLATFORMS = ['linux', 'darwin', 'win32'] as const + +export type PlatformName = typeof SUPPORTED_PLATFORMS[number] + +export function assertValidPlatform (platform: NodeJS.Platform): asserts platform is PlatformName { + if (!SUPPORTED_PLATFORMS.includes(platform as any)) { + throw new Error(`Unsupported platform ${platform}, expected ${SUPPORTED_PLATFORMS.join(', ')}`) + } +} diff --git a/packages/types/src/server.ts b/packages/types/src/server.ts index 5055d78444..29519c6b28 100644 --- a/packages/types/src/server.ts +++ b/packages/types/src/server.ts @@ -1,4 +1,6 @@ -import type { Browser, FoundBrowser, PlatformName } from './browser' +import type { DataContext } from '@packages/data-context' +import type { Browser, FoundBrowser } from './browser' +import type { PlatformName } from './platform' export interface LaunchOpts { browser?: FoundBrowser @@ -8,6 +10,11 @@ export interface LaunchOpts { onBrowserClose?: (...args: unknown[]) => void onBrowserOpen?: (...args: unknown[]) => void onError?: (err: Error) => void + /** + * Whether we want to skip opening the browser, in the case we're + * using Cypress to test the server directly + */ + skipBrowserOpenForTest?: true } export interface LaunchArgs { @@ -48,7 +55,13 @@ export interface AutomationMiddleware { type WebSocketOptionsCallback = (...args: any[]) => any export interface OpenProjectLaunchOptions { + ctx?: DataContext args?: LaunchArgs + /** + * Whether to skip the plugin initialization, useful when + * we're using Cypress to test Cypress + */ + skipPluginIntializeForTesting?: boolean configFile?: string | false browsers?: Cypress.Browser[] diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json index c49a327d2a..eb50e709c6 100644 --- a/packages/types/tsconfig.json +++ b/packages/types/tsconfig.json @@ -8,13 +8,12 @@ "strict": true, "noImplicitAny": true, "esModuleInterop": true, + "noUnusedLocals": false, + "noUnusedParameters": false, "experimentalDecorators": true, "allowJs": true, "types": [], "noUncheckedIndexedAccess": true, "importsNotUsedAsValues": "error" }, - // "files": [ - // "../ts/index.d.ts" - // ], } \ No newline at end of file diff --git a/scripts/gulp/gulpConstants.ts b/scripts/gulp/gulpConstants.ts index c96ef52aff..bb4ec161ef 100644 --- a/scripts/gulp/gulpConstants.ts +++ b/scripts/gulp/gulpConstants.ts @@ -11,32 +11,18 @@ export const ENV_VARS = { PROD: { CYPRESS_INTERNAL_ENV: 'production', CYPRESS_INTERNAL_CLOUD_ENV: 'production', - CYPRESS_INTERNAL_GQL_PORT: `52200`, - }, - - // Used when we're spawning Cypress as the E2E target for the - // test runner. We build the assets w/ GQL_TEST_PORT into `dist-e2e`, - // and spawn the server against - E2E_TEST_TARGET: { - CYPRESS_INTERNAL_CLOUD_ENV: DEFAULT_INTERNAL_CLOUD_ENV, // staging for now, until we get an e2e workflow w/ cloud project - CYPRESS_INTERNAL_GQL_PORT: `52300`, - CYPRESS_INTERNAL_ENV: 'staging', // Different than DEV, which will default to "development". TODO: Make this do less things internall - CYPRESS_INTERNAL_E2E_TESTING_SELF: `true`, - XVFB_DISPLAY_NUM: `44`, }, // Uses the "built" vite assets, not the served ones DEV_OPEN: { CYPRESS_KONFIG_ENV: DEFAULT_INTERNAL_CLOUD_ENV, // TODO: Change this / remove konfig CYPRESS_INTERNAL_CLOUD_ENV: DEFAULT_INTERNAL_CLOUD_ENV, // staging for now, until we get an e2e workflow w/ cloud project - CYPRESS_INTERNAL_GQL_PORT: `52200`, }, // Used when we're running Cypress in true "development" mode DEV: { CYPRESS_KONFIG_ENV: DEFAULT_INTERNAL_CLOUD_ENV, // TODO: Change this / remove konfig CYPRESS_INTERNAL_CLOUD_ENV: DEFAULT_INTERNAL_CLOUD_ENV, // staging for now, until we get an e2e workflow w/ cloud project - CYPRESS_INTERNAL_GQL_PORT: `52200`, CYPRESS_INTERNAL_VITE_APP_PORT: `3333`, CYPRESS_INTERNAL_VITE_LAUNCHPAD_PORT: `3001`, }, diff --git a/scripts/gulp/gulpfile.ts b/scripts/gulp/gulpfile.ts index 2e6140452e..f5fe28661e 100644 --- a/scripts/gulp/gulpfile.ts +++ b/scripts/gulp/gulpfile.ts @@ -9,32 +9,33 @@ import gulp from 'gulp' import { autobarrelWatcher } from './tasks/gulpAutobarrel' -import { startCypressWatch, startCypressForTest, openCypressLaunchpad, openCypressApp, runCypressLaunchpad, wrapRunWithExit, runCypressApp, waitForTestGraphQLApi, killExistingCypress } from './tasks/gulpCypress' +import { startCypressWatch, openCypressLaunchpad, openCypressApp, runCypressLaunchpad, wrapRunWithExit, runCypressApp, killExistingCypress } from './tasks/gulpCypress' import { graphqlCodegen, graphqlCodegenWatch, nexusCodegen, nexusCodegenWatch, generateFrontendSchema, syncRemoteGraphQL } from './tasks/gulpGraphql' -import { viteApp, viteBuildAndWatchLaunchpadForTest, viteBuildLaunchpadForTest, serveBuiltLaunchpadForTest, viteCleanApp, viteCleanLaunchpad, viteLaunchpad, serveBuiltAppForTest, viteBuildAppForTest, viteBuildAndWatchAppForTest, viteBuildApp, viteBuildLaunchpad } from './tasks/gulpVite' +import { viteApp, viteCleanApp, viteCleanLaunchpad, viteLaunchpad, viteBuildApp, viteBuildAndWatchApp, viteBuildLaunchpad, viteBuildAndWatchLaunchpad } from './tasks/gulpVite' import { checkTs } from './tasks/gulpTsc' import { makePathMap } from './utils/makePathMap' import { makePackage } from './tasks/gulpMakePackage' import { setGulpGlobal } from './gulpConstants' import { exitAfterAll } from './tasks/gulpRegistry' import { execSync } from 'child_process' +import { webpackRunner } from './tasks/gulpWebpack' /**------------------------------------------------------------------------ * Local Development Workflow * * `yarn dev` is your primary command for getting work done *------------------------------------------------------------------------**/ +gulp.task('viteClean', gulp.parallel( + viteCleanApp, + viteCleanLaunchpad, +)) + gulp.task( 'codegen', gulp.series( // Autobarrel watcher autobarrelWatcher, - // Clean any vite assets - gulp.parallel( - viteCleanApp, - viteCleanLaunchpad, - ), // Codegen for our GraphQL Server so we have the latest schema to build // the frontend codegen correctly // Fetch the latest "remote" schema from the Cypress cloud @@ -48,25 +49,50 @@ gulp.task( ), ) +gulp.task( + 'commonSetup', + gulp.series( + 'codegen', + killExistingCypress, + ), +) + gulp.task( 'dev', gulp.series( 'codegen', + killExistingCypress, + // Now that we have the codegen, we can start the frontend(s) gulp.parallel( viteApp, viteLaunchpad, + webpackRunner, ), - killExistingCypress, - // And we're finally ready for electron, watching for changes in // /graphql to auto-restart the server startCypressWatch, ), ) +gulp.task( + 'dev:no-watch', + gulp.series( + async function setNoWatch () { + setGulpGlobal('shouldWatch', false) + }, + 'dev', + ), +) + +gulp.task('dev:clean', gulp.series( + // Clean any vite assets + 'viteClean', + 'dev', +)) + gulp.task( 'debug', gulp.series( @@ -94,10 +120,7 @@ gulp.task( gulp.task('buildProd', gulp.series( - gulp.parallel( - viteCleanApp, - viteCleanLaunchpad, - ), + 'viteClean', syncRemoteGraphQL, nexusCodegen, @@ -135,22 +158,9 @@ gulp.task('cyRunLaunchpadE2E', gulp.series( // 1. Build the Cypress App itself 'buildProd', - // 2. Build the Launchpad under test. - viteBuildLaunchpadForTest, - - // 3. Host the Launchpad on a static server for cy.visit. - serveBuiltLaunchpadForTest, - // Ensure we have no existing cypress processes running killExistingCypress, - // 4. Start the TEST Cypress App, such that its ports and other globals - // don't conflict with the real Cypress App. - startCypressForTest, - - // Wait for the Test Cypress open to start - waitForTestGraphQLApi, - // 5. Start the REAL Cypress App, which will execute the integration specs. async function _runCypressLaunchpad () { wrapRunWithExit(await runCypressLaunchpad()) @@ -161,24 +171,8 @@ gulp.task('cyRunAppE2E', gulp.series( // 1. Build the Cypress App itself 'buildProd', - // 2. Build the Launchpad under test. - gulp.parallel( - viteBuildLaunchpadForTest, - viteBuildAppForTest, - ), - - // 3. Host the Launchpad on a static server for cy.visit. - serveBuiltAppForTest, - killExistingCypress, - // 4. Start the TEST Cypress App, such that its ports and other globals - // don't conflict with the real Cypress App. - startCypressForTest, - - // Wait for the Test Cypress open to start - waitForTestGraphQLApi, - // 5. Start the REAL Cypress App, which will execute the integration specs. async function _runCypressApp () { wrapRunWithExit(await runCypressApp()) @@ -186,47 +180,41 @@ gulp.task('cyRunAppE2E', gulp.series( )) const cyOpenLaunchpad = gulp.series( - // 2. Build + watch Launchpad under test. + // 1. Build + watch Launchpad under test. // This watches for changes and is not the same things as statically // building the app for production. - viteBuildAndWatchLaunchpadForTest, + gulp.parallel( + viteBuildApp, + viteBuildAndWatchLaunchpad, + ), - // 4. Start the TEST Cypress App, such that its ports and other globals - // don't conflict with the real Cypress App. - startCypressForTest, - - // 3. Host the Launchpad on a static server for cy.visit. - serveBuiltLaunchpadForTest, - - // 5. Start the REAL (dev) Cypress App, which will launch in open mode. + // 2. Start the REAL (dev) Cypress App, which will launch in open mode. openCypressLaunchpad, ) const cyOpenApp = gulp.series( - // 2. Build + watch Launchpad under test. + // 1. Build + watch Launchpad under test. // This watches for changes and is not the same things as statically // building the app for production. gulp.parallel( - viteBuildLaunchpadForTest, - viteBuildAndWatchAppForTest, + gulp.series( + viteBuildAndWatchLaunchpad, + viteBuildAndWatchApp, + ), + webpackRunner, ), - // 3. Start the TEST Cypress App, such that its ports and other globals - // don't conflict with the real Cypress App. - startCypressForTest, - - // 4. Host the Launchpad on a static server for cy.visit. - serveBuiltAppForTest, - - // 5. Start the REAL (dev) Cypress App, which will launch in open mode. + // 2. Start the REAL (dev) Cypress App, which will launch in open mode. openCypressApp, ) // Open Cypress in production mode. // Rebuild the Launchpad app between changes. gulp.task('cyOpenLaunchpadE2E', gulp.series( + 'viteClean', + // 1. Build the Cypress App itself - 'buildProd', + 'commonSetup', // 2. Open the "app" cyOpenLaunchpad, @@ -235,8 +223,10 @@ gulp.task('cyOpenLaunchpadE2E', gulp.series( // Open Cypress in production mode. // Rebuild the Launchpad app between changes. gulp.task('cyOpenAppE2E', gulp.series( + 'viteClean', + // 1. Build the Cypress App itself - 'buildProd', + 'commonSetup', // 2. Open the launchpad app cyOpenApp, @@ -267,22 +257,14 @@ gulp.task(nexusCodegen) gulp.task(nexusCodegenWatch) gulp.task(graphqlCodegen) gulp.task(graphqlCodegenWatch) -gulp.task(startCypressForTest) gulp.task(viteCleanApp) gulp.task(viteCleanLaunchpad) -gulp.task(viteBuildLaunchpadForTest) -gulp.task(viteBuildAppForTest) - -gulp.task(serveBuiltAppForTest) -gulp.task(serveBuiltLaunchpadForTest) - -gulp.task(viteBuildAndWatchLaunchpadForTest) -gulp.task(viteBuildAndWatchAppForTest) - gulp.task(viteBuildApp) gulp.task(viteBuildLaunchpad) +gulp.task(viteBuildAndWatchApp) +gulp.task(viteBuildAndWatchLaunchpad) gulp.task('debugCypressLaunchpad', gulp.series( async function setupDebugBrk () { diff --git a/scripts/gulp/tasks/gulpCypress.ts b/scripts/gulp/tasks/gulpCypress.ts index f6ce23b231..b980b402fa 100644 --- a/scripts/gulp/tasks/gulpCypress.ts +++ b/scripts/gulp/tasks/gulpCypress.ts @@ -4,8 +4,6 @@ * * @summary Gulp tasks to run the Cypress app. */ -// @ts-expect-error - no types -import rp from '@cypress/request-promise' import chokidar from 'chokidar' import path from 'path' import pDefer from 'p-defer' @@ -33,23 +31,6 @@ export async function killExistingCypress () { child.on('exit', dfd.resolve) } -export async function waitForTestGraphQLApi () { - let i = 0 - - // eslint-disable-next-line no-constant-condition - while (true) { - try { - return await rp.get('http://localhost:52300/graphql?query={__typename}') - } catch (e) { - if (i++ > 10) { - throw e - } - - await new Promise((resolve) => setTimeout(resolve, 2000)) - } - } -} - export async function openCypressLaunchpad () { return spawnCypressWithMode('open', 'dev', ENV_VARS.DEV_OPEN, ['--project', monorepoPaths.pkgLaunchpad]) } @@ -70,23 +51,6 @@ export async function runCypressProd () { return spawnCypressWithMode('run', 'prod', ENV_VARS.PROD) } -/**------------------------------------------------------------------------ - * Testing Tasks - * Building and running the Cypress app and graphql server for testing. - * * startCypressForTest - Start the Cypress server, but without watching - * * runCypressAgainstDist - Serve the dist'd frontend over file:// - *------------------------------------------------------------------------**/ - -// Use the GQL Test Port (52300 by default, defined in ./gulp/gulpConstants) -// Spawns Cypress in "Test Cypress within Cypress" mode -export async function startCypressForTest () { - return spawnCypressWithMode('open', 'test', ENV_VARS.E2E_TEST_TARGET) -} - -export async function runCypressAgainstDist () { - return spawnCypressWithMode('run', 'test', ENV_VARS.E2E_TEST_TARGET) -} - /**------------------------------------------------------------------------ * Start and Watch Utils * * spawnCypressWithMode - Formerly known as: `node ./scripts/cypress.js run` @@ -126,6 +90,7 @@ async function spawnCypressWithMode ( ...process.env, ...env, LAUNCHPAD: '1', + TS_NODE_COMPILER: 'typescript-cached-transpile', } return await forked(`cy:${mode}:${type}`, pathToCli, [mode, ...argv], { @@ -142,15 +107,6 @@ async function spawnCypressWithMode ( *------------------------------------------------------------------------**/ export async function startCypressWatch () { - const watcher = chokidar.watch([ - 'packages/{graphql,data-context}/src/**/*.{js,ts}', - 'packages/server/lib/graphql/**/*.{js,ts}', - ], { - cwd: monorepoPaths.root, - ignored: /\.gen\.ts/, - ignoreInitial: true, - }) - let isClosing = false let isRestarting = false let child: ChildProcess | null = null @@ -194,15 +150,26 @@ export async function startCypressWatch () { isRestarting = false } - watcher.on('add', restartServer) - watcher.on('change', restartServer) + if (getGulpGlobal('shouldWatch')) { + const watcher = chokidar.watch([ + 'packages/{graphql,data-context}/src/**/*.{js,ts}', + 'packages/server/lib/**/*.{js,ts}', + ], { + cwd: monorepoPaths.root, + ignored: /\.gen\.ts/, + ignoreInitial: true, + }) + + watcher.on('add', restartServer) + watcher.on('change', restartServer) + + process.on('beforeExit', () => { + isClosing = true + watcher.close() + }) + } await startCypressWithListeners() - - process.on('beforeExit', () => { - isClosing = true - watcher.close() - }) } export function wrapRunWithExit (proc: ChildProcess) { diff --git a/scripts/gulp/tasks/gulpMakePackage.ts b/scripts/gulp/tasks/gulpMakePackage.ts index c96fc116f9..451fc27ded 100644 --- a/scripts/gulp/tasks/gulpMakePackage.ts +++ b/scripts/gulp/tasks/gulpMakePackage.ts @@ -68,9 +68,8 @@ export async function makePackage () { 'test-integration': 'mocha -r @packages/ts/register test/integration/**/*.spec.ts --config ./test/.mocharc.js --exit', } : {}), }, - dependencies: { - 'tslib': '2.3.0', - }, + files: ['src'], + dependencies: {}, devDependencies: results.scaffoldTests ? { 'mocha': '7.0.1', 'chai': '4.2.0', @@ -94,7 +93,6 @@ export async function makePackage () { 'script', ], 'compilerOptions': { - 'importHelpers': true, 'strict': true, 'allowJs': false, 'rootDir': 'src', diff --git a/scripts/gulp/tasks/gulpRegistry.ts b/scripts/gulp/tasks/gulpRegistry.ts index 44c095d25b..74460b9bdb 100644 --- a/scripts/gulp/tasks/gulpRegistry.ts +++ b/scripts/gulp/tasks/gulpRegistry.ts @@ -1,6 +1,7 @@ import type { ChildProcess } from 'child_process' import pDefer from 'p-defer' import treeKill from 'tree-kill' +import gulp from 'gulp' const childProcesses = new Set() const exitedPids = new Set() @@ -53,6 +54,19 @@ export async function exitAllProcesses () { process.stdin.resume() //so the program will not close instantly +const _task = gulp.task + +// So that we auto-exit on single tasks +// @ts-expect-error +gulp.task = function () { + if (arguments.length === 1 && typeof arguments[0] === 'function') { + process.stdin.pause() + } + + // @ts-ignore + return _task.apply(this, arguments) +} + export async function exitAfterAll () { process.stdin.pause() } diff --git a/scripts/gulp/tasks/gulpVite.ts b/scripts/gulp/tasks/gulpVite.ts index 129b63fa43..766486698d 100644 --- a/scripts/gulp/tasks/gulpVite.ts +++ b/scripts/gulp/tasks/gulpVite.ts @@ -22,26 +22,18 @@ import { AllSpawnableApps, spawned, spawnUntilMatch } from '../utils/childProces *------------------------------------------------------------------------**/ export function viteApp () { - const GQL_PORT = ENV_VARS.DEV.CYPRESS_INTERNAL_GQL_PORT const APP_PORT = ENV_VARS.DEV.CYPRESS_INTERNAL_VITE_APP_PORT return spawnViteDevServer('vite-app', `yarn vite --port ${APP_PORT} --base /__vite__/`, { cwd: monorepoPaths.pkgApp, - env: { - VITE_CYPRESS_INTERNAL_GQL_PORT: GQL_PORT, - }, }) } export function viteLaunchpad () { - const GQL_PORT = ENV_VARS.DEV.CYPRESS_INTERNAL_GQL_PORT const LAUNCHPAD_PORT = ENV_VARS.DEV.CYPRESS_INTERNAL_VITE_LAUNCHPAD_PORT return spawnViteDevServer('vite-launchpad', `yarn vite --port ${LAUNCHPAD_PORT}`, { cwd: monorepoPaths.pkgLaunchpad, - env: { - VITE_CYPRESS_INTERNAL_GQL_PORT: GQL_PORT, - }, }) } @@ -85,7 +77,17 @@ export function viteBuildApp () { cwd: monorepoPaths.pkgApp, waitForExit: true, env: { - ...process.env, + // ...process.env, + NODE_ENV: 'production', + }, + }) +} + +export function viteBuildAndWatchApp () { + return watchViteBuild('vite:build-watch-app', `yarn vite build --watch`, { + cwd: monorepoPaths.pkgApp, + env: { + // ...process.env, NODE_ENV: 'production', }, }) @@ -95,10 +97,12 @@ export function viteBuildLaunchpad () { return spawned('vite:build-launchpad', `yarn vite build`, { cwd: monorepoPaths.pkgLaunchpad, waitForExit: true, - env: { - ...process.env, - NODE_ENV: 'production', - }, + }) +} + +export function viteBuildAndWatchLaunchpad () { + return watchViteBuild('vite:build-watch-launchpad', `yarn vite build --watch`, { + cwd: monorepoPaths.pkgLaunchpad, }) } @@ -115,84 +119,3 @@ export function viteCleanLaunchpad () { waitForExit: true, }) } - -/**------------------------------------------------------------------------ - * Testing Tasks - * Build and serve the Vite frontend(s) as web apps on a static server. - * * viteBuildLaunchpadForTest - * * viteBuildAppForTest - * * serveBuiltLaunchpadForTest - * * serveBuiltAppForTest - *------------------------------------------------------------------------**/ - -// After running `serveBuiltLaunchpadForTest`, you're able to visit -// `http://localhost:5555` to access the Launchpad frontend. -export function serveBuiltLaunchpadForTest () { - return spawnUntilMatch('serve:launchpad-for-test', { - command: `yarn serve ./dist-e2e -p 5555`, - match: 'Accepting connections', - options: { - cwd: monorepoPaths.pkgLaunchpad, - }, - }) -} - -export function viteBuildLaunchpadForTest () { - const GQL_PORT = ENV_VARS.E2E_TEST_TARGET.CYPRESS_INTERNAL_GQL_PORT - - return spawned('vite:build-launchpad-for-test', `yarn vite build --outDir=./dist-e2e`, { - cwd: monorepoPaths.pkgLaunchpad, - waitForExit: true, - env: { - NODE_ENV: 'production', - VITE_CYPRESS_INTERNAL_GQL_PORT: GQL_PORT, - }, - }) -} - -export async function viteBuildAndWatchLaunchpadForTest () { - const GQL_PORT = ENV_VARS.E2E_TEST_TARGET.CYPRESS_INTERNAL_GQL_PORT - - return watchViteBuild('vite:build-watch-launchpad-for-test', `yarn vite build --watch --outDir=./dist-e2e`, { - cwd: monorepoPaths.pkgLaunchpad, - env: { - NODE_ENV: 'production', - VITE_CYPRESS_INTERNAL_GQL_PORT: GQL_PORT, - }, - }) -} - -/**---------------------- - *todo Implement E2E tests for the App. - *------------------------**/ - -export function viteBuildAppForTest () { - const GQL_PORT = ENV_VARS.E2E_TEST_TARGET.CYPRESS_INTERNAL_GQL_PORT - - return spawned('vite:build-app-for-test', `yarn vite build --outDir=./dist-e2e`, { - cwd: monorepoPaths.pkgApp, - waitForExit: true, - env: { - VITE_CYPRESS_INTERNAL_GQL_PORT: GQL_PORT, - ...process.env, - }, - }) -} - -export function serveBuiltAppForTest () { - return spawned('serve:app-for-test', `yarn serve ./dist-e2e -p 5556`, { - cwd: monorepoPaths.pkgApp, - }) -} - -export async function viteBuildAndWatchAppForTest () { - const GQL_PORT = ENV_VARS.E2E_TEST_TARGET.CYPRESS_INTERNAL_GQL_PORT - - return watchViteBuild('vite:build-watch-app-for-test', `yarn vite build --watch --outDir=./dist-e2e`, { - cwd: monorepoPaths.pkgApp, - env: { - NODE_ENV: 'production', - VITE_CYPRESS_INTERNAL_GQL_PORT: GQL_PORT, - }, - }) -} diff --git a/scripts/gulp/tasks/gulpWebpack.ts b/scripts/gulp/tasks/gulpWebpack.ts new file mode 100644 index 0000000000..0a4f1bb4a7 --- /dev/null +++ b/scripts/gulp/tasks/gulpWebpack.ts @@ -0,0 +1,70 @@ +import chalk from 'chalk' +import { spawn } from 'child_process' +import pDefer from 'p-defer' +import { monorepoPaths } from '../monorepoPaths' +import { addChildProcess } from './gulpRegistry' + +export function webpackRunner () { + return runWebpack({ + cwd: monorepoPaths.pkgRunner, + prefix: 'webpack:runner', + args: ['-w'], + }) +} + +type RunWebpackCfg = { + cwd: string + prefix: string + args?: string[] + env?: object + devServer?: boolean +} + +export async function runWebpack (cfg: RunWebpackCfg) { + const { cwd, args = [], env = process.env, devServer = false, prefix } = cfg + const dfd = pDefer() + const spawned = spawn( + devServer + ? './node_modules/.bin/webpack-dev-server' + : './node_modules/.bin/webpack', + args, + { + cwd, + env: { + ...(env || process.env), + FORCE_COLOR: '1', + }, + }, + ) + + addChildProcess(spawned) + + spawned.stdout.on('data', (chunk) => { + process.stdout.write('\n') + String(chunk) + .split('\n') + .forEach((line) => { + if ( + line.includes('Compiled successfully') || + line.includes('Compiled with warnings') || + line.includes('Failed to compile') || + line.includes('Built at: ') + ) { + dfd.resolve({}) + } + + process.stdout.write(`${chalk.cyan(`${prefix}: `)}${line}\n`) + }) + }) + + spawned.stderr.on('data', (chunk) => { + process.stderr.write('\n') + String(chunk) + .split('\n') + .forEach((line) => { + process.stderr.write(`${chalk.red(`${prefix}: `)}${line}\n`) + }) + }) + + return dfd.promise +} diff --git a/yarn.lock b/yarn.lock index 2cca54e125..a4815741f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2159,6 +2159,11 @@ resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.0.tgz#860ce718b0b73f4009e153541faff2cb6b85d047" integrity sha512-4Th98KlMHr5+JkxfcoDT//6vY8vM+iSPrLNpHhRyLx2CFYi8e2RfqPLdpbnpo0Q5lQC5hNB79yes07zb02fvCw== +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@benmalka/foxdriver@0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@benmalka/foxdriver/-/foxdriver-0.4.1.tgz#d21113f450b5d2dee669162b3f983c4588d0459e" @@ -2184,6 +2189,18 @@ resolved "https://registry.yarnpkg.com/@coolaj86/urequest/-/urequest-1.3.7.tgz#66a1d66378dd6534e9c8e68948bf09acf32bab77" integrity sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA== +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz#118511f316e2e87ee4294761868e254d3da47960" + integrity sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + "@csstools/convert-colors@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" @@ -8192,6 +8209,26 @@ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669" integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow== +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + "@types/anymatch@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" @@ -8628,7 +8665,7 @@ resolved "https://registry.yarnpkg.com/@types/is-function/-/is-function-1.0.0.tgz#1b0b819b1636c7baf0d6785d030d12edf70c3e83" integrity sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w== -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== @@ -8829,10 +8866,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== -"@types/node@^12.11.1", "@types/node@^12.12.29": - version "12.20.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.12.tgz#fd9c1c2cfab536a2383ed1ef70f94adea743a226" - integrity sha512-KQZ1al2hKOONAs2MFv+yTQP1LkDWMrRJ9YCVRalXltOfXsBmH5IownLxQaiq0lnAHwAViLnh2aTYqrPcRGEbgg== +"@types/node@^12.11.1", "@types/node@^12.12.29", "@types/node@^12.12.7": + version "12.20.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.28.tgz#4b20048c6052b5f51a8d5e0d2acbf63d5a17e1e2" + integrity sha512-cBw8gzxUPYX+/5lugXIPksioBSbE42k0fZ39p+4yRzfYjN6++eq9kAPdlY9qm+MXyfbk9EmvCYAYRn380sF46w== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -9013,6 +9050,14 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb" integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== +"@types/send@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" + integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/serve-index@*": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -10684,6 +10729,11 @@ acorn-walk@^7.0.0, acorn-walk@^7.1.1, acorn-walk@^7.2.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^5.2.1, acorn@^5.5.3: version "5.7.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" @@ -11570,7 +11620,7 @@ arraybuffer.slice@~0.0.7: resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== -arrify@^1.0.0, arrify@^1.0.1: +arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= @@ -13962,6 +14012,24 @@ bytes@3.1.0, bytes@^3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +c8@^7.10.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/c8/-/c8-7.10.0.tgz#c539ebb15d246b03b0c887165982c49293958a73" + integrity sha512-OAwfC5+emvA6R7pkYFVBTOtI5ruf9DahffGmIqUc9l6wEh0h7iAFP6dt/V9Ioqlr2zW5avX9U9/w1I4alTRHkA== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@istanbuljs/schema" "^0.1.2" + find-up "^5.0.0" + foreground-child "^2.0.0" + istanbul-lib-coverage "^3.0.1" + istanbul-lib-report "^3.0.0" + istanbul-reports "^3.0.2" + rimraf "^3.0.0" + test-exclude "^6.0.0" + v8-to-istanbul "^8.0.0" + yargs "^16.2.0" + yargs-parser "^20.2.7" + cac@^6.7.2, cac@^6.7.3: version "6.7.3" resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.3.tgz#10410b8611677990cc2e3c8b576d471c1d71b768" @@ -15869,7 +15937,7 @@ convert-source-map@1.6.0: dependencies: safe-buffer "~5.1.1" -convert-source-map@1.7.0, convert-source-map@^1.1.0, convert-source-map@^1.3.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: +convert-source-map@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -15881,6 +15949,13 @@ convert-source-map@^0.3.3: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA= +convert-source-map@^1.1.0, convert-source-map@^1.3.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + convert-source-map@~1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" @@ -17882,7 +17957,7 @@ diff@3.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= -diff@3.5.0, diff@^3.0.0, diff@^3.1.0, diff@^3.2.0, diff@^3.4.0, diff@^3.5.0: +diff@3.5.0, diff@^3.0.0, diff@^3.2.0, diff@^3.4.0, diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== @@ -24843,7 +24918,7 @@ istanbul-instrumenter-loader@3.0.1: loader-utils "^1.1.0" schema-utils "^0.3.0" -istanbul-lib-coverage@3.0.0, istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: +istanbul-lib-coverage@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== @@ -24858,6 +24933,11 @@ istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1, istanbul-lib-coverage@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz#e8900b3ed6069759229cf30f7067388d148aeb5e" + integrity sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ== + istanbul-lib-hook@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" @@ -39750,54 +39830,25 @@ ts-log@^2.2.3: resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.3.tgz#4da5640fe25a9fb52642cd32391c886721318efb" integrity sha512-XvB+OdKSJ708Dmf9ore4Uf/q62AYDTzFcAdxc8KNML1mmAWywRFVt/dn1KYJH8Agt5UJNujfM3znU5PxgAzA2w== -ts-node@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-5.0.1.tgz#78e5d1cb3f704de1b641e43b76be2d4094f06f81" - integrity sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw== - dependencies: - arrify "^1.0.0" - chalk "^2.3.0" - diff "^3.1.0" - make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - yn "^2.0.0" - -ts-node@8.10.1: - version "8.10.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.1.tgz#77da0366ff8afbe733596361d2df9a60fc9c9bd3" - integrity sha512-bdNz1L4ekHiJul6SHtZWs1ujEKERJnHs4HxN7rjTyyVOFf3HaJ6sLqe6aPG62XTzAB/63pKRh5jTSWL0D7bsvw== +ts-node@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.2.1.tgz#4cc93bea0a7aba2179497e65bb08ddfc198b3ab5" + integrity sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw== dependencies: + "@cspotcode/source-map-support" "0.6.1" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" arg "^4.1.0" + create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - source-map-support "^0.5.17" yn "3.1.1" -ts-node@8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.3.0.tgz#e4059618411371924a1fb5f3b125915f324efb57" - integrity sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ== - dependencies: - arg "^4.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.6" - yn "^3.0.0" - -ts-node@8.5.4: - version "8.5.4" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" - integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== - dependencies: - arg "^4.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.6" - yn "^3.0.0" - -ts-node@9.1.1, ts-node@^9, ts-node@^9.1.1: +ts-node@^9: version "9.1.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== @@ -40128,6 +40179,15 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript-cached-transpile@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typescript-cached-transpile/-/typescript-cached-transpile-0.0.6.tgz#1d1f0620ebb29cf8d8c11e5353c2b4f43dfafc01" + integrity sha512-bfPc7YUW0PrVkQHU0xN0ANRuxdPgoYYXtZEW6PNkH5a97/AOM+kPPxSTMZbpWA3BG1do22JUkfC60KoCKJ9VZQ== + dependencies: + "@types/node" "^12.12.7" + fs-extra "^8.1.0" + tslib "^1.10.0" + typescript@4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" @@ -40932,6 +40992,15 @@ v8-compile-cache@2.0.3, v8-compile-cache@^2.0.2, v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== +v8-to-istanbul@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c" + integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + v8flags@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" @@ -43422,7 +43491,7 @@ yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.1, yargs-parser@^1 camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@20.2.4, yargs-parser@^20.2.2, yargs-parser@^20.2.3: +yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== @@ -43474,6 +43543,11 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.7: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" @@ -43782,16 +43856,11 @@ ylru@^1.2.0: resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ== -yn@3.1.1, yn@^3.0.0: +yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" - integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo= - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"