diff --git a/Cargo.lock b/Cargo.lock index 552c9fb9b85..187cc016e90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1943,6 +1943,7 @@ dependencies = [ "enso-build", "enso-build-base", "enso-formatter", + "ensogl-pack", "futures", "futures-util", "glob", diff --git a/app/ide-desktop/lib/client/src/file-associations.ts b/app/ide-desktop/lib/client/src/file-associations.ts index 038f2ecfd59..b73e229653c 100644 --- a/app/ide-desktop/lib/client/src/file-associations.ts +++ b/app/ide-desktop/lib/client/src/file-associations.ts @@ -111,7 +111,6 @@ export function onFileOpened(event: Event, path: string): string | null { if (!electron.app.isReady() && CLIENT_ARGUMENTS.length === 0) { event.preventDefault() logger.log(`Opening file '${path}'.`) - // eslint-disable-next-line no-restricted-syntax return handleOpenFile(path) } else { // Another copy of the application needs to be started, as the first one is diff --git a/app/ide-desktop/lib/content-config/src/index.ts b/app/ide-desktop/lib/content-config/src/index.ts index c840f743d99..b27f11f2658 100644 --- a/app/ide-desktop/lib/content-config/src/index.ts +++ b/app/ide-desktop/lib/content-config/src/index.ts @@ -2,7 +2,7 @@ import * as semver from 'semver' -import * as linkedDist from '../../../../../target/ensogl-pack/linked-dist/index' +import * as linkedDist from '../../../../../target/ensogl-pack/linked-dist' import BUILD_INFO from '../../../build.json' assert { type: 'json' } // Aliases with the same name as the original. diff --git a/app/ide-desktop/lib/content/src/index.ts b/app/ide-desktop/lib/content/src/index.ts index ee53fbefdf3..602e0714649 100644 --- a/app/ide-desktop/lib/content/src/index.ts +++ b/app/ide-desktop/lib/content/src/index.ts @@ -7,7 +7,7 @@ import * as semver from 'semver' import * as authentication from 'enso-authentication' import * as contentConfig from 'enso-content-config' -import * as app from '../../../../../target/ensogl-pack/linked-dist/index' +import * as app from '../../../../../target/ensogl-pack/linked-dist' import GLOBAL_CONFIG from '../../../../gui/config.yaml' assert { type: 'yaml' } const logger = app.log.logger diff --git a/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/dashboard.tsx b/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/dashboard.tsx index 830dc9e2158..68467555ba9 100644 --- a/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/dashboard.tsx +++ b/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/dashboard.tsx @@ -476,8 +476,7 @@ function Dashboard(props: DashboardProps) { } }} > - {fileInfo.fileIcon(fileInfo.fileExtension(file.title))}{' '} - {file.title} + {fileInfo.fileIcon()} {file.title} ), } diff --git a/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/uploadFileModal.tsx b/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/uploadFileModal.tsx index 77e87a519f0..f0a1bf40661 100644 --- a/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/uploadFileModal.tsx +++ b/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/components/uploadFileModal.tsx @@ -110,13 +110,7 @@ function UploadFileModal(props: UploadFileModalProps) { {file ? fileInfo.toReadableSize(file.size) : '\u00a0'} -
- {file ? ( - fileInfo.fileIcon(fileInfo.fileExtension(file.name)) - ) : ( - <> - )} -
+
{file && fileInfo.fileIcon()}
diff --git a/app/ide-desktop/lib/dashboard/src/authentication/src/fileInfo.ts b/app/ide-desktop/lib/dashboard/src/authentication/src/fileInfo.ts index 2d21ab75d26..5abe4fee09f 100644 --- a/app/ide-desktop/lib/dashboard/src/authentication/src/fileInfo.ts +++ b/app/ide-desktop/lib/dashboard/src/authentication/src/fileInfo.ts @@ -10,8 +10,8 @@ export function fileExtension(fileName: string) { return fileName.match(/\.(.+?)$/)?.[1] ?? '' } -/** Return the appropriate icon for a specific file extension. */ -export function fileIcon(_extension: string) { +/** Returns the appropriate icon for a specific file extension. */ +export function fileIcon() { return svg.FILE_ICON } diff --git a/app/ide-desktop/lib/types/globals.d.ts b/app/ide-desktop/lib/types/globals.d.ts index 53caf383a26..62a17d97865 100644 --- a/app/ide-desktop/lib/types/globals.d.ts +++ b/app/ide-desktop/lib/types/globals.d.ts @@ -3,6 +3,9 @@ * monkeypatching on `window` and generated code. * * This file MUST `export {}` for the globals to be visible to other files. */ +// This file is being imported for its types. +// eslint-disable-next-line no-restricted-syntax +import * as buildJson from './build.json' assert { type: 'json' } // ============= // === Types === @@ -18,14 +21,6 @@ interface Enso { main: (inputConfig?: StringConfig) => Promise } -/** Build information injected by the build script. */ -interface BuildInfo { - commit: string - version: string - engineVersion: string - name: string -} - // ========================== // === Authentication API === // ========================== @@ -74,7 +69,7 @@ declare global { // These are used in other files (because they're globals) /* eslint-disable @typescript-eslint/naming-convention */ const BUNDLED_ENGINE_VERSION: string - const BUILD_INFO: BuildInfo + const BUILD_INFO: buildJson.BuildInfo const PROJECT_MANAGER_IN_BUNDLE_PATH: string const IS_DEV_MODE: boolean // This will be `undefined` when it is not defined by esbuild. @@ -82,5 +77,3 @@ declare global { const REDIRECT_OVERRIDE: string | undefined /* eslint-disable @typescript-eslint/naming-convention */ } - -export {} diff --git a/app/ide-desktop/lib/types/modules.d.ts b/app/ide-desktop/lib/types/modules.d.ts index 1564bae805b..50d52e8cdc8 100644 --- a/app/ide-desktop/lib/types/modules.d.ts +++ b/app/ide-desktop/lib/types/modules.d.ts @@ -6,6 +6,20 @@ // === Module declarations === // =========================== +// Required because this is a build artifact, which does not exist on a clean repository. +declare module '*/build.json' { + /** Build metadata generated by the build CLI. */ + export interface BuildInfo { + commit: string + version: string + engineVersion: string + name: string + } + + const BUILD_INFO: BuildInfo + export default BUILD_INFO +} + declare module '*/gui/config.yaml' { /** Content of the GUI config file. */ interface Config { @@ -67,7 +81,7 @@ declare module 'create-servers' { /** Configuration options for `create-servers`. */ interface CreateServersOptions { http: number - handler: http.RequestListener + handler: http.RequestListener } /** An error passed to a callback when a HTTP request fails. */ diff --git a/app/ide-desktop/lib/types/tsconfig.json b/app/ide-desktop/lib/types/tsconfig.json new file mode 100644 index 00000000000..50af4660a58 --- /dev/null +++ b/app/ide-desktop/lib/types/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "skipLibCheck": false + }, + "extends": "../../tsconfig.json" +} diff --git a/app/ide-desktop/package.json b/app/ide-desktop/package.json index f9a45a0a4fe..82fe8f51056 100644 --- a/app/ide-desktop/package.json +++ b/app/ide-desktop/package.json @@ -36,6 +36,6 @@ "watch": "npm run watch --workspace enso-content", "watch-dashboard": "npm run watch --workspace enso-dashboard", "build-dashboard": "npm run build --workspace enso-dashboard", - "typecheck": "npm run typecheck --workspace enso && npm run typecheck --workspace enso-content && npm run typecheck --workspace enso-dashboard && npm run typecheck --workspace enso-authentication" + "typecheck": "npx tsc -p lib/types/tsconfig.json && npm run typecheck --workspace enso && npm run typecheck --workspace enso-content && npm run typecheck --workspace enso-dashboard && npm run typecheck --workspace enso-authentication" } } diff --git a/app/ide-desktop/tsconfig.json b/app/ide-desktop/tsconfig.json index 05c497e8c6d..cf3cc70c0c4 100644 --- a/app/ide-desktop/tsconfig.json +++ b/app/ide-desktop/tsconfig.json @@ -6,6 +6,7 @@ "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "node", + "noEmit": true, "allowJs": true, "checkJs": true, "strict": true, diff --git a/build/ci_utils/src/fs.rs b/build/ci_utils/src/fs.rs index 12393462e85..10d71460476 100644 --- a/build/ci_utils/src/fs.rs +++ b/build/ci_utils/src/fs.rs @@ -128,7 +128,7 @@ pub fn symlink_auto(src: impl AsRef, dst: impl AsRef) -> Result { symlink::symlink_auto(&src, &dst).anyhow_err() } -/// Remove a symlink if it exists. +/// Remove a symlink to a directory if it exists. #[context("Failed to remove symlink {}", path.as_ref().display())] pub fn remove_symlink_dir_if_exists(path: impl AsRef) -> Result { let result = symlink::remove_symlink_dir(&path); @@ -138,6 +138,12 @@ pub fn remove_symlink_dir_if_exists(path: impl AsRef) -> Result { } } +/// Create a symlink to a directory, or remove and recreate it if it already exists. +pub fn create_or_update_symlink_dir(src: impl AsRef, dst: impl AsRef) -> Result { + remove_symlink_dir_if_exists(&dst)?; + symlink_auto(&src, &dst) +} + /// `fs_extra`'s error type is not friendly to `anyhow`, so we need to convert it manually. /// /// Otherwise, we get just the message to look into the error kind, but the kind information is diff --git a/build/cli/Cargo.toml b/build/cli/Cargo.toml index 8e0c4025ed3..27e4167e306 100644 --- a/build/cli/Cargo.toml +++ b/build/cli/Cargo.toml @@ -13,6 +13,7 @@ derivative = { workspace = true } enso-build-base = { path = "../base" } enso-build = { path = "../build" } enso-formatter = { path = "../enso-formatter" } +ensogl-pack = { path = "../../lib/rust/ensogl/pack" } futures = { workspace = true } futures-util = "0.3.17" glob = "0.3.0" diff --git a/build/cli/src/lib.rs b/build/cli/src/lib.rs index 7ab115122e0..f07aae61050 100644 --- a/build/cli/src/lib.rs +++ b/build/cli/src/lib.rs @@ -86,6 +86,8 @@ use ide_ci::programs::git; use ide_ci::programs::git::clean; use ide_ci::programs::rustc; use ide_ci::programs::Cargo; +use ide_ci::programs::Npm; +use ide_ci::programs::Npx; use std::time::Duration; use tempfile::tempdir; use tokio::process::Child; @@ -834,7 +836,12 @@ pub async fn main_internal(config: Option) -> Result .run_ok() .await?; + ensogl_pack::build_ts_sources_only().await?; prettier::check(&ctx.repo_root).await?; + let js_modules_root = ctx.repo_root.join("app/ide-desktop"); + Npm.cmd()?.current_dir(&js_modules_root).args(["install"]).run_ok().await?; + Npm.cmd()?.current_dir(&js_modules_root).args(["run", "typecheck"]).run_ok().await?; + Npx.cmd()?.current_dir(&js_modules_root).args(["eslint", "."]).run_ok().await?; } Target::Fmt => { let prettier = prettier::write(&ctx.repo_root); diff --git a/lib/rust/ensogl/pack/src/lib.rs b/lib/rust/ensogl/pack/src/lib.rs index 5c11558b56a..7a98dd09bc0 100644 --- a/lib/rust/ensogl/pack/src/lib.rs +++ b/lib/rust/ensogl/pack/src/lib.rs @@ -353,7 +353,7 @@ fn check_if_ts_needs_rebuild(paths: &Paths) -> Result { } /// Compile TypeScript sources of this crate in case they were not compiled yet. -async fn compile_this_crate_ts_sources(paths: &Paths) -> Result<()> { +pub async fn compile_this_crate_ts_sources(paths: &Paths) -> Result<()> { println!("compile_this_crate_ts_sources"); if check_if_ts_needs_rebuild(paths)? { info!("EnsoGL Pack TypeScript sources changed, recompiling."); @@ -447,6 +447,16 @@ async fn extract_assets(paths: &Paths) -> Result<()> { .await } +/// Just builds the TypeScript sources, and creates (or recreates) the symlink to `linked_dist`. +pub async fn build_ts_sources_only() -> Result { + let paths = Paths::new().await?; + compile_this_crate_ts_sources(&paths).await?; + ide_ci::fs::create_or_update_symlink_dir( + &paths.target.ensogl_pack.dist, + &paths.target.ensogl_pack.linked_dist, + ) +} + /// Wrapper over `wasm-pack build` command. /// /// # Arguments @@ -464,6 +474,8 @@ pub async fn build( assets::build(&paths).await?; let out_dir = Path::new(&outputs.out_dir); ide_ci::fs::copy(&paths.target.ensogl_pack.dist, out_dir)?; - ide_ci::fs::remove_symlink_dir_if_exists(&paths.target.ensogl_pack.linked_dist)?; - ide_ci::fs::symlink_auto(&paths.target.ensogl_pack.dist, &paths.target.ensogl_pack.linked_dist) + ide_ci::fs::create_or_update_symlink_dir( + &paths.target.ensogl_pack.dist, + &paths.target.ensogl_pack.linked_dist, + ) }