Allow downloading projects on GUI dev server (#9851)

- Fixes #9482
- Add URL rewriting logic to `npm run dev` in `app/gui2/` so that "download" actions work

# Important Notes
- ⚠️ `config.yaml` HAS BEEN REMOVED in favor of `config.json`.
- Most of the keys have been removed as they were only used by GUI1.
- This is a REQUIRED change, because the vite dev server does not seem to like importing yaml files when running `vite.config.ts`.
This commit is contained in:
somebody1234 2024-05-03 23:37:26 +10:00 committed by GitHub
parent 6d605a5926
commit 25d1007a9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 43 additions and 57 deletions

View File

@ -1,30 +0,0 @@
# The name of an object created in the global window scope. This object will contain functions
# to control the IDE, like the `main` function, and also the configuration object.
windowAppScopeName: 'enso'
# The configuration object nested inside of the `windowAppScopeName` object containing all
# startup configuration options. See usages of this variable to learn more about available
# options.
windowAppScopeConfigName: 'config'
# The configuration object nested inside of the `windowAppScopeName` object containing theming
# utilities and allowing for runtime theme modification.
windowAppScopeThemeName: 'theme'
# The URL to the JSON-RPC endpoint to the Project Manager.
# This MUST be kept in sync with the corresponding value in `app/gui/src/constants.rs`.
projectManagerEndpoint: 'ws://127.0.0.1:30535'
# The URL to the base path of the HTTP endpoints of the Project Manager.
projectManagerHttpEndpoint: 'http://127.0.0.1:30535'
# TODO [ao] add description here.
minimumSupportedVersion": '2.0.0-alpha.6'
# The minimum engine version supported by the application. The projects opened with the older versions
# will have the "Unsupported engine version" message displayed.
engineVersionSupported: '2023.1.1'
# The minimum language edition supported by the application. It will be displayed as edition user
# should put in their package.yaml file to have project compatible with the IDE.
languageEditionSupported: '2023.1.1'

View File

@ -30,7 +30,7 @@ const NAME = 'enso'
* `yargs` is a modules we explicitly want the default imports of.
* `node:process` is here because `process.on` does not exist on the namespace import. */
const DEFAULT_IMPORT_ONLY_MODULES =
'@vitejs\\u002Fplugin-react|node:process|chalk|string-length|yargs|yargs\\u002Fyargs|sharp|to-ico|connect|morgan|serve-static|tiny-invariant|clsx|create-servers|electron-is-dev|fast-glob|esbuild-plugin-.+|opener|tailwindcss.*|enso-assets.*|@modyfi\\u002Fvite-plugin-yaml|is-network-error|validator.+'
'@vitejs\\u002Fplugin-react|node:process|chalk|string-length|yargs|yargs\\u002Fyargs|sharp|to-ico|connect|morgan|serve-static|tiny-invariant|clsx|create-servers|electron-is-dev|fast-glob|esbuild-plugin-.+|opener|tailwindcss.*|enso-assets.*|@modyfi\\u002Fvite-plugin-yaml|is-network-error|validator.+|.*[.]json$'
const OUR_MODULES = 'enso-.*'
const RELATIVE_MODULES =
'bin\\u002Fproject-manager|bin\\u002Fserver|config\\u002Fparser|authentication|config|debug|detect|file-associations|index|ipc|log|naming|paths|preload|project-management|security|url-associations|#\\u002F.*'

View File

@ -13,14 +13,12 @@ import type * as vite from 'vite'
import createServer from 'create-servers'
import * as common from 'enso-common'
import GLOBAL_CONFIG from 'enso-common/src/config.json' assert { type: 'json' }
import * as contentConfig from 'enso-content-config'
import * as ydocServer from 'enso-gui2/ydoc-server'
import * as paths from '../paths'
// prettier-ignore
import GLOBAL_CONFIG from '../../../../../gui2/config.yaml' assert { type: 'yaml' }
const logger = contentConfig.logger
// =================

View File

@ -16,6 +16,7 @@ import * as portfinder from 'portfinder'
import * as common from 'enso-common'
import * as buildUtils from 'enso-common/src/buildUtils'
import GLOBAL_CONFIG from 'enso-common/src/config.json' assert { type: 'json' }
import * as contentConfig from 'enso-content-config'
import * as authentication from 'authentication'
@ -34,9 +35,6 @@ import * as security from 'security'
import * as server from 'bin/server'
import * as urlAssociations from 'url-associations'
// prettier-ignore
import GLOBAL_CONFIG from '../../../../gui2/config.yaml' assert { type: 'yaml' }
const logger = contentConfig.logger
if (process.env.ELECTRON_DEV_MODE === 'true' && process.env.NODE_MODULES_PATH != null) {

View File

@ -5,6 +5,7 @@
"main": "./src/index.js",
"exports": {
".": "./src/index.js",
"./src/config.json": "./src/config.json",
"./src/appConfig": "./src/appConfig.js",
"./src/buildUtils": "./src/buildUtils.js",
"./src/detect": "./src/detect.ts",

View File

@ -0,0 +1,4 @@
{
"projectManagerEndpoint": "ws://127.0.0.1:30535",
"projectManagerHttpEndpoint": "http://127.0.0.1:30535"
}

View File

@ -2,7 +2,7 @@
import * as fs from 'node:fs/promises'
import * as fsSync from 'node:fs'
import type * as http from 'node:http'
import * as http from 'node:http'
import * as os from 'node:os'
import * as path from 'node:path'
@ -10,6 +10,8 @@ import * as tar from 'tar'
import * as yaml from 'yaml'
import * as common from 'enso-common'
import GLOBAL_CONFIG from '../../common/src/config.json' assert { type: 'json' }
import * as projectManagement from './projectManagement'
// =================
@ -97,7 +99,37 @@ export default function projectManagerShimMiddleware(
) {
const requestUrl = request.url
const requestPath = requestUrl?.split('?')[0]?.split('#')[0]
if (request.method === 'POST') {
if (requestUrl != null && requestUrl.startsWith('/api/project-manager/')) {
const actualUrl = new URL(
requestUrl.replace(/^\/api\/project-manager/, GLOBAL_CONFIG.projectManagerHttpEndpoint)
)
request.pipe(
http.request(
// `...actualUrl` does NOT work because `URL` properties are not enumerable.
{
headers: request.headers,
host: actualUrl.host,
hostname: actualUrl.hostname,
method: request.method,
path: actualUrl.pathname,
port: actualUrl.port,
protocol: actualUrl.protocol,
},
actualResponse => {
response.writeHead(
// This is SAFE. The documentation says:
// Only valid for response obtained from ClientRequest.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
actualResponse.statusCode!,
actualResponse.statusMessage,
actualResponse.headers
)
actualResponse.pipe(response, { end: true })
}
),
{ end: true }
)
} else if (request.method === 'POST') {
switch (requestPath) {
case '/api/upload-file': {
const url = new URL(`https://example.com/${requestUrl}`)

View File

@ -5,5 +5,5 @@
"checkJs": false,
"skipLibCheck": false
},
"include": ["./src/"]
"include": ["./src/", "../common/src/config.json"]
}

View File

@ -20,23 +20,6 @@ declare module '*/build.json' {
export default BUILD_INFO
}
declare module '*/gui2/config.yaml' {
/** Content of the GUI config file. */
interface Config {
readonly windowAppScopeName: string
readonly windowAppScopeConfigName: string
readonly windowAppScopeThemeName: string
readonly projectManagerEndpoint: string
readonly projectManagerHttpEndpoint: string
readonly minimumSupportedVersion: string
readonly engineVersionSupported: string
readonly languageEditionSupported: string
}
const DATA: Config
export default DATA
}
declare module '@eslint/js' {
/** A set of configurations. */
export interface Config {