Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb144ae472 | ||
|
|
f3571abeaf | ||
|
|
b87b7aac7d | ||
|
|
ae172000a6 | ||
|
|
ffd647d152 | ||
|
|
4142d084f6 | ||
|
|
b7a20d9d41 | ||
|
|
b68711ef88 | ||
|
|
7b546c567c | ||
|
|
49f22f048f | ||
|
|
4472c2852e | ||
|
|
5d940b57ef | ||
|
|
bc7e1faa1c | ||
|
|
557cea3f48 | ||
|
|
4fb6302c67 | ||
|
|
59decd17e2 | ||
|
|
52fadcd617 | ||
|
|
8a5592f92b | ||
|
|
79183d6417 | ||
|
|
89243371fa | ||
|
|
4a9b430702 | ||
|
|
ac176935f5 | ||
|
|
abec9def07 | ||
|
|
b71ad797a3 | ||
|
|
ec34ac1124 | ||
|
|
840adf9429 | ||
|
|
5eff3a0488 | ||
|
|
5abf8ff216 | ||
|
|
e7218850ba | ||
|
|
adc2089887 | ||
|
|
4ac1425f76 | ||
|
|
a721e82a4f | ||
|
|
98845e6cae | ||
|
|
19645248ab | ||
|
|
255c51c8a0 | ||
|
|
bbf3490e9c |
32
.github/actions/force-ipv4/README.md
vendored
Normal file
32
.github/actions/force-ipv4/README.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# force-ipv4
|
||||
|
||||
## Overview
|
||||
|
||||
This GitHub action enforces IPv4 for all outgoing network requests. It addresses connectivity issues encountered in GitHub runners, where IPv6 requests may lead to timeouts due to the lack of IPv6 support [1] [2].
|
||||
|
||||
## Background
|
||||
|
||||
Some applications attempt network connections over IPv6.
|
||||
Such as requests made by Node's `fetch` API causes `UND_ERR_CONNECT_TIMEOUT` [3] [4] and similar issues [5].
|
||||
This happens when the software cannot handle this such as by using Happy Eyeballs [6] [7].
|
||||
|
||||
## Usage
|
||||
|
||||
To use this action in your GitHub workflow, add the following step before any job that requires network access:
|
||||
|
||||
```yaml
|
||||
- name: Enforce IPv4 Connectivity
|
||||
uses: ./.github/actions/force-ipv4
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
This action is a workaround addressing specific IPv6-related connectivity issues on GitHub runners and may not be necessary if GitHub's infrastructure evolves to fully support IPv6 in the future.
|
||||
|
||||
[1]: https://archive.ph/2024.03.28-185829/https://github.com/actions/runner/issues/3138 "Actions Runner fails on IPv6 only host · Issue #3138 · actions/runner · GitHub | github.com"
|
||||
[2]: https://archive.ph/2024.03.28-185838/https://github.com/actions/runner-images/issues/668 "IPv6 on GitHub-hosted runners · Issue #668 · actions/runner-images · GitHub | github.com"
|
||||
[3]: https://archive.ph/2024.03.28-185847/https://github.com/actions/runner/issues/3213 "GitHub runner cannot send `fetch` with `node`, failing with IPv6 DNS error `UND_ERR_CONNECT_TIMEOUT` · Issue #3213 · actions/runner · GitHub | github.com"
|
||||
[4]: https://archive.ph/2024.03.28-185853/https://github.com/actions/runner-images/issues/9540 "Cannot send outbound requests using node fetch, failing with IPv6 DNS error UND_ERR_CONNECT_TIMEOUT · Issue #9540 · actions/runner-images · GitHub | github.com"
|
||||
[5]: https://archive.today/2024.03.30-113315/https://github.com/nodejs/node/issues/40537 "\"localhost\" favours IPv6 in node v17, used to favour IPv4 · Issue #40537 · nodejs/node · GitHub"
|
||||
[6]: https://archive.ph/2024.03.28-185900/https://github.com/nodejs/node/issues/41625 "Happy Eyeballs support (address IPv6 issues in Node 17) · Issue #41625 · nodejs/node · GitHub | github.com"
|
||||
[7]: https://archive.ph/2024.03.28-185910/https://github.com/nodejs/undici/issues/1531 "fetch times out in under 5 seconds · Issue #1531 · nodejs/undici · GitHub | github.com"
|
||||
12
.github/actions/force-ipv4/action.yml
vendored
Normal file
12
.github/actions/force-ipv4/action.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
inputs:
|
||||
project-root:
|
||||
required: false
|
||||
default: '.'
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
-
|
||||
name: Run prefer IPv4 script
|
||||
shell: bash
|
||||
run: ./.github/actions/force-ipv4/force-ipv4.sh
|
||||
working-directory: ${{ inputs.project-root }}
|
||||
80
.github/actions/force-ipv4/force-ipv4.sh
vendored
Executable file
80
.github/actions/force-ipv4/force-ipv4.sh
vendored
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
main() {
|
||||
if is_linux; then
|
||||
echo 'Configuring Linux...'
|
||||
|
||||
configure_warp_with_doh_and_ipv6_exclusion_on_linux # [WORKS] Resolves the issue when run independently on GitHub runners lacking IPv6 support.
|
||||
prefer_ipv4_on_linux # [DOES NOT WORK] It does not resolve the issue when run independently on GitHub runners without IPv6 support.
|
||||
|
||||
# Considered alternatives:
|
||||
# - `sysctl` commands, and direct changes to `/proc/sys/net/` and `/etc/sysctl.conf` led to silent
|
||||
# Node 18 exits (code: 13) when using `fetch`.
|
||||
elif is_macos; then
|
||||
echo 'Configuring macOS...'
|
||||
|
||||
configure_warp_with_doh_and_ipv6_exclusion_on_macos # [WORKS] Resolves the issue when run independently on GitHub runners lacking IPv6 support.
|
||||
disable_ipv6_on_macos # [WORKS INCONSISTENTLY] Resolves the issue inconsistently when run independently on GitHub runners without IPv6 support.
|
||||
fi
|
||||
echo "IPv4: $(curl --ipv4 --silent --max-time 15 --retry 3 --user-agent Mozilla https://api.ip.sb/geoip)"
|
||||
echo "IPv6: $(curl --ipv6 --silent --max-time 15 --retry 3 --user-agent Mozilla https://api.ip.sb/geoip)"
|
||||
}
|
||||
|
||||
is_linux() {
|
||||
[[ "$(uname -s)" == "Linux" ]]
|
||||
}
|
||||
|
||||
is_macos() {
|
||||
[[ "$(uname -s)" == "Darwin" ]]
|
||||
}
|
||||
|
||||
configure_warp_with_doh_and_ipv6_exclusion_on_linux() {
|
||||
install_warp_on_debian
|
||||
configure_warp_doh_and_exclude_ipv6
|
||||
}
|
||||
|
||||
configure_warp_with_doh_and_ipv6_exclusion_on_macos() {
|
||||
brew install cloudflare-warp
|
||||
configure_warp_doh_and_exclude_ipv6
|
||||
}
|
||||
|
||||
configure_warp_doh_and_exclude_ipv6() {
|
||||
echo 'Beginning configuration of the Cloudflare WARP client with DNS-over-HTTPS and IPv6 exclusion...'
|
||||
echo 'Initiating client registration with Cloudflare...'
|
||||
warp-cli --accept-tos registration new
|
||||
echo 'Configuring WARP to operate in DNS-over-HTTPS mode (warp+doh)...'
|
||||
warp-cli --accept-tos mode warp+doh
|
||||
echo 'Excluding IPv6 traffic from WARP by configuring it as a split tunnel...'
|
||||
warp-cli --accept-tos add-excluded-route '::/0' # Exclude IPv6, forcing IPv4 resolution
|
||||
# `tunnel ip add` does not work with IP ranges, see https://community.cloudflare.com/t/cant-cidr-for-split-tunnling/630834
|
||||
echo 'Establishing WARP connection...'
|
||||
warp-cli --accept-tos connect
|
||||
}
|
||||
|
||||
install_warp_on_debian() {
|
||||
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
|
||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cloudflare-warp
|
||||
}
|
||||
|
||||
disable_ipv6_on_macos() {
|
||||
networksetup -listallnetworkservices \
|
||||
| tail -n +2 \
|
||||
| while IFS= read -r interface; do
|
||||
echo "Disabling IPv6 on: $interface..."
|
||||
networksetup -setv6off "$interface"
|
||||
done
|
||||
}
|
||||
|
||||
prefer_ipv4_on_linux() {
|
||||
local -r gai_config_file_path='/etc/gai.conf'
|
||||
if [ ! -f "$gai_config_file_path" ]; then
|
||||
echo "Creating $gai_config_file_path since it doesn't exist..."
|
||||
touch "$gai_config_file_path"
|
||||
fi
|
||||
echo "precedence ::ffff:0:0/96 100" | sudo tee -a "$gai_config_file_path" > /dev/null
|
||||
echo "Configuration complete."
|
||||
}
|
||||
|
||||
main
|
||||
3
.github/actions/setup-node/action.yml
vendored
3
.github/actions/setup-node/action.yml
vendored
@@ -5,4 +5,5 @@ runs:
|
||||
name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 20.x
|
||||
check-latest: true
|
||||
|
||||
8
.github/workflows/checks.build.yaml
vendored
8
.github/workflows/checks.build.yaml
vendored
@@ -95,6 +95,12 @@ jobs:
|
||||
-
|
||||
name: Run Docker image on port 8080
|
||||
run: docker run -d -p 8080:80 --rm --name privacy.sexy undergroundwires/privacy.sexy:latest
|
||||
-
|
||||
name: Enforce IPv4 Connectivity # Used due to GitHub runners' lack of IPv6 support, preventing request timeouts.
|
||||
uses: ./.github/actions/force-ipv4
|
||||
-
|
||||
name: Check server is up and returns HTTP 200
|
||||
run: node ./scripts/verify-web-server-status.js --url http://localhost:8080
|
||||
run: >-
|
||||
node ./scripts/verify-web-server-status.js \
|
||||
--url http://localhost:8080 \
|
||||
--max-retries ${{ matrix.os == 'macos' && '90' || '30' }}
|
||||
|
||||
8
.github/workflows/checks.external-urls.yaml
vendored
8
.github/workflows/checks.external-urls.yaml
vendored
@@ -1,6 +1,7 @@
|
||||
name: checks.external-urls
|
||||
|
||||
on:
|
||||
push:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # at 00:00 on every Sunday
|
||||
|
||||
@@ -17,6 +18,13 @@ jobs:
|
||||
-
|
||||
name: Install dependencies
|
||||
uses: ./.github/actions/npm-install-dependencies
|
||||
-
|
||||
name: Enforce IPv4 Connectivity # Used due to GitHub runners' lack of IPv6 support, preventing request timeouts.
|
||||
uses: ./.github/actions/force-ipv4
|
||||
-
|
||||
name: Test
|
||||
run: npm run check:external-urls
|
||||
env:
|
||||
RANDOMIZED_URL_CHECK_LIMIT: "${{ github.event_name == 'push' && '100' || '3000' }}"
|
||||
# - Scheduled checks has high limit for thorough testing.
|
||||
# - For push events, triggered by code changes, the amount of URLs are limited to provide quick feedback.
|
||||
|
||||
1
.github/workflows/release.desktop.yaml
vendored
1
.github/workflows/release.desktop.yaml
vendored
@@ -20,6 +20,7 @@ jobs:
|
||||
fetch-depth: 0 # fetch all history
|
||||
-
|
||||
name: Checkout to bump commit
|
||||
shell: bash
|
||||
run: git checkout "$(git rev-list "${{ github.event.release.tag_name }}"..master | tail -1)"
|
||||
-
|
||||
name: Setup node
|
||||
|
||||
47
CHANGELOG.md
47
CHANGELOG.md
@@ -1,5 +1,52 @@
|
||||
# Changelog
|
||||
|
||||
## 0.13.1 (2024-03-22)
|
||||
|
||||
* ci/cd: Fix cross-platform git command compability | [255c51c](https://github.com/undergroundwires/privacy.sexy/commit/255c51c8a0524d3ea8a3b16ffc1b178650525010)
|
||||
* Fix tooltip falling behind elements on fade out | [1964524](https://github.com/undergroundwires/privacy.sexy/commit/19645248ab7bc78dc872fa176c1a3650d7d6d644)
|
||||
* Improve VSCode detection in `configure_vscode.py` | [98845e6](https://github.com/undergroundwires/privacy.sexy/commit/98845e6caee168db131aaf0736533e450827a52c)
|
||||
* Bump TypeScript to 5.3 with `verbatimModuleSyntax` | [a721e82](https://github.com/undergroundwires/privacy.sexy/commit/a721e82a4fb603c0732ccfdffc87396c2a01363e)
|
||||
* Migrate to Vite 5 and adjust configurations | [4ac1425](https://github.com/undergroundwires/privacy.sexy/commit/4ac1425f76079352268c488f3ff607d1fdc1beb2)
|
||||
* win: improve and unify service start/stop logic | [adc2089](https://github.com/undergroundwires/privacy.sexy/commit/adc20898873d50a8873ffc74c48257e69a45d367)
|
||||
* Upgrade vitest to v1 and fix test definitions | [e721885](https://github.com/undergroundwires/privacy.sexy/commit/e7218850ba62a7bebaf4768b13e46cba0dedd906)
|
||||
* Improve URL checks to reduce false-negatives | [5abf8ff](https://github.com/undergroundwires/privacy.sexy/commit/5abf8ff216a1da737fd489864eeee880f78d6601)
|
||||
* win: improve OneDrive data deletion safety | [5eff3a0](https://github.com/undergroundwires/privacy.sexy/commit/5eff3a04886d0d23a6e4c13a0178bb247105c5cb)
|
||||
* Bump Electron to latest and use native ESM | [840adf9](https://github.com/undergroundwires/privacy.sexy/commit/840adf9429ed47f9e88c05e90f1d3ab930c2dfc4)
|
||||
* Fix tooltip styling inconsistency | [ec34ac1](https://github.com/undergroundwires/privacy.sexy/commit/ec34ac1124e8b8ae53bf31a4dbdc88bb078b3d4e)
|
||||
* win: fix VSCode manual update switch script #312 | [b71ad79](https://github.com/undergroundwires/privacy.sexy/commit/b71ad797a3af0db45143249903cb5e178692de7c)
|
||||
* mac, linux, win: fix dead URLs and improve docs | [abec9de](https://github.com/undergroundwires/privacy.sexy/commit/abec9def075d82fdaee9663ef8fe1a488911f45b)
|
||||
|
||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.13.0...0.13.1)
|
||||
|
||||
## 0.13.0 (2024-02-11)
|
||||
|
||||
* win: add disabling clipboard features #251, #247 | [c6ebba8](https://github.com/undergroundwires/privacy.sexy/commit/c6ebba85fb1b362be0d81d3078f19db71e0528b2)
|
||||
* win: improve search privacy scripts #117 | [541f9aa](https://github.com/undergroundwires/privacy.sexy/commit/541f9aa5ee1b5f4885063b65beaf6cd873f0d786)
|
||||
* win: add disabling Windows Copilot #263, #266 | [cd42550](https://github.com/undergroundwires/privacy.sexy/commit/cd425502ae882bba9642dc2171c2b5771946b5a9)
|
||||
* win: add Dropbox telemetry blocking #125, #118 | [10829d6](https://github.com/undergroundwires/privacy.sexy/commit/10829d65aa3fb0df937bb8829244e6290bb748c7)
|
||||
* Improve selection type documentation | [7af8daa](https://github.com/undergroundwires/privacy.sexy/commit/7af8daa3411b24efb6385c7876a49bd372753f38)
|
||||
* Expand script names to take full available width | [d277139](https://github.com/undergroundwires/privacy.sexy/commit/d277139dd50eeb4e4057b0a7d8fc4ac2d70785de)
|
||||
* Limit tooltip width for improved readability | [6ab6dac](https://github.com/undergroundwires/privacy.sexy/commit/6ab6dacd1be2d7bf1863b07b121d86f2a379ac67)
|
||||
* Add markdown support for script/category names | [a5ffed4](https://github.com/undergroundwires/privacy.sexy/commit/a5ffed4cd60d9d058d5374145c1176b10fad1660)
|
||||
* Normalize and improve font sizes | [4da306b](https://github.com/undergroundwires/privacy.sexy/commit/4da306b9f79b0bb7a64bb197fb246258cf435b8d)
|
||||
* Change 'revert' button to title case | [937f459](https://github.com/undergroundwires/privacy.sexy/commit/937f4593d1a91081ab6b1bcb8f85d03879d7cf07)
|
||||
* Remove playful emojis (🍑🍆) | [aa4205f](https://github.com/undergroundwires/privacy.sexy/commit/aa4205ff7af7d05cfb5e82bf541b521d49bbd1c8)
|
||||
* Improve UI code styling for all platforms | [311fcb1](https://github.com/undergroundwires/privacy.sexy/commit/311fcb18133d1343f6a9ae5bd7a25795a1d12c49)
|
||||
* Render bracket references as superscript text | [b9c89b7](https://github.com/undergroundwires/privacy.sexy/commit/b9c89b701fc77d20dcc706419a8659ad156c4fc2)
|
||||
* Change slogan and refactor project info naming | [a54e164](https://github.com/undergroundwires/privacy.sexy/commit/a54e16488ce32219bcf811b5da85f06584b293fb)
|
||||
* Add 'Revert All Selection' feature #68 | [55fa7ea](https://github.com/undergroundwires/privacy.sexy/commit/55fa7eae71031357d6f03f0d349a09cd446270d3)
|
||||
* win, mac, linux: add privacy.sexy cleanup scripts | [63366a4](https://github.com/undergroundwires/privacy.sexy/commit/63366a4ec2533a376849d692211e9972b56ab4a8)
|
||||
* Extend search by including documentation content | [6142f3a](https://github.com/undergroundwires/privacy.sexy/commit/6142f3a2973d20493f784f323f3be57fa8deaeef)
|
||||
* Remove 'preview' label from Linux options | [ebd8285](https://github.com/undergroundwires/privacy.sexy/commit/ebd82853ddc56f1cc2fc9be3fe0b3001b07f0186)
|
||||
* Change fonts for improved readability | [d5bbc32](https://github.com/undergroundwires/privacy.sexy/commit/d5bbc321f902dc60618ffdfda0d583a4a433f7af)
|
||||
* Apply global styles for visual consistency | [faa7a38](https://github.com/undergroundwires/privacy.sexy/commit/faa7a38a7d16390f27e4a3e51017b81665cf85ca)
|
||||
* Add UI animations for expand/collapse actions | [fb08f03](https://github.com/undergroundwires/privacy.sexy/commit/fb08f037651e1a7d453b9a6af724cbccecc5b903)
|
||||
* win: relocate service disabling and improve docs | [894687c](https://github.com/undergroundwires/privacy.sexy/commit/894687c0e0375a24f40bcd720ea69c9b2aa62a58)
|
||||
* win: add host blocking category #26 | [17152c8](https://github.com/undergroundwires/privacy.sexy/commit/17152c84dc639e75560998a6feddfd46e0f713ce)
|
||||
* Update meta title and description | [c7fa4b6](https://github.com/undergroundwires/privacy.sexy/commit/c7fa4b6d020ac6fd3bf72bb4e57022dffb1ba921)
|
||||
|
||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.10...0.13.0)
|
||||
|
||||
## 0.12.10 (2024-01-17)
|
||||
|
||||
* Fix CSP for Vue, Ace, Vite, Safari compatibility | [940febc](https://github.com/undergroundwires/privacy.sexy/commit/940febc3e80cfd0c01b5cc8282ebaab6b024d1b5)
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
## Get started
|
||||
|
||||
- 🌍️ **Online**: [https://privacy.sexy](https://privacy.sexy).
|
||||
- 🖥️ **Offline**: Download directly for: [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.10/privacy.sexy-Setup-0.12.10.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.10/privacy.sexy-0.12.10.dmg), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.10/privacy.sexy-0.12.10.AppImage). For more options, see [here](#additional-install-options).
|
||||
- 🖥️ **Offline**: Download directly for: [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.13.1/privacy.sexy-Setup-0.13.1.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.13.1/privacy.sexy-0.13.1.dmg), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.13.1/privacy.sexy-0.13.1.AppImage). For more options, see [here](#additional-install-options).
|
||||
|
||||
For a detailed comparison of features between the desktop and web versions of privacy.sexy, see [Desktop vs. Web Features](./docs/desktop-vs-web-features.md).
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@ The presentation layer uses an event-driven architecture for bidirectional react
|
||||
- [**`main.ts`**](./../src/presentation/main.ts): Starts Vue app.
|
||||
- [**`index.html`**](./../src/presentation/index.html): The `index.html` entry file, located at the root of the project as required by Vite
|
||||
- [**`bootstrapping/`**](./../src/presentation/bootstrapping/): Registers Vue components and plugins.
|
||||
- [**`components/`**](./../src/presentation/components/): Contains Vue components and helpers.
|
||||
- [**`components/`**](./../src/presentation/components/): Contains Vue components, helpers and styles coupled to Vue components.
|
||||
- [**`Shared/`**](./../src/presentation/components/Shared): Contains shared Vue components and helpers.
|
||||
- [**`Hooks`**](../src/presentation/components/Shared/Hooks): Hooks used by components through [dependency injection](#dependency-injections).
|
||||
- [**`/public/`**](../src/presentation/public/): Contains static assets.
|
||||
- [**`assets/`**](./../src/presentation/assets/styles/): Contains assets processed by Vite.
|
||||
- [**`fonts/`**](./../src/presentation/assets/fonts/): Contains fonts.
|
||||
- [**`styles/`**](./../src/presentation/assets/styles/): Contains shared styles.
|
||||
- [**`components/`**](./../src/presentation/assets/styles/components): Contains styles coupled to Vue components.
|
||||
- [**`main.scss`**](./../src/presentation/assets/styles/main.scss): Main Sass file, imported by other components as single entrypoint..
|
||||
- [**`electron/`**](./../src/presentation/electron/): Contains Electron code.
|
||||
- [`/main/` **`index.ts`**](./../src/presentation/main.ts): Main entry for Electron, managing application windows and lifecycle events.
|
||||
@@ -38,6 +37,13 @@ The presentation layer uses an event-driven architecture for bidirectional react
|
||||
They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility.
|
||||
- **Borders**:
|
||||
privacy.sexy prefers sharper edges in its design language.
|
||||
- **Fonts**:
|
||||
- Use the primary font for regular text and monospace font for code or specific data.
|
||||
- Use cursive and logo fonts solely for branding.
|
||||
- Refer to [standardized font size variables](../src/presentation/assets/styles/_typography.scss) for font sizing, avoiding arbitrary `px`, `em`, `rem`, or percentage values.
|
||||
- **Spacing**:
|
||||
Use [global spacing variables](../src/presentation/assets/styles/_spacing.scss) for consistent margin, padding, and gap definitions.
|
||||
This provides uniform spatial distribution and alignment of elements, enhancing visual harmony and making the UI more scalable and maintainable.
|
||||
|
||||
## Application data
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ Key attributes of a good script:
|
||||
## Documentation
|
||||
|
||||
- Use credible and reputable sources for references.
|
||||
- Use archived links by using [archive.org](https://archive.org) or [archive.today](https://archive.today).
|
||||
- Format archive.today links fully, for example: `https://archive.today/YYYYMMDDhhmmss/https://privacy.sexy`.
|
||||
- Use archived links by using [archive.org](https://archive.org) or [archive.ph](https://archive.ph).
|
||||
- Format archive.today links fully, for example: `https://archive.ph/YYYYMMDDhhmmss/https://privacy.sexy`.
|
||||
- Explain the default behavior if the script is not executed.
|
||||
|
||||
## Shared functions
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
|
||||
const { join } = require('node:path');
|
||||
const { readdirSync } = require('fs');
|
||||
const { electronBundled, electronUnbundled } = require('./dist-dirs.json');
|
||||
|
||||
/**
|
||||
* @type {import('electron-builder').Configuration}
|
||||
* @see https://www.electron.build/configuration/configuration
|
||||
*/
|
||||
module.exports = {
|
||||
// Common options
|
||||
publish: {
|
||||
@@ -14,7 +19,9 @@ module.exports = {
|
||||
output: electronBundled,
|
||||
},
|
||||
extraMetadata: {
|
||||
main: join(electronUnbundled, 'main/index.cjs'), // do not `path.resolve`, it expects a relative path
|
||||
main: findMainEntryFile(
|
||||
join(electronUnbundled, 'main'), // do not `path.resolve`, it expects a relative path
|
||||
),
|
||||
},
|
||||
|
||||
// Windows
|
||||
@@ -41,3 +48,15 @@ module.exports = {
|
||||
artifactName: '${name}-${version}.${ext}',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds by accommodating different JS file extensions and module formats.
|
||||
*/
|
||||
function findMainEntryFile(parentDirectory) {
|
||||
const files = readdirSync(parentDirectory);
|
||||
const entryFile = files.find((file) => /^index\.(cjs|mjs|js)$/.test(file));
|
||||
if (!entryFile) {
|
||||
throw new Error(`Main entry file not found in ${parentDirectory}.`);
|
||||
}
|
||||
return join(parentDirectory, entryFile);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { resolve } from 'node:path';
|
||||
import { mergeConfig, UserConfig } from 'vite';
|
||||
import { mergeConfig, type UserConfig } from 'vite';
|
||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
|
||||
import { getAliases, getClientEnvironmentVariables } from './vite-config-helper';
|
||||
import { createVueConfig } from './vite.config';
|
||||
@@ -14,7 +14,7 @@ const ELECTRON_DIST_SUBDIRECTORIES = {
|
||||
renderer: resolveElectronDistSubdirectory('renderer'),
|
||||
};
|
||||
|
||||
process.env.ELECTRON_ENTRY = resolve(ELECTRON_DIST_SUBDIRECTORIES.main, 'index.cjs');
|
||||
process.env.ELECTRON_ENTRY = resolve(ELECTRON_DIST_SUBDIRECTORIES.main, 'index.mjs');
|
||||
|
||||
export default defineConfig({
|
||||
main: getSharedElectronConfig({
|
||||
@@ -54,13 +54,23 @@ function getSharedElectronConfig(options: {
|
||||
},
|
||||
rollupOptions: {
|
||||
output: {
|
||||
// Mark: electron-esm-support
|
||||
// This is needed so `type="module"` works
|
||||
entryFileNames: '[name].cjs',
|
||||
format: 'es',
|
||||
|
||||
// Ensure all generated files use '.mjs' for module consistency.
|
||||
// Otherwise, preloader process get `.mjs` extension but main process get `.js` extension, see https://github.com/alex8088/electron-vite/issues/397.
|
||||
entryFileNames: '[name].mjs',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [externalizeDepsPlugin()],
|
||||
plugins: [externalizeDepsPlugin({
|
||||
exclude: [
|
||||
// Keep 'electron-log' in bundling process.
|
||||
// This is a workaround for inability of Electron's ESM loader to resolve subpath imports.
|
||||
// Do not externalize `electron-log` so subpath imports such as `electron-log/main` works.
|
||||
// See https://github.com/electron/electron/issues/41241, https://github.com/alex8088/electron-vite/issues/401
|
||||
'electron-log',
|
||||
],
|
||||
})],
|
||||
define: {
|
||||
...getClientEnvironmentVariables(),
|
||||
},
|
||||
|
||||
12362
package-lock.json
generated
12362
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
84
package.json
84
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "privacy.sexy",
|
||||
"version": "0.12.10",
|
||||
"version": "0.13.1",
|
||||
"private": true,
|
||||
"slogan": "Privacy is sexy",
|
||||
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy.",
|
||||
@@ -33,62 +33,66 @@
|
||||
"postuninstall": "electron-builder install-app-deps"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/vue": "^1.0.2",
|
||||
"@floating-ui/vue": "^1.0.6",
|
||||
"@juggle/resize-observer": "^3.4.0",
|
||||
"@types/markdown-it": "^13.0.7",
|
||||
"ace-builds": "^1.30.0",
|
||||
"electron-log": "^5.0.1",
|
||||
"electron-progressbar": "^2.1.0",
|
||||
"electron-updater": "^6.1.4",
|
||||
"ace-builds": "^1.33.0",
|
||||
"electron-log": "^5.1.2",
|
||||
"electron-progressbar": "^2.2.1",
|
||||
"electron-updater": "^6.1.9",
|
||||
"file-saver": "^2.0.5",
|
||||
"markdown-it": "^13.0.2",
|
||||
"vue": "^3.3.7"
|
||||
"markdown-it": "^14.1.0",
|
||||
"vue": "^3.4.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@modyfi/vite-plugin-yaml": "^1.0.4",
|
||||
"@rushstack/eslint-patch": "^1.6.1",
|
||||
"@types/ace": "^0.0.49",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
||||
"@typescript-eslint/parser": "^6.17.0",
|
||||
"@vitejs/plugin-legacy": "^4.1.1",
|
||||
"@vitejs/plugin-vue": "^4.4.0",
|
||||
"@modyfi/vite-plugin-yaml": "^1.1.0",
|
||||
"@rushstack/eslint-patch": "^1.10.2",
|
||||
"@types/ace": "^0.0.52",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/markdown-it": "^14.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "6.21.0",
|
||||
"@typescript-eslint/parser": "6.21.0",
|
||||
"@vitejs/plugin-legacy": "^5.3.2",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vue/eslint-config-airbnb-with-typescript": "^8.0.0",
|
||||
"@vue/eslint-config-typescript": "^12.0.0",
|
||||
"@vue/test-utils": "^2.4.1",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"cypress": "^13.3.1",
|
||||
"electron": "^27.0.0",
|
||||
"electron-builder": "^24.6.4",
|
||||
"@vue/eslint-config-typescript": "12.0.0",
|
||||
"@vue/test-utils": "^2.4.5",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"cypress": "^13.7.3",
|
||||
"electron": "^29.3.0",
|
||||
"electron-builder": "^24.13.3",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-icon-builder": "^2.0.1",
|
||||
"electron-vite": "^1.0.28",
|
||||
"eslint": "^8.56.0",
|
||||
"electron-vite": "^2.1.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"eslint-plugin-vue": "^9.19.2",
|
||||
"eslint-plugin-vuejs-accessibility": "^2.2.0",
|
||||
"eslint-plugin-vue": "^9.25.0",
|
||||
"eslint-plugin-vuejs-accessibility": "^2.2.1",
|
||||
"icon-gen": "^4.0.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"markdownlint-cli": "^0.37.0",
|
||||
"postcss": "^8.4.31",
|
||||
"jsdom": "^24.0.0",
|
||||
"markdownlint-cli": "^0.39.0",
|
||||
"postcss": "^8.4.38",
|
||||
"remark-cli": "^12.0.0",
|
||||
"remark-lint-no-dead-urls": "^1.1.0",
|
||||
"remark-preset-lint-consistent": "^5.1.2",
|
||||
"remark-validate-links": "^13.0.0",
|
||||
"sass": "^1.69.3",
|
||||
"start-server-and-test": "^2.0.1",
|
||||
"remark-preset-lint-consistent": "^6.0.0",
|
||||
"remark-validate-links": "^13.0.1",
|
||||
"sass": "^1.75.0",
|
||||
"start-server-and-test": "^2.0.3",
|
||||
"svgexport": "^0.4.2",
|
||||
"terser": "^5.21.0",
|
||||
"terser": "^5.30.3",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.11",
|
||||
"vitest": "^0.34.6",
|
||||
"vue-tsc": "^1.8.19",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.8",
|
||||
"vitest": "^1.5.0",
|
||||
"vue-tsc": "^2.0.13",
|
||||
"yaml-lint": "^1.7.0"
|
||||
},
|
||||
"//devDependencies": {
|
||||
"terser": "Used by `@vitejs/plugin-legacy` for minification",
|
||||
"@rushstack/eslint-patch": "Needed by `@vue/eslint-config-typescript` and `@vue/eslint-config-airbnb-with-typescript`"
|
||||
"@rushstack/eslint-patch": "Needed by `@vue/eslint-config-typescript` and `@vue/eslint-config-airbnb-with-typescript`",
|
||||
"@typescript-eslint/eslint-plugin": "Cannot migrate to v7 because of `@vue/eslint-config-airbnb-with-typescript`, see https://github.com/vuejs/eslint-config-airbnb/issues/63",
|
||||
"@typescript-eslint/parser": "Cannot migrate to v7 because of `@vue/eslint-config-airbnb-with-typescript`, see https://github.com/vuejs/eslint-config-airbnb/issues/63",
|
||||
"@vue/eslint-config-typescript": "Cannot migrate to v13 because of `@vue/eslint-config-airbnb-with-typescript`, see https://github.com/vuejs/eslint-config-airbnb/issues/63",
|
||||
"eslint": "Cannot migrate to v9 `@typescript-eslint/eslint-plugin` (≤ v7), `@typescript-eslint/parser` (≤ v7), `@vue/eslint-config-airbnb-with-typescript@` (≤ v8) requires `eslint` ≤ v8, see https://github.com/vuejs/eslint-config-airbnb/issues/65, https://github.com/typescript-eslint/typescript-eslint/issues/8211"
|
||||
},
|
||||
"homepage": "https://privacy.sexy",
|
||||
"repository": {
|
||||
|
||||
@@ -6,10 +6,11 @@ development and installs recommended extensions from '.vscode/extensions.json'.
|
||||
|
||||
import os
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
from typing import Any
|
||||
from typing import Any, Optional
|
||||
from shutil import which
|
||||
|
||||
VSCODE_SETTINGS_JSON_FILE: str = '.vscode/settings.json'
|
||||
@@ -84,7 +85,7 @@ def install_recommended_extensions() -> None:
|
||||
if not extensions:
|
||||
print_skip(f"No recommendations found in the {VSCODE_EXTENSIONS_JSON_FILE} file.")
|
||||
return
|
||||
vscode_cli_path = which('code') # More reliable than using `code`, especially on Windows.
|
||||
vscode_cli_path = locate_vscode_cli()
|
||||
if vscode_cli_path is None:
|
||||
print_error('Visual Studio Code CLI (`code`) tool not found.')
|
||||
return
|
||||
@@ -92,11 +93,23 @@ def install_recommended_extensions() -> None:
|
||||
except json.JSONDecodeError:
|
||||
print_error(f"Invalid JSON in {VSCODE_EXTENSIONS_JSON_FILE}")
|
||||
|
||||
def locate_vscode_cli() -> Optional[str]:
|
||||
vscode_alias = which('code') # More reliable than using `code`, especially on Windows.
|
||||
if vscode_alias:
|
||||
return vscode_alias
|
||||
potential_vscode_cli_paths = [
|
||||
'/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code' # macOS VS Code may not register 'code' command in PATH
|
||||
]
|
||||
for vscode_cli_candidate_path in potential_vscode_cli_paths:
|
||||
if Path(vscode_cli_candidate_path).is_file():
|
||||
return vscode_cli_candidate_path
|
||||
return None
|
||||
|
||||
def remove_json_comments(json_like: str) -> str:
|
||||
pattern: str = r'(?:"(?:\\.|[^"\\])*"|/\*[\s\S]*?\*/|//.*)|([^:]//.*$)'
|
||||
return re.sub(
|
||||
pattern,
|
||||
lambda m: '' if m.group(1) else m.group(0), json_like, flags=re.MULTILINE,
|
||||
lambda m: '' if m.group(1) else m.agroup(0), json_like, flags=re.MULTILINE,
|
||||
)
|
||||
|
||||
def install_vscode_extensions(vscode_cli_path: str, extensions: list[str]) -> None:
|
||||
@@ -123,6 +136,12 @@ def install_vscode_extensions(vscode_cli_path: str, extensions: list[str]) -> No
|
||||
f"Visual Studio Code CLI tool not found: {vscode_cli_path}."
|
||||
f"Could not install extension: {ext}",
|
||||
]))
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
print_error(' '.join([
|
||||
f"Failed to install extension '{ext}'.",
|
||||
f"Attempted using Visual Studio Code CLI at: '{vscode_cli_path}'.",
|
||||
f"Encountered error: {e}",
|
||||
]))
|
||||
total_extensions = len(extensions)
|
||||
print_installation_results(successful_installations, total_extensions)
|
||||
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
/**
|
||||
* Description:
|
||||
* This script updates the logo images across the project based on the primary
|
||||
* logo file ('img/logo.svg' file).
|
||||
* It handles the creation and update of various icon sizes for different purposes,
|
||||
* including desktop launcher icons, tray icons, and web favicons from a single source
|
||||
* SVG logo file.
|
||||
*
|
||||
* Usage:
|
||||
* node ./scripts/logo-update.js
|
||||
*/
|
||||
|
||||
import { resolve, join } from 'node:path';
|
||||
import { rm, mkdtemp, stat } from 'node:fs/promises';
|
||||
import { spawn } from 'node:child_process';
|
||||
|
||||
@@ -44,8 +44,8 @@ function getBuildVerificationConfigs() {
|
||||
'--electron-unbundled': {
|
||||
printDistDirScriptArgument: '--electron-unbundled',
|
||||
filePatterns: [
|
||||
/main[/\\]index\.cjs/,
|
||||
/preload[/\\]index\.cjs/,
|
||||
/main[/\\]index\.(cjs|mjs|js)/,
|
||||
/preload[/\\]index\.(cjs|mjs|js)/,
|
||||
/renderer[/\\]index\.htm(l)?/,
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,62 +1,87 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* This script checks if a server, provided as a CLI argument, is up
|
||||
* and returns an HTTP 200 status code.
|
||||
* It is designed to provide easy verification of server availability
|
||||
* and will retry a specified number of times.
|
||||
* This script checks if a server, provided as a CLI argument, is up
|
||||
* and returns an HTTP 200 status code.
|
||||
* It is designed to provide easy verification of server availability
|
||||
* and will retry a specified number of times.
|
||||
*
|
||||
* Usage:
|
||||
* node ./scripts/verify-web-server-status.js --url [URL]
|
||||
* node ./scripts/verify-web-server-status.js --url [URL] [--max-retries NUMBER]
|
||||
*
|
||||
* Options:
|
||||
* --url URL of the server to check
|
||||
* --url URL of the server to check
|
||||
* --max-retries Maximum number of retry attempts (default: 30)
|
||||
*/
|
||||
|
||||
import { get } from 'http';
|
||||
|
||||
const MAX_RETRIES = 30;
|
||||
const DEFAULT_MAX_RETRIES = 30;
|
||||
const RETRY_DELAY_IN_SECONDS = 3;
|
||||
const URL_PARAMETER_NAME = '--url';
|
||||
const PARAMETER_NAME_URL = '--url';
|
||||
const PARAMETER_NAME_MAX_RETRIES = '--max-retries';
|
||||
|
||||
function checkServer(currentRetryCount = 1) {
|
||||
const serverUrl = getServerUrl();
|
||||
console.log(`Requesting ${serverUrl}...`);
|
||||
get(serverUrl, (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
async function checkServer(currentRetryCount = 1) {
|
||||
const serverUrl = readRequiredParameterValue(PARAMETER_NAME_URL);
|
||||
const maxRetries = parseNumber(
|
||||
readOptionalParameterValue(PARAMETER_NAME_MAX_RETRIES, DEFAULT_MAX_RETRIES),
|
||||
);
|
||||
console.log(`🌐 Requesting ${serverUrl}...`);
|
||||
try {
|
||||
const response = await fetch(serverUrl);
|
||||
if (response.status === 200) {
|
||||
console.log('🎊 Success: The server is up and returned HTTP 200.');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log(`Server returned HTTP status code ${res.statusCode}.`);
|
||||
retry(currentRetryCount);
|
||||
exitWithError(`Server returned unexpected HTTP status code ${response.statusCode}.`);
|
||||
}
|
||||
}).on('error', (err) => {
|
||||
console.error('Error making the request:', err);
|
||||
retry(currentRetryCount);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error making the request:', error);
|
||||
scheduleNextRetry(maxRetries, currentRetryCount);
|
||||
}
|
||||
}
|
||||
|
||||
function retry(currentRetryCount) {
|
||||
console.log(`Attempt ${currentRetryCount}/${MAX_RETRIES}:`);
|
||||
function scheduleNextRetry(maxRetries, currentRetryCount) {
|
||||
console.log(`Attempt ${currentRetryCount}/${maxRetries}:`);
|
||||
console.log(`Retrying in ${RETRY_DELAY_IN_SECONDS} seconds.`);
|
||||
|
||||
const remainingTime = (MAX_RETRIES - currentRetryCount) * RETRY_DELAY_IN_SECONDS;
|
||||
const remainingTime = (maxRetries - currentRetryCount) * RETRY_DELAY_IN_SECONDS;
|
||||
console.log(`Time remaining before timeout: ${remainingTime}s`);
|
||||
|
||||
if (currentRetryCount < MAX_RETRIES) {
|
||||
if (currentRetryCount < maxRetries) {
|
||||
setTimeout(() => checkServer(currentRetryCount + 1), RETRY_DELAY_IN_SECONDS * 1000);
|
||||
} else {
|
||||
console.log('Failure: The server at did not return HTTP 200 within the allocated time. Exiting.');
|
||||
process.exit(1);
|
||||
exitWithError('The server at did not return HTTP 200 within the allocated time.');
|
||||
}
|
||||
}
|
||||
|
||||
function getServerUrl() {
|
||||
const urlIndex = process.argv.indexOf(URL_PARAMETER_NAME);
|
||||
if (urlIndex === -1 || urlIndex === process.argv.length - 1) {
|
||||
console.error(`Parameter "${URL_PARAMETER_NAME}" is not provided.`);
|
||||
process.exit(1);
|
||||
function readRequiredParameterValue(parameterName) {
|
||||
const parameterValue = readOptionalParameterValue(parameterName);
|
||||
if (parameterValue === undefined) {
|
||||
exitWithError(`Parameter "${parameterName}" is required but not provided.`);
|
||||
}
|
||||
return process.argv[urlIndex + 1];
|
||||
return parameterValue;
|
||||
}
|
||||
|
||||
checkServer();
|
||||
function readOptionalParameterValue(parameterName, defaultValue) {
|
||||
const index = process.argv.indexOf(parameterName);
|
||||
if (index === -1 || index === process.argv.length - 1) {
|
||||
return defaultValue;
|
||||
}
|
||||
return process.argv[index + 1];
|
||||
}
|
||||
|
||||
function parseNumber(numberLike) {
|
||||
const number = parseInt(numberLike, 10);
|
||||
if (Number.isNaN(number)) {
|
||||
exitWithError(`Invalid number: ${numberLike}`);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
function exitWithError(message) {
|
||||
console.error(`Failure: ${message}`);
|
||||
console.log('Exiting');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await checkServer();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IApplication } from '@/domain/IApplication';
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
import { AsyncLazy } from '@/infrastructure/Threading/AsyncLazy';
|
||||
import { IApplicationFactory } from './IApplicationFactory';
|
||||
import { parseApplication } from './Parser/ApplicationParser';
|
||||
import type { IApplicationFactory } from './IApplicationFactory';
|
||||
|
||||
export type ApplicationGetterType = () => IApplication;
|
||||
const ApplicationGetter: ApplicationGetterType = parseApplication;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { assertInRange } from '@/application/Common/Enum';
|
||||
import { IScriptingLanguageFactory } from './IScriptingLanguageFactory';
|
||||
import type { IScriptingLanguageFactory } from './IScriptingLanguageFactory';
|
||||
|
||||
type Getter<T> = () => T;
|
||||
|
||||
|
||||
12
src/application/Common/Shuffle.ts
Normal file
12
src/application/Common/Shuffle.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Shuffle an array of strings, returning a new array with elements in random order.
|
||||
Uses the Fisher-Yates (or Durstenfeld) algorithm.
|
||||
*/
|
||||
export function shuffle<T>(array: readonly T[]): T[] {
|
||||
const shuffledArray = [...array];
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
|
||||
}
|
||||
return shuffledArray;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PlatformTimer } from './PlatformTimer';
|
||||
import { TimeoutType, Timer } from './Timer';
|
||||
import type { TimeoutType, Timer } from './Timer';
|
||||
|
||||
export function batchedDebounce<T>(
|
||||
callback: (batches: readonly T[]) => void,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Timer } from './Timer';
|
||||
import type { Timer } from './Timer';
|
||||
|
||||
export const PlatformTimer: Timer = {
|
||||
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Timer, TimeoutType } from './Timer';
|
||||
import { PlatformTimer } from './PlatformTimer';
|
||||
import type { Timer, TimeoutType } from './Timer';
|
||||
|
||||
export type CallbackType = (..._: readonly unknown[]) => void;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { IApplication } from '@/domain/IApplication';
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import { assertInRange } from '@/application/Common/Enum';
|
||||
import { CategoryCollectionState } from './State/CategoryCollectionState';
|
||||
import { ICategoryCollectionState } from './State/ICategoryCollectionState';
|
||||
import { IApplicationContext, IApplicationContextChangedEvent } from './IApplicationContext';
|
||||
import type { IApplicationContext, IApplicationContextChangedEvent } from './IApplicationContext';
|
||||
import type { ICategoryCollectionState } from './State/ICategoryCollectionState';
|
||||
|
||||
type StateMachine = Map<OperatingSystem, ICategoryCollectionState>;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { IApplicationContext } from '@/application/Context/IApplicationContext';
|
||||
import type { IApplicationContext } from '@/application/Context/IApplicationContext';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { IApplication } from '@/domain/IApplication';
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
import { CurrentEnvironment } from '@/infrastructure/RuntimeEnvironment/RuntimeEnvironmentFactory';
|
||||
import { IApplicationFactory } from '../IApplicationFactory';
|
||||
import { ApplicationFactory } from '../ApplicationFactory';
|
||||
import { ApplicationContext } from './ApplicationContext';
|
||||
import type { IApplicationFactory } from '../IApplicationFactory';
|
||||
|
||||
export async function buildContext(
|
||||
factory: IApplicationFactory = ApplicationFactory.Current,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import { IApplication } from '@/domain/IApplication';
|
||||
import { ICategoryCollectionState, IReadOnlyCategoryCollectionState } from './State/ICategoryCollectionState';
|
||||
import type { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
import type { ICategoryCollectionState, IReadOnlyCategoryCollectionState } from './State/ICategoryCollectionState';
|
||||
|
||||
export interface IReadOnlyApplicationContext {
|
||||
readonly app: IApplication;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { AdaptiveFilterContext } from './Filter/AdaptiveFilterContext';
|
||||
import { FilterContext } from './Filter/FilterContext';
|
||||
import { ApplicationCode } from './Code/ApplicationCode';
|
||||
import { UserSelection } from './Selection/UserSelection';
|
||||
import { ICategoryCollectionState } from './ICategoryCollectionState';
|
||||
import { IApplicationCode } from './Code/IApplicationCode';
|
||||
import { UserSelectionFacade } from './Selection/UserSelectionFacade';
|
||||
import type { FilterContext } from './Filter/FilterContext';
|
||||
import type { UserSelection } from './Selection/UserSelection';
|
||||
import type { ICategoryCollectionState } from './ICategoryCollectionState';
|
||||
import type { IApplicationCode } from './Code/IApplicationCode';
|
||||
|
||||
export class CategoryCollectionState implements ICategoryCollectionState {
|
||||
public readonly os: OperatingSystem;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { ReadonlyScriptSelection } from '@/application/Context/State/Selection/Script/ScriptSelection';
|
||||
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import type { ReadonlyScriptSelection } from '@/application/Context/State/Selection/Script/ScriptSelection';
|
||||
import { CodeChangedEvent } from './Event/CodeChangedEvent';
|
||||
import { CodePosition } from './Position/CodePosition';
|
||||
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
||||
import { UserScriptGenerator } from './Generation/UserScriptGenerator';
|
||||
import { IApplicationCode } from './IApplicationCode';
|
||||
import { IUserScriptGenerator } from './Generation/IUserScriptGenerator';
|
||||
import type { IUserScriptGenerator } from './Generation/IUserScriptGenerator';
|
||||
import type { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
||||
import type { IApplicationCode } from './IApplicationCode';
|
||||
|
||||
export class ApplicationCode implements IApplicationCode {
|
||||
public readonly changed = new EventSource<ICodeChangedEvent>();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { ICodeChangedEvent } from './ICodeChangedEvent';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import type { ICodeChangedEvent } from './ICodeChangedEvent';
|
||||
|
||||
export class CodeChangedEvent implements ICodeChangedEvent {
|
||||
public readonly code: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
|
||||
export interface ICodeChangedEvent {
|
||||
readonly code: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ICodeBuilder } from './ICodeBuilder';
|
||||
import type { ICodeBuilder } from './ICodeBuilder';
|
||||
|
||||
const TotalFunctionSeparatorChars = 58;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ScriptingLanguageFactory } from '@/application/Common/ScriptingLanguage/ScriptingLanguageFactory';
|
||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { ICodeBuilder } from './ICodeBuilder';
|
||||
import { BatchBuilder } from './Languages/BatchBuilder';
|
||||
import { ShellBuilder } from './Languages/ShellBuilder';
|
||||
import { ICodeBuilderFactory } from './ICodeBuilderFactory';
|
||||
import type { ICodeBuilder } from './ICodeBuilder';
|
||||
import type { ICodeBuilderFactory } from './ICodeBuilderFactory';
|
||||
|
||||
export class CodeBuilderFactory
|
||||
extends ScriptingLanguageFactory<ICodeBuilder>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IScriptingLanguageFactory } from '@/application/Common/ScriptingLanguage/IScriptingLanguageFactory';
|
||||
import { ICodeBuilder } from './ICodeBuilder';
|
||||
import type { IScriptingLanguageFactory } from '@/application/Common/ScriptingLanguage/IScriptingLanguageFactory';
|
||||
import type { ICodeBuilder } from './ICodeBuilder';
|
||||
|
||||
export type ICodeBuilderFactory = IScriptingLanguageFactory<ICodeBuilder>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
|
||||
export interface IUserScript {
|
||||
readonly code: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { IUserScript } from './IUserScript';
|
||||
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import type { IUserScript } from './IUserScript';
|
||||
|
||||
export interface IUserScriptGenerator {
|
||||
buildCode(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { CodePosition } from '../Position/CodePosition';
|
||||
import { IUserScriptGenerator } from './IUserScriptGenerator';
|
||||
import { IUserScript } from './IUserScript';
|
||||
import { ICodeBuilder } from './ICodeBuilder';
|
||||
import { ICodeBuilderFactory } from './ICodeBuilderFactory';
|
||||
import { CodeBuilderFactory } from './CodeBuilderFactory';
|
||||
import type { IUserScriptGenerator } from './IUserScriptGenerator';
|
||||
import type { IUserScript } from './IUserScript';
|
||||
import type { ICodeBuilder } from './ICodeBuilder';
|
||||
import type { ICodeBuilderFactory } from './ICodeBuilderFactory';
|
||||
|
||||
export class UserScriptGenerator implements IUserScriptGenerator {
|
||||
constructor(private readonly codeBuilderFactory: ICodeBuilderFactory = new CodeBuilderFactory()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
||||
import type { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import type { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
||||
|
||||
export interface IApplicationCode {
|
||||
readonly changed: IEventSource<ICodeChangedEvent>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ICodePosition } from './ICodePosition';
|
||||
import type { ICodePosition } from './ICodePosition';
|
||||
|
||||
export class CodePosition implements ICodePosition {
|
||||
public get totalLines(): number {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { FilterResult } from './Result/FilterResult';
|
||||
import { FilterContext } from './FilterContext';
|
||||
import { FilterChangeDetails } from './Event/FilterChangeDetails';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { FilterChange } from './Event/FilterChange';
|
||||
import { FilterStrategy } from './Strategy/FilterStrategy';
|
||||
import { LinearFilterStrategy } from './Strategy/LinearFilterStrategy';
|
||||
import type { FilterResult } from './Result/FilterResult';
|
||||
import type { FilterContext } from './FilterContext';
|
||||
import type { FilterChangeDetails } from './Event/FilterChangeDetails';
|
||||
import type { FilterStrategy } from './Strategy/FilterStrategy';
|
||||
|
||||
export class AdaptiveFilterContext implements FilterContext {
|
||||
public readonly filterChanged = new EventSource<FilterChangeDetails>();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FilterResult } from '@/application/Context/State/Filter/Result/FilterResult';
|
||||
import type { FilterResult } from '@/application/Context/State/Filter/Result/FilterResult';
|
||||
import { FilterActionType } from './FilterActionType';
|
||||
import {
|
||||
import type {
|
||||
FilterChangeDetails, FilterChangeDetailsVisitor,
|
||||
ApplyFilterAction, ClearFilterAction,
|
||||
} from './FilterChangeDetails';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import { FilterResult } from './Result/FilterResult';
|
||||
import { FilterChangeDetails } from './Event/FilterChangeDetails';
|
||||
import type { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import type { FilterResult } from './Result/FilterResult';
|
||||
import type { FilterChangeDetails } from './Event/FilterChangeDetails';
|
||||
|
||||
export interface ReadonlyFilterContext {
|
||||
readonly currentFilter: FilterResult | undefined;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import { ICategory } from '@/domain/ICategory';
|
||||
import { FilterResult } from './FilterResult';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
import type { ICategory } from '@/domain/ICategory';
|
||||
import type { FilterResult } from './FilterResult';
|
||||
|
||||
export class AppliedFilterResult implements FilterResult {
|
||||
constructor(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IScript, ICategory } from '@/domain/ICategory';
|
||||
import type { IScript, ICategory } from '@/domain/ICategory';
|
||||
|
||||
export interface FilterResult {
|
||||
readonly categoryMatches: ReadonlyArray<ICategory>;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { ReadonlyFilterContext, FilterContext } from './Filter/FilterContext';
|
||||
import { ReadonlyUserSelection, UserSelection } from './Selection/UserSelection';
|
||||
import { IApplicationCode } from './Code/IApplicationCode';
|
||||
import type { IApplicationCode } from './Code/IApplicationCode';
|
||||
import type { ReadonlyFilterContext, FilterContext } from './Filter/FilterContext';
|
||||
import type { ReadonlyUserSelection, UserSelection } from './Selection/UserSelection';
|
||||
|
||||
export interface IReadOnlyCategoryCollectionState {
|
||||
readonly code: IApplicationCode;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ICategory } from '@/domain/ICategory';
|
||||
import { CategorySelectionChangeCommand } from './CategorySelectionChange';
|
||||
import type { ICategory } from '@/domain/ICategory';
|
||||
import type { CategorySelectionChangeCommand } from './CategorySelectionChange';
|
||||
|
||||
export interface ReadonlyCategorySelection {
|
||||
areAllScriptsSelected(category: ICategory): boolean;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ICategory } from '@/domain/ICategory';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { ScriptSelection } from '../Script/ScriptSelection';
|
||||
import { ScriptSelectionChange } from '../Script/ScriptSelectionChange';
|
||||
import { CategorySelection } from './CategorySelection';
|
||||
import { CategorySelectionChange, CategorySelectionChangeCommand } from './CategorySelectionChange';
|
||||
import type { ICategory } from '@/domain/ICategory';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { CategorySelectionChange, CategorySelectionChangeCommand } from './CategorySelectionChange';
|
||||
import type { CategorySelection } from './CategorySelection';
|
||||
import type { ScriptSelection } from '../Script/ScriptSelection';
|
||||
import type { ScriptSelectionChange } from '../Script/ScriptSelectionChange';
|
||||
|
||||
export class ScriptToCategorySelectionMapper implements CategorySelection {
|
||||
constructor(
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryRepository';
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import { ReadonlyRepository, Repository } from '@/application/Repository/Repository';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ReadonlyRepository, Repository } from '@/application/Repository/Repository';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { batchedDebounce } from '@/application/Common/Timing/BatchedDebounce';
|
||||
import { ScriptSelection } from './ScriptSelection';
|
||||
import { ScriptSelectionChange, ScriptSelectionChangeCommand } from './ScriptSelectionChange';
|
||||
import { SelectedScript } from './SelectedScript';
|
||||
import { UserSelectedScript } from './UserSelectedScript';
|
||||
import type { ScriptSelection } from './ScriptSelection';
|
||||
import type { ScriptSelectionChange, ScriptSelectionChangeCommand } from './ScriptSelectionChange';
|
||||
import type { SelectedScript } from './SelectedScript';
|
||||
|
||||
const DEBOUNCE_DELAY_IN_MS = 100;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import { SelectedScript } from './SelectedScript';
|
||||
import { ScriptSelectionChangeCommand } from './ScriptSelectionChange';
|
||||
import type { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
import type { SelectedScript } from './SelectedScript';
|
||||
import type { ScriptSelectionChangeCommand } from './ScriptSelectionChange';
|
||||
|
||||
export interface ReadonlyScriptSelection {
|
||||
readonly changed: IEventSource<readonly SelectedScript[]>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IEntity } from '@/infrastructure/Entity/IEntity';
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import type { IEntity } from '@/infrastructure/Entity/IEntity';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
|
||||
type ScriptId = IScript['id'];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import { SelectedScript } from './SelectedScript';
|
||||
import type { IScript } from '@/domain/IScript';
|
||||
import type { SelectedScript } from './SelectedScript';
|
||||
|
||||
type SelectedScriptId = SelectedScript['id'];
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CategorySelection, ReadonlyCategorySelection } from './Category/CategorySelection';
|
||||
import { ReadonlyScriptSelection, ScriptSelection } from './Script/ScriptSelection';
|
||||
import type { CategorySelection, ReadonlyCategorySelection } from './Category/CategorySelection';
|
||||
import type { ReadonlyScriptSelection, ScriptSelection } from './Script/ScriptSelection';
|
||||
|
||||
export interface ReadonlyUserSelection {
|
||||
readonly categories: ReadonlyCategorySelection;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { CategorySelection } from './Category/CategorySelection';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { ScriptToCategorySelectionMapper } from './Category/ScriptToCategorySelectionMapper';
|
||||
import { DebouncedScriptSelection } from './Script/DebouncedScriptSelection';
|
||||
import { ScriptSelection } from './Script/ScriptSelection';
|
||||
import { UserSelection } from './UserSelection';
|
||||
import { SelectedScript } from './Script/SelectedScript';
|
||||
import type { CategorySelection } from './Category/CategorySelection';
|
||||
import type { ScriptSelection } from './Script/ScriptSelection';
|
||||
import type { UserSelection } from './UserSelection';
|
||||
import type { SelectedScript } from './Script/SelectedScript';
|
||||
|
||||
export class UserSelectionFacade implements UserSelection {
|
||||
public readonly categories: CategorySelection;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IApplication } from '@/domain/IApplication';
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
|
||||
export interface IApplicationFactory {
|
||||
getApp(): Promise<IApplication>;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { CollectionData } from '@/application/collections/';
|
||||
import { IApplication } from '@/domain/IApplication';
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import WindowsData from '@/application/collections/windows.yaml';
|
||||
import MacOsData from '@/application/collections/macos.yaml';
|
||||
import LinuxData from '@/application/collections/linux.yaml';
|
||||
import { parseProjectDetails } from '@/application/Parser/ProjectDetailsParser';
|
||||
import { Application } from '@/domain/Application';
|
||||
import { IAppMetadata } from '@/infrastructure/EnvironmentVariables/IAppMetadata';
|
||||
import type { IAppMetadata } from '@/infrastructure/EnvironmentVariables/IAppMetadata';
|
||||
import { EnvironmentVariablesFactory } from '@/infrastructure/EnvironmentVariables/EnvironmentVariablesFactory';
|
||||
import { parseCategoryCollection } from './CategoryCollectionParser';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CollectionData } from '@/application/collections/';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { CategoryCollection } from '@/domain/CategoryCollection';
|
||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||
import { createEnumParser } from '../Common/Enum';
|
||||
|
||||
@@ -6,8 +6,8 @@ import { Category } from '@/domain/Category';
|
||||
import { NodeValidator } from '@/application/Parser/NodeValidation/NodeValidator';
|
||||
import { NodeType } from '@/application/Parser/NodeValidation/NodeType';
|
||||
import { parseDocs } from './DocumentationParser';
|
||||
import { ICategoryCollectionParseContext } from './Script/ICategoryCollectionParseContext';
|
||||
import { parseScript } from './Script/ScriptParser';
|
||||
import type { ICategoryCollectionParseContext } from './Script/ICategoryCollectionParseContext';
|
||||
|
||||
let categoryIdCounter = 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CustomError } from '@/application/Common/CustomError';
|
||||
import { NodeType } from './NodeType';
|
||||
import { NodeData } from './NodeData';
|
||||
import type { NodeData } from './NodeData';
|
||||
|
||||
export class NodeDataError extends CustomError {
|
||||
constructor(message: string, public readonly context: INodeDataErrorContext) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { isString } from '@/TypeHelpers';
|
||||
import { INodeDataErrorContext, NodeDataError } from './NodeDataError';
|
||||
import { NodeData } from './NodeData';
|
||||
import { type INodeDataErrorContext, NodeDataError } from './NodeDataError';
|
||||
import type { NodeData } from './NodeData';
|
||||
|
||||
export class NodeValidator {
|
||||
constructor(private readonly context: INodeDataErrorContext) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||
import { GitHubProjectDetails } from '@/domain/Project/GitHubProjectDetails';
|
||||
import { IAppMetadata } from '@/infrastructure/EnvironmentVariables/IAppMetadata';
|
||||
import type { IAppMetadata } from '@/infrastructure/EnvironmentVariables/IAppMetadata';
|
||||
import { Version } from '@/domain/Version';
|
||||
import { EnvironmentVariablesFactory } from '@/infrastructure/EnvironmentVariables/EnvironmentVariablesFactory';
|
||||
import { ConstructorArguments } from '@/TypeHelpers';
|
||||
import type { ConstructorArguments } from '@/TypeHelpers';
|
||||
|
||||
export function
|
||||
parseProjectDetails(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { FunctionData } from '@/application/collections/';
|
||||
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import { IScriptCompiler } from './Compiler/IScriptCompiler';
|
||||
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||
import { ScriptCompiler } from './Compiler/ScriptCompiler';
|
||||
import { ICategoryCollectionParseContext } from './ICategoryCollectionParseContext';
|
||||
import { SyntaxFactory } from './Validation/Syntax/SyntaxFactory';
|
||||
import { ISyntaxFactory } from './Validation/Syntax/ISyntaxFactory';
|
||||
import { ILanguageSyntax } from './Validation/Syntax/ILanguageSyntax';
|
||||
import type { ILanguageSyntax } from './Validation/Syntax/ILanguageSyntax';
|
||||
import type { IScriptCompiler } from './Compiler/IScriptCompiler';
|
||||
import type { ICategoryCollectionParseContext } from './ICategoryCollectionParseContext';
|
||||
import type { ISyntaxFactory } from './Validation/Syntax/ISyntaxFactory';
|
||||
|
||||
export class CategoryCollectionParseContext implements ICategoryCollectionParseContext {
|
||||
public readonly compiler: IScriptCompiler;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { FunctionParameterCollection } from '@/application/Parser/Script/Compiler/Function/Parameter/FunctionParameterCollection';
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '../../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import { IReadOnlyFunctionParameterCollection } from '../../Function/Parameter/IFunctionParameterCollection';
|
||||
import { FunctionCallArgumentCollection } from '../../Function/Call/Argument/FunctionCallArgumentCollection';
|
||||
import { IExpression } from './IExpression';
|
||||
import { ExpressionEvaluationContext, type IExpressionEvaluationContext } from './ExpressionEvaluationContext';
|
||||
import { ExpressionPosition } from './ExpressionPosition';
|
||||
import { ExpressionEvaluationContext, IExpressionEvaluationContext } from './ExpressionEvaluationContext';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from '../../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import type { IReadOnlyFunctionParameterCollection } from '../../Function/Parameter/IFunctionParameterCollection';
|
||||
import type { IExpression } from './IExpression';
|
||||
|
||||
export type ExpressionEvaluator = (context: IExpressionEvaluationContext) => string;
|
||||
export class Expression implements IExpression {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '../../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import { IPipelineCompiler } from '../Pipes/IPipelineCompiler';
|
||||
import { PipelineCompiler } from '../Pipes/PipelineCompiler';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from '../../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import type { IPipelineCompiler } from '../Pipes/IPipelineCompiler';
|
||||
|
||||
export interface IExpressionEvaluationContext {
|
||||
readonly args: IReadOnlyFunctionCallArgumentCollection;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IReadOnlyFunctionParameterCollection } from '../../Function/Parameter/IFunctionParameterCollection';
|
||||
import { ExpressionPosition } from './ExpressionPosition';
|
||||
import { IExpressionEvaluationContext } from './ExpressionEvaluationContext';
|
||||
import type { IReadOnlyFunctionParameterCollection } from '../../Function/Parameter/IFunctionParameterCollection';
|
||||
import type { IExpressionEvaluationContext } from './ExpressionEvaluationContext';
|
||||
|
||||
export interface IExpression {
|
||||
readonly position: ExpressionPosition;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { IExpressionEvaluationContext, ExpressionEvaluationContext } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionEvaluationContext';
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import { IExpressionsCompiler } from './IExpressionsCompiler';
|
||||
import { IExpression } from './Expression/IExpression';
|
||||
import { IExpressionParser } from './Parser/IExpressionParser';
|
||||
import { type IExpressionEvaluationContext, ExpressionEvaluationContext } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionEvaluationContext';
|
||||
import { CompositeExpressionParser } from './Parser/CompositeExpressionParser';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from '../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import type { IExpressionsCompiler } from './IExpressionsCompiler';
|
||||
import type { IExpression } from './Expression/IExpression';
|
||||
import type { IExpressionParser } from './Parser/IExpressionParser';
|
||||
|
||||
export class ExpressionsCompiler implements IExpressionsCompiler {
|
||||
public constructor(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from '../Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
|
||||
export interface IExpressionsCompiler {
|
||||
compileExpressions(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IExpression } from '../Expression/IExpression';
|
||||
import { ParameterSubstitutionParser } from '../SyntaxParsers/ParameterSubstitutionParser';
|
||||
import { WithParser } from '../SyntaxParsers/WithParser';
|
||||
import { IExpressionParser } from './IExpressionParser';
|
||||
import type { IExpression } from '../Expression/IExpression';
|
||||
import type { IExpressionParser } from './IExpressionParser';
|
||||
|
||||
const Parsers = [
|
||||
new ParameterSubstitutionParser(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IExpression } from '../Expression/IExpression';
|
||||
import type { IExpression } from '../Expression/IExpression';
|
||||
|
||||
export interface IExpressionParser {
|
||||
findExpressions(code: string): IExpression[];
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { IExpressionParser } from '../IExpressionParser';
|
||||
import { IExpression } from '../../Expression/IExpression';
|
||||
import { Expression, ExpressionEvaluator } from '../../Expression/Expression';
|
||||
import { IFunctionParameter } from '../../../Function/Parameter/IFunctionParameter';
|
||||
import { Expression, type ExpressionEvaluator } from '../../Expression/Expression';
|
||||
import { FunctionParameterCollection } from '../../../Function/Parameter/FunctionParameterCollection';
|
||||
import { createPositionFromRegexFullMatch } from '../../Expression/ExpressionPositionFactory';
|
||||
import type { IExpressionParser } from '../IExpressionParser';
|
||||
import type { IExpression } from '../../Expression/IExpression';
|
||||
import type { IFunctionParameter } from '../../../Function/Parameter/IFunctionParameter';
|
||||
|
||||
export abstract class RegexParser implements IExpressionParser {
|
||||
protected abstract readonly regex: RegExp;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPipe } from '../IPipe';
|
||||
import type { IPipe } from '../IPipe';
|
||||
|
||||
export class EscapeDoubleQuotes implements IPipe {
|
||||
public readonly name: string = 'escapeDoubleQuotes';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPipe } from '../IPipe';
|
||||
import type { IPipe } from '../IPipe';
|
||||
|
||||
export class InlinePowerShell implements IPipe {
|
||||
public readonly name: string = 'inlinePowerShell';
|
||||
@@ -95,7 +95,7 @@ function getLines(code: string): string[] {
|
||||
|
||||
/*
|
||||
Merges inline here-strings to a single lined string with Windows line terminator (\r\n)
|
||||
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules#here-strings
|
||||
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.4#here-strings
|
||||
*/
|
||||
function mergeHereStrings(code: string) {
|
||||
const regex = /@(['"])\s*(?:\r\n|\r|\n)((.|\n|\r)+?)(\r\n|\r|\n)\1@/g;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IPipe } from './IPipe';
|
||||
import { InlinePowerShell } from './PipeDefinitions/InlinePowerShell';
|
||||
import { EscapeDoubleQuotes } from './PipeDefinitions/EscapeDoubleQuotes';
|
||||
import type { IPipe } from './IPipe';
|
||||
|
||||
const RegisteredPipes = [
|
||||
new EscapeDoubleQuotes(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IPipeFactory, PipeFactory } from './PipeFactory';
|
||||
import { IPipelineCompiler } from './IPipelineCompiler';
|
||||
import { type IPipeFactory, PipeFactory } from './PipeFactory';
|
||||
import type { IPipelineCompiler } from './IPipelineCompiler';
|
||||
|
||||
export class PipelineCompiler implements IPipelineCompiler {
|
||||
constructor(private readonly factory: IPipeFactory = new PipeFactory()) { }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FunctionParameter } from '@/application/Parser/Script/Compiler/Function/Parameter/FunctionParameter';
|
||||
import { RegexParser, IPrimitiveExpression } from '../Parser/Regex/RegexParser';
|
||||
import { RegexParser, type IPrimitiveExpression } from '../Parser/Regex/RegexParser';
|
||||
import { ExpressionRegexBuilder } from '../Parser/Regex/ExpressionRegexBuilder';
|
||||
|
||||
export class ParameterSubstitutionParser extends RegexParser {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import { IExpressionParser } from '@/application/Parser/Script/Compiler/Expressions/Parser/IExpressionParser';
|
||||
import type { IExpressionParser } from '@/application/Parser/Script/Compiler/Expressions/Parser/IExpressionParser';
|
||||
import { FunctionParameterCollection } from '@/application/Parser/Script/Compiler/Function/Parameter/FunctionParameterCollection';
|
||||
import { FunctionParameter } from '@/application/Parser/Script/Compiler/Function/Parameter/FunctionParameter';
|
||||
import { IExpression } from '../Expression/IExpression';
|
||||
import { ExpressionPosition } from '../Expression/ExpressionPosition';
|
||||
import { ExpressionRegexBuilder } from '../Parser/Regex/ExpressionRegexBuilder';
|
||||
import { createPositionFromRegexFullMatch } from '../Expression/ExpressionPositionFactory';
|
||||
import type { IExpression } from '../Expression/IExpression';
|
||||
|
||||
export class WithParser implements IExpressionParser {
|
||||
public findExpressions(code: string): IExpression[] {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ensureValidParameterName } from '../../Shared/ParameterNameValidator';
|
||||
import { IFunctionCallArgument } from './IFunctionCallArgument';
|
||||
import type { IFunctionCallArgument } from './IFunctionCallArgument';
|
||||
|
||||
export class FunctionCallArgument implements IFunctionCallArgument {
|
||||
constructor(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IFunctionCallArgument } from './IFunctionCallArgument';
|
||||
import { IFunctionCallArgumentCollection } from './IFunctionCallArgumentCollection';
|
||||
import type { IFunctionCallArgument } from './IFunctionCallArgument';
|
||||
import type { IFunctionCallArgumentCollection } from './IFunctionCallArgumentCollection';
|
||||
|
||||
export class FunctionCallArgumentCollection implements IFunctionCallArgumentCollection {
|
||||
private readonly arguments = new Map<string, IFunctionCallArgument>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IFunctionCallArgument } from './IFunctionCallArgument';
|
||||
import type { IFunctionCallArgument } from './IFunctionCallArgument';
|
||||
|
||||
export interface IReadOnlyFunctionCallArgumentCollection {
|
||||
getArgument(parameterName: string): IFunctionCallArgument;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CompiledCode } from '../CompiledCode';
|
||||
import type { CompiledCode } from '../CompiledCode';
|
||||
|
||||
export interface CodeSegmentMerger {
|
||||
mergeCodeParts(codeSegments: readonly CompiledCode[]): CompiledCode;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CompiledCode } from '../CompiledCode';
|
||||
import { CodeSegmentMerger } from './CodeSegmentMerger';
|
||||
import type { CompiledCode } from '../CompiledCode';
|
||||
import type { CodeSegmentMerger } from './CodeSegmentMerger';
|
||||
|
||||
export class NewlineCodeSegmentMerger implements CodeSegmentMerger {
|
||||
public mergeCodeParts(codeSegments: readonly CompiledCode[]): CompiledCode {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ISharedFunctionCollection } from '@/application/Parser/Script/Compiler/Function/ISharedFunctionCollection';
|
||||
import { FunctionCall } from '../FunctionCall';
|
||||
import type { ISharedFunctionCollection } from '@/application/Parser/Script/Compiler/Function/ISharedFunctionCollection';
|
||||
import type { FunctionCall } from '../FunctionCall';
|
||||
import type { SingleCallCompiler } from './SingleCall/SingleCallCompiler';
|
||||
|
||||
export interface FunctionCallCompilationContext {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ISharedFunctionCollection } from '@/application/Parser/Script/Compiler/Function/ISharedFunctionCollection';
|
||||
import { FunctionCall } from '../FunctionCall';
|
||||
import { CompiledCode } from './CompiledCode';
|
||||
import type { ISharedFunctionCollection } from '@/application/Parser/Script/Compiler/Function/ISharedFunctionCollection';
|
||||
import type { CompiledCode } from './CompiledCode';
|
||||
import type { FunctionCall } from '../FunctionCall';
|
||||
|
||||
export interface FunctionCallCompiler {
|
||||
compileFunctionCalls(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { ISharedFunctionCollection } from '../../ISharedFunctionCollection';
|
||||
import { FunctionCallCompiler } from './FunctionCallCompiler';
|
||||
import { CompiledCode } from './CompiledCode';
|
||||
import { FunctionCallCompilationContext } from './FunctionCallCompilationContext';
|
||||
import { SingleCallCompiler } from './SingleCall/SingleCallCompiler';
|
||||
import { AdaptiveFunctionCallCompiler } from './SingleCall/AdaptiveFunctionCallCompiler';
|
||||
import { CodeSegmentMerger } from './CodeSegmentJoin/CodeSegmentMerger';
|
||||
import type { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { NewlineCodeSegmentMerger } from './CodeSegmentJoin/NewlineCodeSegmentMerger';
|
||||
import { AdaptiveFunctionCallCompiler } from './SingleCall/AdaptiveFunctionCallCompiler';
|
||||
import type { ISharedFunctionCollection } from '../../ISharedFunctionCollection';
|
||||
import type { FunctionCallCompiler } from './FunctionCallCompiler';
|
||||
import type { CompiledCode } from './CompiledCode';
|
||||
import type { FunctionCallCompilationContext } from './FunctionCallCompilationContext';
|
||||
import type { SingleCallCompiler } from './SingleCall/SingleCallCompiler';
|
||||
import type { CodeSegmentMerger } from './CodeSegmentJoin/CodeSegmentMerger';
|
||||
|
||||
export class FunctionCallSequenceCompiler implements FunctionCallCompiler {
|
||||
public static readonly instance: FunctionCallCompiler = new FunctionCallSequenceCompiler();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { FunctionCall } from '../../FunctionCall';
|
||||
import { CompiledCode } from '../CompiledCode';
|
||||
import { FunctionCallCompilationContext } from '../FunctionCallCompilationContext';
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '../../Argument/IFunctionCallArgumentCollection';
|
||||
import { ISharedFunction } from '../../../ISharedFunction';
|
||||
import { SingleCallCompiler } from './SingleCallCompiler';
|
||||
import { SingleCallCompilerStrategy } from './SingleCallCompilerStrategy';
|
||||
import { InlineFunctionCallCompiler } from './Strategies/InlineFunctionCallCompiler';
|
||||
import { NestedFunctionCallCompiler } from './Strategies/NestedFunctionCallCompiler';
|
||||
import type { FunctionCall } from '../../FunctionCall';
|
||||
import type { CompiledCode } from '../CompiledCode';
|
||||
import type { FunctionCallCompilationContext } from '../FunctionCallCompilationContext';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from '../../Argument/IFunctionCallArgumentCollection';
|
||||
import type { ISharedFunction } from '../../../ISharedFunction';
|
||||
import type { SingleCallCompiler } from './SingleCallCompiler';
|
||||
import type { SingleCallCompilerStrategy } from './SingleCallCompilerStrategy';
|
||||
|
||||
export class AdaptiveFunctionCallCompiler implements SingleCallCompiler {
|
||||
public constructor(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FunctionCall } from '../../FunctionCall';
|
||||
import { CompiledCode } from '../CompiledCode';
|
||||
import { FunctionCallCompilationContext } from '../FunctionCallCompilationContext';
|
||||
import type { FunctionCallCompilationContext } from '../FunctionCallCompilationContext';
|
||||
import type { FunctionCall } from '../../FunctionCall';
|
||||
import type { CompiledCode } from '../CompiledCode';
|
||||
|
||||
export interface SingleCallCompiler {
|
||||
compileSingleCall(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
|
||||
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { CompiledCode } from '../CompiledCode';
|
||||
import { FunctionCallCompilationContext } from '../FunctionCallCompilationContext';
|
||||
import type { ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
|
||||
import type { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import type { CompiledCode } from '../CompiledCode';
|
||||
import type { FunctionCallCompilationContext } from '../FunctionCallCompilationContext';
|
||||
|
||||
export interface SingleCallCompilerStrategy {
|
||||
canCompile(func: ISharedFunction): boolean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { FunctionCallCompilationContext } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||
import type { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import type { FunctionCallCompilationContext } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||
|
||||
export interface ArgumentCompiler {
|
||||
createCompiledNestedCall(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||
import { FunctionCallArgument } from '@/application/Parser/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||
import { FunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
||||
import { ExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/ExpressionsCompiler';
|
||||
import { IExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { FunctionCallCompilationContext } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||
import type { IExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||
import type { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import type { FunctionCallCompilationContext } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||
import { ParsedFunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/ParsedFunctionCall';
|
||||
import { ArgumentCompiler } from './ArgumentCompiler';
|
||||
import type { ArgumentCompiler } from './ArgumentCompiler';
|
||||
|
||||
export class NestedFunctionArgumentCompiler implements ArgumentCompiler {
|
||||
constructor(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/ExpressionsCompiler';
|
||||
import { IExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||
import { FunctionBodyType, ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
|
||||
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { CompiledCode } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/CompiledCode';
|
||||
import { SingleCallCompilerStrategy } from '../SingleCallCompilerStrategy';
|
||||
import type { IExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||
import { FunctionBodyType, type ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
|
||||
import type { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import type { CompiledCode } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/CompiledCode';
|
||||
import type { SingleCallCompilerStrategy } from '../SingleCallCompilerStrategy';
|
||||
|
||||
export class InlineFunctionCallCompiler implements SingleCallCompilerStrategy {
|
||||
public constructor(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { CallFunctionBody, FunctionBodyType, ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
|
||||
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import { FunctionCallCompilationContext } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||
import { CompiledCode } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/CompiledCode';
|
||||
import { SingleCallCompilerStrategy } from '../SingleCallCompilerStrategy';
|
||||
import { ArgumentCompiler } from './Argument/ArgumentCompiler';
|
||||
import { type CallFunctionBody, FunctionBodyType, type ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
|
||||
import type { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
|
||||
import type { FunctionCallCompilationContext } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||
import type { CompiledCode } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/CompiledCode';
|
||||
import { NestedFunctionArgumentCompiler } from './Argument/NestedFunctionArgumentCompiler';
|
||||
import type { SingleCallCompilerStrategy } from '../SingleCallCompilerStrategy';
|
||||
import type { ArgumentCompiler } from './Argument/ArgumentCompiler';
|
||||
|
||||
export class NestedFunctionCallCompiler implements SingleCallCompilerStrategy {
|
||||
public constructor(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from './Argument/IFunctionCallArgumentCollection';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from './Argument/IFunctionCallArgumentCollection';
|
||||
|
||||
export interface FunctionCall {
|
||||
readonly functionName: string;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { FunctionCallData, FunctionCallsData, FunctionCallParametersData } from '@/application/collections/';
|
||||
import { isArray, isPlainObject } from '@/TypeHelpers';
|
||||
import { FunctionCall } from './FunctionCall';
|
||||
import { FunctionCallArgumentCollection } from './Argument/FunctionCallArgumentCollection';
|
||||
import { FunctionCallArgument } from './Argument/FunctionCallArgument';
|
||||
import { ParsedFunctionCall } from './ParsedFunctionCall';
|
||||
import type { FunctionCall } from './FunctionCall';
|
||||
|
||||
export function parseFunctionCalls(calls: FunctionCallsData): FunctionCall[] {
|
||||
const sequence = getCallSequence(calls);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from './Argument/IFunctionCallArgumentCollection';
|
||||
import { FunctionCall } from './FunctionCall';
|
||||
import type { FunctionCall } from './FunctionCall';
|
||||
import type { IReadOnlyFunctionCallArgumentCollection } from './Argument/IFunctionCallArgumentCollection';
|
||||
|
||||
export class ParsedFunctionCall implements FunctionCall {
|
||||
constructor(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IReadOnlyFunctionParameterCollection } from './Parameter/IFunctionParameterCollection';
|
||||
import { FunctionCall } from './Call/FunctionCall';
|
||||
import type { IReadOnlyFunctionParameterCollection } from './Parameter/IFunctionParameterCollection';
|
||||
import type { FunctionCall } from './Call/FunctionCall';
|
||||
|
||||
export interface ISharedFunction {
|
||||
readonly name: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ISharedFunction } from './ISharedFunction';
|
||||
import type { ISharedFunction } from './ISharedFunction';
|
||||
|
||||
export interface ISharedFunctionCollection {
|
||||
getFunctionByName(name: string): ISharedFunction;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { FunctionData } from '@/application/collections/';
|
||||
import { ILanguageSyntax } from '@/application/Parser/Script/Validation/Syntax/ILanguageSyntax';
|
||||
import { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||
import type { ILanguageSyntax } from '@/application/Parser/Script/Validation/Syntax/ILanguageSyntax';
|
||||
import type { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||
|
||||
export interface ISharedFunctionsParser {
|
||||
parseFunctions(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ensureValidParameterName } from '../Shared/ParameterNameValidator';
|
||||
import { IFunctionParameter } from './IFunctionParameter';
|
||||
import type { IFunctionParameter } from './IFunctionParameter';
|
||||
|
||||
export class FunctionParameter implements IFunctionParameter {
|
||||
constructor(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IFunctionParameterCollection } from './IFunctionParameterCollection';
|
||||
import { IFunctionParameter } from './IFunctionParameter';
|
||||
import type { IFunctionParameterCollection } from './IFunctionParameterCollection';
|
||||
import type { IFunctionParameter } from './IFunctionParameter';
|
||||
|
||||
export class FunctionParameterCollection implements IFunctionParameterCollection {
|
||||
private parameters = new Array<IFunctionParameter>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IFunctionParameter } from './IFunctionParameter';
|
||||
import type { IFunctionParameter } from './IFunctionParameter';
|
||||
|
||||
export interface IReadOnlyFunctionParameterCollection {
|
||||
readonly all: readonly IFunctionParameter[];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user