Skip to content

Commit 799bdc6

Browse files
authored
Prune ide-desktop package (#14069)
Closes #13501 - `ide-desktop/client` moved one directory up, to `app`. - Icons generator removed, app icons committed to the repository - `.ico` for Windows - `.icns` for Mac & Linux (Linux needs to be checked, but it should work according to [documentation](https://github.com/electron-userland/electron-builder/blob/d83658ad312a41fe0d15b400c5a89756f3d53f52/pages/icons.md) - `.svg` added as a “source” of the current icon, so we can adjust it in the future if needed. - MacOS Tahoe will use `.icon` format, but it is not yet supported in the `electron-builder`—we must wait before adding it as well. - Electron app CLI simplified and reduced - Removed all unused parameters and flags (I mean literally unused, no code to handle them) - Removed many parameters that seem not _useful_ and weren’t reported as used by anyone in the team. It includes performance-related Chrome flags and custom Chrome flags in general, window dimensions, and “inverted” flags such as `--engine`. Only `--no-engine` was used, so only it stayed. - Removed a bunch of complex code to define config options, load them from JSON, merge them together, type them with Typescript. A much simpler system is implemented, where we still have typed nested config objects, but parsing and validation is done with Zod, and we can flatten/unflatten it into a simple key-value list. `lib/js/runner` package was removed. - Removed duplication of config options in `project-view`. Before, we defined the same options twice—once in `client`, then in `project-view` as URL parameters. We also had duplication of `lib/js/runner` code inside `project-view` to parse this configuration from JSON. - [`commander.js`](https://github.com/tj/commander.js) used instead of `yargs` for mostly technical reasons—configuring `yargs` to work well with the new logging system was a very confusing experience. `commander.js` is simpler and has a slightly smaller bundle size, but the main reason it was simpler to integrate. - `vibrancy` feature is removed. - New application-wide logging system. - Overwriting most `console.*` methods—it does not require changing existing code, and also does not require remembering to import logging stuff everywhere. - DevTools console messages are forwarded to the stdout of the Electron app. Keep in mind that some messages will not appear there—for example, failed network requests. But most of the other stuff will be forwarded. - In the Electron app, `console.*` methods are now used for logging. It gives unification with the GUI code. Some complex mechanics like grouped messages and timing recordings were removed—I didn’t find enough code to justify supporting them. - As before, all stdout messages (including those forwarded from DevTools) are also saved to the local log file in the filesystem. On Mac, it is `/Library/Logs/enso`. According to Electron documentation, it would be the “userData” directory on Windows and Linux. e.g. @farmaazon found his logs somewhere inside `~/.config`. - Terminal colors support was removed—it only mangles the log file and complicates the implementation. - Removed duplication of code between `globals.d.ts` and `env.d.ts` files.
1 parent 8a8dfe0 commit 799bdc6

File tree

108 files changed

+1335
-5272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+1335
-5272
lines changed

.bazelignore

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,7 @@
22
node_modules
33
app/gui/node_modules
44
app/common/node_modules
5-
app/ide-desktop/client/node_modules
6-
app/ide-desktop/icons/node_modules
7-
app/ide-desktop/lib/assets/node_modules
8-
app/ide-desktop/lib/client/node_modules
9-
app/ide-desktop/lib/common/node_modules
10-
app/ide-desktop/lib/content-config/node_modules
11-
app/ide-desktop/lib/dashboard/node_modules
12-
app/ide-desktop/lib/esbuild-plugin-copy-directories/node_modules
13-
app/ide-desktop/lib/icons/node_modules
14-
app/ide-desktop/lib/ts-plugin-namespace-auto-import/node_modules
15-
app/ide-desktop/node_modules
5+
app/electron-client/node_modules
166
app/lang-markdown/node_modules
177
app/lezer-markdown/node_modules
188
app/project-manager-shim/node_modules
@@ -23,7 +13,6 @@ app/ydoc-server-nodejs/node_modules
2313
app/ydoc-server-polyglot/node_modules
2414
app/ydoc-shared/node_modules
2515
app/ydoc-shared/parser-codegen/node_modules
26-
lib/js/runner/node_modules
2716

2817
#
2918
.bloop

.github/workflows/gui-checks.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
run: pnpm install --frozen-lockfile
5050

5151
- uses: actions/cache/restore@v4
52+
if: "${{ !(contains(github.event.pull_request.labels.*.name, 'CI: Clean build required')) }}"
5253
name: Download cache
5354
id: cache
5455
with:

.github/workflows/ide-packaging-optional.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ jobs:
216216
name: ide-macos
217217
path: dist/ide/enso-*.dmg
218218
- name: Prepare Package Tests
219-
run: 'mkdir -p app/ide-desktop/client/playwright/.auth && touch app/ide-desktop/client/playwright/.auth/user.json && chmod 600 app/ide-desktop/client/playwright/.auth/user.json && echo "{\"user\": \"$ENSO_TEST_USER\",\"password\":\"$ENSO_TEST_USER_PASSWORD\"}" > app/ide-desktop/client/playwright/.auth/user.json'
219+
run: 'mkdir -p app/electron-client/playwright/.auth && touch app/electron-client/playwright/.auth/user.json && chmod 600 app/electron-client/playwright/.auth/user.json && echo "{\"user\": \"$ENSO_TEST_USER\",\"password\":\"$ENSO_TEST_USER_PASSWORD\"}" > app/electron-client/playwright/.auth/user.json'
220220
shell: bash
221221
env:
222222
ENSO_TEST_USER: ${{ secrets.ENSO_CLOUD_TEST_ACCOUNT_USERNAME }}
@@ -233,7 +233,7 @@ jobs:
233233
with:
234234
compression-level: 0
235235
name: test-traces-macos-amd64
236-
path: app/ide-desktop/client/test-traces
236+
path: app/electron-client/test-traces
237237
- if: always()
238238
name: Remove Credentials File
239239
run: rm -f $HOME/.enso/credentials

.github/workflows/ide-packaging.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ jobs:
344344
name: ide-linux
345345
path: dist/ide/enso-*.AppImage
346346
- name: Prepare Package Tests
347-
run: 'mkdir -p app/ide-desktop/client/playwright/.auth && touch app/ide-desktop/client/playwright/.auth/user.json && chmod 600 app/ide-desktop/client/playwright/.auth/user.json && echo "{\"user\": \"$ENSO_TEST_USER\",\"password\":\"$ENSO_TEST_USER_PASSWORD\"}" > app/ide-desktop/client/playwright/.auth/user.json'
347+
run: 'mkdir -p app/electron-client/playwright/.auth && touch app/electron-client/playwright/.auth/user.json && chmod 600 app/electron-client/playwright/.auth/user.json && echo "{\"user\": \"$ENSO_TEST_USER\",\"password\":\"$ENSO_TEST_USER_PASSWORD\"}" > app/electron-client/playwright/.auth/user.json'
348348
shell: bash
349349
env:
350350
ENSO_TEST_USER: ${{ secrets.ENSO_CLOUD_TEST_ACCOUNT_USERNAME }}
@@ -361,7 +361,7 @@ jobs:
361361
with:
362362
compression-level: 0
363363
name: test-traces-linux-amd64
364-
path: app/ide-desktop/client/test-traces
364+
path: app/electron-client/test-traces
365365
- if: always()
366366
name: Remove Credentials File
367367
run: rm -f $HOME/.enso/credentials
@@ -449,7 +449,7 @@ jobs:
449449
name: ide-windows
450450
path: dist/ide/enso-*.exe
451451
- name: Prepare Package Tests
452-
run: 'mkdir -p app/ide-desktop/client/playwright/.auth && touch app/ide-desktop/client/playwright/.auth/user.json && chmod 600 app/ide-desktop/client/playwright/.auth/user.json && echo "{\"user\": \"$ENSO_TEST_USER\",\"password\":\"$ENSO_TEST_USER_PASSWORD\"}" > app/ide-desktop/client/playwright/.auth/user.json'
452+
run: 'mkdir -p app/electron-client/playwright/.auth && touch app/electron-client/playwright/.auth/user.json && chmod 600 app/electron-client/playwright/.auth/user.json && echo "{\"user\": \"$ENSO_TEST_USER\",\"password\":\"$ENSO_TEST_USER_PASSWORD\"}" > app/electron-client/playwright/.auth/user.json'
453453
shell: bash
454454
env:
455455
ENSO_TEST_USER: ${{ secrets.ENSO_CLOUD_TEST_ACCOUNT_USERNAME }}
@@ -466,7 +466,7 @@ jobs:
466466
with:
467467
compression-level: 0
468468
name: test-traces-windows-amd64
469-
path: app/ide-desktop/client/test-traces
469+
path: app/electron-client/test-traces
470470
- if: always()
471471
name: Remove Credentials File
472472
run: rm -f $HOME/.enso/credentials

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [When connecting to port a value with additional type, a necessary type cast
1414
is included][14028]
1515
- [Function docs in autocomplete in table expressions][14059]
16+
- [Many CLI arguments removed][14069]
1617

1718
[13685]: https://github.com/enso-org/enso/pull/13685
1819
[13658]: https://github.com/enso-org/enso/pull/13658
@@ -24,6 +25,7 @@
2425
[14028]: https://github.com/enso-org/enso/pull/14028
2526
[13976]: https://github.com/enso-org/enso/pull/13976
2627
[14059]: https://github.com/enso-org/enso/pull/14059
28+
[14069]: https://github.com/enso-org/enso/pull/14069
2729

2830
#### Enso Standard Library
2931

app/common/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
"exports": {
66
".": {
77
"source": "./src/index.ts",
8-
"types": "./dist/index.d.ts",
8+
"types": "./src/index.ts",
99
"import": "./dist/index.js"
1010
},
1111
"./src/config.json": "./src/config.json",
1212
"./src/*": {
1313
"source": "./src/*.ts",
14-
"types": "./dist/*.d.ts",
14+
"types": "./src/*.ts",
1515
"import": "./dist/*.js"
1616
}
1717
},
@@ -32,7 +32,6 @@
3232
"@tanstack/vue-query": "5.59.20",
3333
"@types/node": "catalog:",
3434
"is-network-error": "^1.1.0",
35-
"lib0": "^0.2.99",
3635
"vue": "*"
3736
},
3837
"devDependencies": {

app/common/src/options.ts

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/** @file Shared application options schema and helpers. */
2+
3+
import { z } from 'zod'
4+
5+
const DEFAULT_PROFILING_TIME = 120
6+
const DEFAULT_PORT = 8080
7+
8+
/** Schema for app-wide configuration options. */
9+
export const OptionsSchema = z.object({
10+
version: z.boolean().default(false),
11+
displayWindow: z.boolean().default(true),
12+
useServer: z.boolean().default(true),
13+
engineEnabled: z.boolean().default(true),
14+
useJvm: z.boolean().default(false),
15+
startup: z
16+
.object({
17+
project: z.string().default(''),
18+
displayedProjectName: z.string().default(''),
19+
})
20+
.default({}),
21+
authentication: z
22+
.object({
23+
enabled: z.boolean().default(true),
24+
email: z.string().default(''),
25+
})
26+
.default({}),
27+
server: z
28+
.object({
29+
port: z.number().int().default(DEFAULT_PORT),
30+
})
31+
.default({}),
32+
engine: z
33+
.object({
34+
projectManagerPath: z.string().default(''),
35+
projectManagerUrl: z.string().default(''),
36+
ydocUrl: z.string().default(''),
37+
})
38+
.default({}),
39+
debug: z
40+
.object({
41+
info: z.boolean().default(false),
42+
verbose: z.boolean().default(false),
43+
devTools: z.boolean().default(false),
44+
profile: z.boolean().default(false),
45+
profileTime: z.number().int().default(DEFAULT_PROFILING_TIME),
46+
})
47+
.default({}),
48+
})
49+
50+
/** Global configuration of Enso Studio, parsed from CLI arguments and passed to web application via URL params. */
51+
export type Options = z.infer<typeof OptionsSchema>
52+
53+
/** Default values for all configuration options. */
54+
export function defaultOptions(): Options {
55+
return OptionsSchema.parse({})
56+
}
57+
58+
/**
59+
* Dotted keys which should be synced to the web application via URL params.
60+
* Other options are only used by Electron and not passed to the web application.
61+
*/
62+
export const PASS_TO_WEB: ReadonlySet<string> = new Set([
63+
'startup.project',
64+
'startup.displayedProjectName',
65+
'authentication.enabled',
66+
'authentication.email',
67+
'engine.projectManagerUrl',
68+
'engine.ydocUrl',
69+
])
70+
71+
/** Possible values for options. */
72+
export type OptionValue = string | number | boolean
73+
74+
const phantomKey = Symbol('flattened')
75+
type Flat<T> = Record<string, OptionValue> & { readonly [phantomKey]?: T }
76+
77+
/** Flatten a nested object into a dotted-key record. */
78+
export function flattenObject<T extends object>(obj: T, prefix = ''): Flat<T> {
79+
const out: Flat<T> = {}
80+
if (obj != null) {
81+
for (const [k, v] of Object.entries(obj)) {
82+
const key = prefix ? `${prefix}.${k}` : k
83+
if (v != null && typeof v === 'object' && !Array.isArray(v)) {
84+
Object.assign(out, flattenObject(v, key))
85+
} else {
86+
out[key] = v
87+
}
88+
}
89+
}
90+
return out
91+
}
92+
93+
/** Turn a flat dotted-record into a nested object. */
94+
export function unflattenObject<T extends object>(flat: Flat<T>): T {
95+
const out: any = {}
96+
for (const [k, v] of Object.entries(flat)) {
97+
const pathSegments = k.split('.')
98+
let cur = out
99+
for (const segment of pathSegments.slice(0, -1)) {
100+
cur[segment] ??= {}
101+
cur = cur[segment]
102+
}
103+
const last = pathSegments[pathSegments.length - 1]!
104+
cur[last] = v
105+
}
106+
return out as T
107+
}
108+
109+
/** Build URLSearchParams for non-default pass-to-web options. */
110+
export function buildWebAppURLSearchParamsFromArgs(args: Options): URLSearchParams {
111+
const params = new URLSearchParams()
112+
const entries = collectWebAppOptionsFromArgs(args)
113+
Object.entries(entries).forEach(([key, val]) => params.append(key, String(val)))
114+
return params
115+
}
116+
117+
/** Collect non-default values of pass-to-web options from parsed args. */
118+
function collectWebAppOptionsFromArgs(options: Options): Record<string, string | number | boolean> {
119+
const result: Record<string, string | number | boolean> = {}
120+
const defaults = defaultOptions()
121+
const flatDefaults = flattenObject(defaults)
122+
const flatOptions = flattenObject(options)
123+
for (const key of PASS_TO_WEB) {
124+
const value = flatOptions[key]
125+
if (value == null)
126+
throw new Error(`Option ${key} not found, but needs to be passed to web application`)
127+
const def = flatDefaults[key]
128+
if (value != null && JSON.stringify(value) !== JSON.stringify(def)) {
129+
result[key] = value
130+
}
131+
}
132+
return result
133+
}
134+
135+
/** Parse pass-to-web options from URLSearchParams. For missing values, defaults are used. */
136+
export function parseWebAppOptionsFromSearchParams(params: URLSearchParams): Options {
137+
const out = flattenObject(defaultOptions())
138+
for (const key of PASS_TO_WEB) {
139+
const value = params.get(key)
140+
if (value == null) continue
141+
const def = out[key]
142+
switch (typeof def) {
143+
case 'boolean': {
144+
const b = coerceBoolean(value)
145+
if (b != null) {
146+
out[key] = b
147+
} else {
148+
console.warn(`Invalid boolean value for option ${key}: ${value}, using default ${def}.`)
149+
}
150+
break
151+
}
152+
case 'number': {
153+
const n = Number(value)
154+
if (!Number.isNaN(n)) {
155+
out[key] = n
156+
} else {
157+
console.warn(`Invalid number value for option ${key}: ${value}, using default ${def}.`)
158+
}
159+
break
160+
}
161+
case 'string': {
162+
out[key] = value
163+
break
164+
}
165+
default:
166+
throw new Error(`Invalid option type for option ${key}: ${typeof def}.`)
167+
}
168+
}
169+
return unflattenObject<Options>(out)
170+
}
171+
172+
/**
173+
* Coerce a string to a boolean.
174+
*
175+
* true, 1, yes, enabled → true
176+
* false, 0, no, disabled → false
177+
* anything else → undefined
178+
*/
179+
function coerceBoolean(v: string): boolean | undefined {
180+
switch (v.toLowerCase()) {
181+
case 'true':
182+
case '1':
183+
case 'yes':
184+
case 'enabled':
185+
return true
186+
case 'false':
187+
case '0':
188+
case 'no':
189+
case 'disabled':
190+
return false
191+
default:
192+
return undefined
193+
}
194+
}

app/common/src/services/Backend.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,6 @@ export default abstract class Backend {
17501750

17511751
/** Create a {@link LocalBackend}. */
17521752
constructor(
1753-
private readonly logger: Logger,
17541753
protected getText: GetText,
17551754
private readonly client: HttpClient,
17561755
) {}
@@ -1773,7 +1772,7 @@ export default abstract class Backend {
17731772
...replacements: Replacements[K]
17741773
): Promise<never> {
17751774
if (textId instanceof NetworkError) {
1776-
this.logger.error(textId.message)
1775+
console.error(textId.message)
17771776

17781777
throw textId
17791778
}
@@ -1784,7 +1783,7 @@ export default abstract class Backend {
17841783
: await ((): Promise<Error> => response.json())()
17851784

17861785
const message = `${this.getText(textId, ...replacements)}: ${error.message}.`
1787-
this.logger.error(message)
1786+
console.error(message)
17881787

17891788
const status = response?.status
17901789

File renamed without changes.

app/ide-desktop/client/BUILD.bazel renamed to app/electron-client/BUILD.bazel

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ ts_config(
99
name = "tsconfig",
1010
src = "tsconfig.json",
1111
visibility = [":__subpackages__"],
12+
deps = ["//:tsconfig"],
1213
)
1314

1415
ts_project(
@@ -18,13 +19,13 @@ ts_project(
1819
declaration = True,
1920
resolve_json_module = True,
2021
source_map = True,
21-
tsconfig = "//app/ide-desktop/lib/project-manager-shim:tsconfig",
22+
tsconfig = "//app/project-manager-shim:tsconfig",
2223
validate = select({
2324
"@platforms//os:windows": False,
2425
"//conditions:default": True,
2526
}),
2627
visibility = ["//visibility:public"],
27-
deps = ["//app/ide-desktop:tsconfig"] + npm_link_targets(),
28+
deps = ["//:tsconfig"] + npm_link_targets(),
2829
)
2930

3031
js_library(

0 commit comments

Comments
 (0)