Compare commits
257 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e34e64449 | ||
|
|
ce4cfdd169 | ||
|
|
12b1f183f7 | ||
|
|
4212c7b9e0 | ||
|
|
7794846185 | ||
|
|
150e067039 | ||
|
|
f347fde0c8 | ||
|
|
ff3d5c4841 | ||
|
|
292362135d | ||
|
|
aae5434451 | ||
|
|
2390530d92 | ||
|
|
9ab3ff75b0 | ||
|
|
d25c4e8c81 | ||
|
|
4a7efa27c8 | ||
|
|
cec0b4b4f6 | ||
|
|
a1922c50c1 | ||
|
|
870120bc13 | ||
|
|
f38cf73485 | ||
|
|
9fd193e676 | ||
|
|
52a4730073 | ||
|
|
bc4879cfe9 | ||
|
|
dd71536316 | ||
|
|
a3343205b1 | ||
|
|
1d7cafc831 | ||
|
|
c75df1c8c1 | ||
|
|
ab25e0a066 | ||
|
|
813d820b85 | ||
|
|
66a56888a4 | ||
|
|
4ef16cea56 | ||
|
|
8c17396285 | ||
|
|
694bf1a74d | ||
|
|
0fc2ffc1ea | ||
|
|
d19dde603d | ||
|
|
23bac0fc76 | ||
|
|
e18907ca91 | ||
|
|
4e21f05031 | ||
|
|
8b224eefe7 | ||
|
|
f261ab4cd9 | ||
|
|
f584fabb50 | ||
|
|
2eed6f4afb | ||
|
|
1c9dc93246 | ||
|
|
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 | ||
|
|
c7fa4b6d02 | ||
|
|
17152c84dc | ||
|
|
894687c0e0 | ||
|
|
fb08f03765 | ||
|
|
faa7a38a7d | ||
|
|
d5bbc321f9 | ||
|
|
ebd82853dd | ||
|
|
6142f3a297 | ||
|
|
63366a4ec2 | ||
|
|
55fa7eae71 | ||
|
|
a54e16488c | ||
|
|
b9c89b701f | ||
|
|
311fcb1813 | ||
|
|
aa4205ff7a | ||
|
|
937f4593d1 | ||
|
|
4da306b9f7 | ||
|
|
a5ffed4cd6 | ||
|
|
6ab6dacd1b | ||
|
|
d277139dd5 | ||
|
|
7af8daa341 | ||
|
|
d67100ad5e | ||
|
|
10829d65aa | ||
|
|
cd425502ae | ||
|
|
541f9aa5ee | ||
|
|
c6ebba85fb | ||
|
|
f94a1ffe11 | ||
|
|
6ada8d425c | ||
|
|
f03fc24098 | ||
|
|
756c736e21 | ||
|
|
e09db0f1bd | ||
|
|
c546a33eff | ||
|
|
da4be500da | ||
|
|
b404a91ada | ||
|
|
728584240c | ||
|
|
3b1a89ce86 | ||
|
|
c84a1bb74c | ||
|
|
bf7fb0732c | ||
|
|
dc30825232 | ||
|
|
40f5eb8334 | ||
|
|
fac72edd55 | ||
|
|
cdc32d1f12 | ||
|
|
8f4b34f8f1 | ||
|
|
86fde6d7dc | ||
|
|
2f06043559 | ||
|
|
fc9dd234e9 | ||
|
|
645c333787 | ||
|
|
efa05f42bc | ||
|
|
940febc3e8 | ||
|
|
3f62bb2d6e | ||
|
|
e95b2ba217 | ||
|
|
20633972e9 | ||
|
|
3457fe18cf | ||
|
|
fe3de498c8 | ||
|
|
15134ea04b | ||
|
|
a9851272ae | ||
|
|
916c9d62d9 | ||
|
|
47b4823bc5 | ||
|
|
c72f9f5016 | ||
|
|
e747ee5cbc | ||
|
|
ba5b29a35d | ||
|
|
daa6230fc9 | ||
|
|
4765752ee3 | ||
|
|
25e23c89c3 | ||
|
|
08dbfead7c | ||
|
|
8f5d7ed3cf | ||
|
|
807ae6a8f8 | ||
|
|
5a7d7d88ff | ||
|
|
40ae8a8add | ||
|
|
6488e81901 | ||
|
|
d328f08952 | ||
|
|
bcad357017 | ||
|
|
9845a7cd68 | ||
|
|
7c632f7388 | ||
|
|
1442f62633 | ||
|
|
7f7a84e3ba | ||
|
|
dee3279f85 | ||
|
|
094dbb01b8 | ||
|
|
e299d40fa1 | ||
|
|
cb42f11b97 | ||
|
|
4531645b4c | ||
|
|
bf3426f91b | ||
|
|
3864f04218 | ||
|
|
e541a35e86 | ||
|
|
bd383ed273 | ||
|
|
949fac1a7c | ||
|
|
7ab16ecccb | ||
|
|
58cd551a30 | ||
|
|
7770a9b521 | ||
|
|
aab0f7ea46 | ||
|
|
ea41f4f503 | ||
|
|
af7219f6e1 | ||
|
|
8ccaec7af6 | ||
|
|
b2ffc90da7 | ||
|
|
72e4d0b896 | ||
|
|
5bb13e34f8 | ||
|
|
0466b86f10 | ||
|
|
ca81f68ff1 | ||
|
|
4995e49c46 | ||
|
|
77123d8c92 | ||
|
|
e72c1c13ea | ||
|
|
e775d68a9b | ||
|
|
f8e5f1a5a2 | ||
|
|
f4a74f058d | ||
|
|
80821fca07 | ||
|
|
dfd4451561 | ||
|
|
8570b02dde | ||
|
|
d6da406c61 | ||
|
|
060e789662 | ||
|
|
e40b9a3cf5 | ||
|
|
237d9944f9 | ||
|
|
79b46bf210 | ||
|
|
98a26f9ae4 | ||
|
|
dbe3c5cfb9 | ||
|
|
25d7f7b2a4 | ||
|
|
b76e99ac0f | ||
|
|
67c3677621 | ||
|
|
bab6316e76 | ||
|
|
48730bca05 | ||
|
|
698b570ee6 | ||
|
|
a3f11dff18 | ||
|
|
5e359c2fb8 | ||
|
|
2147eae687 | ||
|
|
286295128d | ||
|
|
8501495c17 | ||
|
|
888c9166fc | ||
|
|
e5f6edf405 | ||
|
|
e8a52f717d | ||
|
|
d45750428c | ||
|
|
cf55ca9e28 | ||
|
|
3e5239f7d3 | ||
|
|
7669985f8e | ||
|
|
5047c9b6e7 | ||
|
|
bd2082e8c5 | ||
|
|
8f188acd3c | ||
|
|
0303ef2fd9 | ||
|
|
cb21a970b6 | ||
|
|
203daeb4a2 | ||
|
|
60dde11311 | ||
|
|
8b930fc57c | ||
|
|
f810ed0c14 | ||
|
|
53222fd83c | ||
|
|
a1f2497381 | ||
|
|
c27172c32e | ||
|
|
6e9b65d8b1 | ||
|
|
6d301f9961 | ||
|
|
659fea7afc | ||
|
|
e0303058a3 | ||
|
|
65f121c451 | ||
|
|
821cc62c4c | ||
|
|
4ce327eb6a | ||
|
|
4beb1bb574 | ||
|
|
0a2a1a026b | ||
|
|
eb096d07e2 | ||
|
|
19e42c9c52 | ||
|
|
f4d86fccfd | ||
|
|
ad0576a752 | ||
|
|
35be05df20 | ||
|
|
dae6d114da | ||
|
|
ecce47fdcd | ||
|
|
e9e0001ef8 | ||
|
|
62f8bfac2f | ||
|
|
75c9b51bf2 | ||
|
|
ec98d8417f | ||
|
|
736590558b | ||
|
|
6e40edd3f8 | ||
|
|
5f11c8d98f | ||
|
|
08737698c2 | ||
|
|
04b3133500 | ||
|
|
0d15992d56 | ||
|
|
a14929a13c | ||
|
|
6a20d804dc | ||
|
|
ae75059cc1 | ||
|
|
39e650cf11 | ||
|
|
bc91237d7c | ||
|
|
9e5491fdbf | ||
|
|
986ba078a6 | ||
|
|
061afad967 | ||
|
|
3bc8da4cbf | ||
|
|
1b9be8fe2d | ||
|
|
3a594ac7fd |
@@ -1,7 +1,33 @@
|
|||||||
[*.{js,jsx,ts,tsx,vue,sh}]
|
root = true # Top-most EditorConfig file
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
|
||||||
|
[*.{js,jsx,ts,tsx,vue,sh,scss}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
end_of_line = lf
|
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
max_line_length = 100
|
max_line_length = 100
|
||||||
|
|
||||||
|
[{Dockerfile}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4 # PEP 8 (the official Python style guide) recommends using 4 spaces per indentation level
|
||||||
|
indent_style = space
|
||||||
|
max_line_length = 100
|
||||||
|
|
||||||
|
[*.ps1]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{scss}] # SASS guidelines: https://archive.today/2024.02.16-232553/https://sass-guidelin.es/
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2 # Recommended by SASS guidelines
|
||||||
|
max_line_length = 100 # Recommended by SASS guidelines
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
dist/
|
|
||||||
@@ -6,53 +6,26 @@ module.exports = {
|
|||||||
root: true,
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
node: true,
|
node: true,
|
||||||
|
es2022: true, // add globals and sets parserOptions.ecmaVersion to 2022
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
// Vue specific rules, eslint-plugin-vue
|
// Vue specific base rules, `eslint-plugin-vue`
|
||||||
// Added by Vue CLI
|
'plugin:vue/vue3-recommended',
|
||||||
'plugin:vue/essential',
|
|
||||||
|
|
||||||
// Extends eslint-config-airbnb
|
// Extends `eslint-config-airbnb`
|
||||||
'@vue/eslint-config-airbnb-with-typescript',
|
'@vue/eslint-config-airbnb-with-typescript',
|
||||||
|
|
||||||
// Extends @typescript-eslint/recommended
|
// - Sets base parser and plugin options.
|
||||||
// Uses the recommended rules from the @typescript-eslint/eslint-plugin
|
// - Includes `plugin:@typescript-eslint/recommended`. But incompatible with
|
||||||
// Added by Vue CLI
|
// `strict-type-checked` and `stylistic-type-checked`, see https://github.com/vuejs/eslint-config-typescript/issues/67.
|
||||||
'@vue/typescript/recommended',
|
'@vue/typescript/recommended',
|
||||||
],
|
],
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 12, // ECMA 2021
|
|
||||||
/*
|
|
||||||
Having 'latest' leads to:
|
|
||||||
```
|
|
||||||
Parsing error: ecmaVersion must be a number. Received value of type string instead
|
|
||||||
```
|
|
||||||
For .js files in the project
|
|
||||||
*/
|
|
||||||
},
|
|
||||||
rules: {
|
rules: {
|
||||||
...getOwnRules(),
|
...getOwnRules(),
|
||||||
...getTurnedOffBrokenRules(),
|
...getTurnedOffBrokenRules(),
|
||||||
...getOpinionatedRuleOverrides(),
|
...getOpinionatedRuleOverrides(),
|
||||||
...getTodoRules(),
|
...getTodoRules(),
|
||||||
},
|
},
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'**/__tests__/*.{j,t}s?(x)',
|
|
||||||
'**/tests/unit/**/*.spec.{j,t}s?(x)',
|
|
||||||
],
|
|
||||||
env: {
|
|
||||||
mocha: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['**/tests/**/*.{j,t}s?(x)'],
|
|
||||||
rules: {
|
|
||||||
'no-console': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getOwnRules() {
|
function getOwnRules() {
|
||||||
57
.github/ISSUE_TEMPLATE/1-bug-report-scripts.md
vendored
@@ -1,57 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report (script bug or unexpected script behavior)
|
|
||||||
about: Create a bug report for generated scripts to help privacy.sexy improve
|
|
||||||
labels: bug
|
|
||||||
title: '[BUG]: '
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for reporting an issue with generated script(s).
|
|
||||||
Please fill in as much of the template below as you're able.
|
|
||||||
As a small open source project with small community, it can sometimes take a long time for issues to be addressed so please be patient.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### OS
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Which OS are you using? What version of OS you were using?
|
|
||||||
On Windows: Open "Start button" > "Settings" > "System" > "About".
|
|
||||||
On macOS: Open "Apple menu (top left corner)" > "About This Mac".
|
|
||||||
On Linux: Open terminal > type: lsb_release -a > copy paste the result.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Reproduction steps
|
|
||||||
|
|
||||||
<!--
|
|
||||||
How can the bug be recreated?
|
|
||||||
It's the most important information in the bug report. Bugs that cannot be reproduced cannot be fixed and verified.
|
|
||||||
E.g.
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Scripts
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, please attach the generated privacy.sexy file instead of copy pasting which becomes too long.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Screenshots
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional information
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, add any other context about the problem here.
|
|
||||||
-->
|
|
||||||
114
.github/ISSUE_TEMPLATE/1-bug-report-scripts.yaml
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
name: "Bug Report: Script Issues"
|
||||||
|
description: 🐛 Report issues with generated scripts to enhance privacy.sexy
|
||||||
|
labels: [ 'bug' ]
|
||||||
|
title: '[Bug]: '
|
||||||
|
body:
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
Thank you for contributing to privacy.sexy and guiding our direction! 🌟
|
||||||
|
Please complete as much of the form below as possible.
|
||||||
|
Your feedback is valuable, even if you can't provide all details.
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "After running the cleanup script, music playback stopped functioning."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: How can the bug be recreated?
|
||||||
|
description: |-
|
||||||
|
This is the most important information in the bug report.
|
||||||
|
Bugs that cannot be reproduced cannot be fixed or verified.
|
||||||
|
placeholder: |-
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Operating system
|
||||||
|
description: |-
|
||||||
|
Please specify your operating system and its version.
|
||||||
|
|
||||||
|
- On Windows: Open "Start button" > "Settings" > "System" > "About".
|
||||||
|
- On macOS: Open "Apple menu (top left corner)" > "About This Mac".
|
||||||
|
- On Linux: Open terminal > type: lsb_release -a > copy paste the result.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Windows 11 Pro 22H3"
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Script file
|
||||||
|
description: |-
|
||||||
|
If applicable, share the generated privacy.sexy file.
|
||||||
|
|
||||||
|
GitHub may restrict script file attachments.
|
||||||
|
Upload your script file to a service like [GitHub Gist](https://gist.github.com/) and share the link here.
|
||||||
|
|
||||||
|
If you used the desktop version to run the script, it is already stored on your system.
|
||||||
|
See the [documentation to locate it](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/desktop/desktop-vs-web-features.md#secure-script-executionstorage).
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach script files by dragging them into this area.
|
||||||
|
placeholder: |-
|
||||||
|
Attach the script, or post GitHub Gist link.
|
||||||
|
For example: https://gist.github.com/privacysexy-forks/6d85ad8ca27acc8c6a5417d4af28c9b6.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: |-
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach screenshots by clicking this area to highlight it and then pasting them or dragging files in.
|
||||||
|
placeholder: Attach screenshots here or link to image hosting.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: |-
|
||||||
|
If applicable, add any other context about the problem here.
|
||||||
|
|
||||||
|
Helpful information includes:
|
||||||
|
|
||||||
|
- Application logs (desktop version only), see: [how to find application logs](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/desktop/desktop-vs-web-features.md#logging).
|
||||||
|
- Terminal output
|
||||||
|
- Proposed solutions
|
||||||
|
- Other related context such as related issues, software behavior, etc.
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach log files by dragging them into this area.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Here are the logs I get from the privacy.sexy 0.13.2 desktop application: ..."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
---
|
||||||
|
|
||||||
|
**✉️ A friendly note from the maintainer:**
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> We are a small open-source project with a small community.
|
||||||
|
> It can sometimes take a long time for issues to be addressed, so please be patient.
|
||||||
|
> Consider [donating](https://undergroundwires.dev/donate) to keep privacy.sexy alive and improve support ❤️.
|
||||||
|
> But your issue will eventually get attention regardless.
|
||||||
|
> <p align="right">@undergroundwires</p>
|
||||||
|
|
||||||
|
---
|
||||||
104
.github/ISSUE_TEMPLATE/2-bug-report-general.yaml
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
name: "Bug Report: General"
|
||||||
|
description: 🐛 Report general issues to enhance privacy.sexy
|
||||||
|
labels: [ 'bug' ]
|
||||||
|
title: '[Bug]: '
|
||||||
|
body:
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
Thank you for contributing to privacy.sexy and guiding our direction! 🌟
|
||||||
|
Please complete as much of the form below as possible.
|
||||||
|
Your feedback is valuable, even if you can't provide all details.
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Provide a clear and concise description of the issue.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "I cannot select any scripts."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Reproduction steps
|
||||||
|
description: |-
|
||||||
|
This is the most important information in the bug report.
|
||||||
|
Bugs that cannot be reproduced cannot be fixed or verified.
|
||||||
|
placeholder: |-
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: Describe what you expected to happen when the error occurred.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "I expected the settings menu to open smoothly without crashing.".
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: |-
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach screenshots by clicking this area to highlight it and then pasting them or dragging files in.
|
||||||
|
placeholder: >-
|
||||||
|
Attach screenshots here or link to image hosting.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: privacy.sexy environment details
|
||||||
|
description: |-
|
||||||
|
If applicable, mention how you were using privacy.sexy when the bug occurred:
|
||||||
|
|
||||||
|
- Web (on which operating system and browser?)
|
||||||
|
- Or desktop (Windows, macOS, or Linux?)
|
||||||
|
placeholder: >-
|
||||||
|
For example: "The web version on Edge browser on Windows 11 23H2."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: |-
|
||||||
|
If applicable, add any other context about the problem here.
|
||||||
|
|
||||||
|
Helpful information includes:
|
||||||
|
|
||||||
|
- Application logs (desktop version only), see: [how to find application logs](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/desktop/desktop-vs-web-features.md#logging).
|
||||||
|
- Terminal output
|
||||||
|
- Proposed solutions
|
||||||
|
- Other related context such as related issues, software behavior, etc.
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach log files by dragging them into this area.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Here are the logs I get from the privacy.sexy 0.13.2 desktop application: ..."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
---
|
||||||
|
|
||||||
|
**✉️ A friendly note from the maintainer:**
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> We are a small open-source project with a small community.
|
||||||
|
> It can sometimes take a long time for issues to be addressed, so please be patient.
|
||||||
|
> Consider [donating](https://undergroundwires.dev/donate) to keep privacy.sexy alive and improve support ❤️.
|
||||||
|
> But your issue will eventually get attention regardless.
|
||||||
|
> <p align="right">@undergroundwires</p>
|
||||||
|
|
||||||
|
---
|
||||||
55
.github/ISSUE_TEMPLATE/2-bug-report-generic.md
vendored
@@ -1,55 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report (unrelated to generated scripts)
|
|
||||||
about: Create a bug report that's not related to generated scripts to help privacy.sexy improve
|
|
||||||
labels: bug
|
|
||||||
title: '[BUG]: '
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for reporting an issue.
|
|
||||||
Please fill in as much of the template below as you're able.
|
|
||||||
As a small open source project with small community, it can sometimes take a long time for issues to be addressed so please be patient.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Reproduction steps
|
|
||||||
|
|
||||||
<!--
|
|
||||||
It's the most important information in the bug report. Bugs that cannot be reproduced cannot be fixed and verified.
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Expected behavior
|
|
||||||
|
|
||||||
<!--
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Screenshots
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Distribution
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, mention how you were using privacy.sexy when the bug was encountered:
|
|
||||||
- Web (on Desktop or mobile?)
|
|
||||||
- Or desktop (Windows, macOS or Linux?)
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional context
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, add any other context about the problem here.
|
|
||||||
-->
|
|
||||||
36
.github/ISSUE_TEMPLATE/3-feature-request.md
vendored
@@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for privacy.sexy
|
|
||||||
labels: enhancement
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for suggesting an idea to improve privacy better 🤗.
|
|
||||||
Please fill in as much of the template below as you're able.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Problem description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
What are we trying to solve?
|
|
||||||
Please add a clear and concise description of the problem you are seeking to solve with this feature request.
|
|
||||||
E.g. I'm always frustrated when [...]
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Proposed solution
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Describe the solution you'd like in a clear and concise manner.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Alternatives considered
|
|
||||||
|
|
||||||
<!--
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional information
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, add any other context or screenshots about the feature request here.
|
|
||||||
-->
|
|
||||||
73
.github/ISSUE_TEMPLATE/3-suggestion-feature.yaml
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
name: "Suggestion: Feature"
|
||||||
|
description: 💡 Suggest new ideas to enhance privacy.sexy
|
||||||
|
labels: [ 'enhancement' ]
|
||||||
|
title: '[Feature]: '
|
||||||
|
body:
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
Thank you for contributing to privacy.sexy and guiding our direction! 🌟
|
||||||
|
Please complete as much of the form below as possible.
|
||||||
|
Your feedback is valuable, even if you can't provide all details.
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Problem statement
|
||||||
|
description: |-
|
||||||
|
What are we trying to solve?
|
||||||
|
|
||||||
|
Please add a clear and concise description of the problem you are seeking to solve with this feature request.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Every time I use the app, I struggle with..."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Proposed solution
|
||||||
|
description: |-
|
||||||
|
Describe the solution you'd like in a clear and concise manner.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "It would be great if the app could..."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Alternatives considered
|
||||||
|
description: |-
|
||||||
|
Have you considered any alternative solutions or features?
|
||||||
|
Different perspectives can inspire new ideas.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "We could also solve it by...".
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: |-
|
||||||
|
If applicable, add any other context or screenshots about the feature request here.
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach files or screenshots by dragging them into this area.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Challenges can be ..., but I'm unsure about ..., here is some documentation about it: ..."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
---
|
||||||
|
|
||||||
|
**✉️ A friendly note from the maintainer:**
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> We are a small open-source project with a small community.
|
||||||
|
> It can sometimes take a long time for issues to be addressed, so please be patient.
|
||||||
|
> Consider [donating](https://undergroundwires.dev/donate) to keep privacy.sexy alive and improve support ❤️.
|
||||||
|
> But your issue will eventually get attention regardless.
|
||||||
|
> <p align="right">@undergroundwires</p>
|
||||||
|
|
||||||
|
---
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
---
|
|
||||||
name: New script suggestion
|
|
||||||
about: Suggest a new script for privacy.sexy
|
|
||||||
labels: enhancement
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for suggesting an script to make privacy better. 🤗
|
|
||||||
Please fill in as much of the template below as you're able.
|
|
||||||
You could alternatively send a PR directly (see CONTRIBUTING.md).
|
|
||||||
-->
|
|
||||||
|
|
||||||
### OS
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Which OS will the new script configure?
|
|
||||||
One of the supported OSes: "Windows", "macOS" or "Linux".
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Name
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The name of the script.
|
|
||||||
It should start with an imperative noun such as "disable", "turn off" , "clear"...
|
|
||||||
E.g. "Disable webcam telemetry"
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Script code
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Code that will be executed when script is selected.
|
|
||||||
Try to keep it as simple and backwards-compatible as possible.
|
|
||||||
Allowed languages:
|
|
||||||
- Windows: PowerShell (ps1) or batchfile
|
|
||||||
- 💡 Prioritize the one that's simpler, batchfile if similar.
|
|
||||||
- macOS: bash (sh)
|
|
||||||
- Linux: bash (sh) or Python 3
|
|
||||||
- 💡 Prioritize the one that's simpler, bash if similar.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Revert code
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, add code that will revert the script code to its original (OS default) state.
|
|
||||||
It may require additional time, but it's much appreciated by the community.
|
|
||||||
Leave blank if the script is nonreversible (e.g. when clearing data without backup).
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Suggested category
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, suggest one more multiple suitable parent category of script.
|
|
||||||
A category is the item where the script will be presented under.
|
|
||||||
Most likely there already is a category for the script, so check the existing categories.
|
|
||||||
If you're unsure, leave blank and maintainer(s) will choose one.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Suggested recommendation level
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, suggest recommending the script or not recommending at all.
|
|
||||||
A script should be only recommended if it'll be safe for your grandmother to run.
|
|
||||||
So you have three options here:
|
|
||||||
STANDARD: Non-breaking scripts that does not limit any functionality.
|
|
||||||
STRICT: Scripts that can break certain functionality but not intrusive to common daily OS usage.
|
|
||||||
NONE: Script is not recommended for newbies at all, only those who knows what's going on should select it.
|
|
||||||
If you're unsure, leave blank and maintainer(s) will choose one.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional documentation/references
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If applicable, refer to documentation that should show up on the script description.
|
|
||||||
Sources (URLs) should be as high quality as possible e.g. vendor documentation is favored over user forums.
|
|
||||||
-->
|
|
||||||
133
.github/ISSUE_TEMPLATE/4-suggestion-new-script.yaml
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
name: "Suggestion: New Script"
|
||||||
|
description: 💡 Suggest new scripts to enhance privacy.sexy
|
||||||
|
labels: [ 'enhancement' ]
|
||||||
|
title: '[New script]: '
|
||||||
|
body:
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
Thank you for contributing to privacy.sexy and guiding our direction! 🌟
|
||||||
|
Please complete as much of the form below as possible.
|
||||||
|
Your feedback is valuable, even if you can't provide all details.
|
||||||
|
|
||||||
|
For guidance, see our [script guidelines](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/script-guidelines.md).
|
||||||
|
Consider submitting a PR to get your script added more quickly: (see [CONTRIBUTING.md](https://github.com/undergroundwires/privacy.sexy/blob/master/CONTRIBUTING.md#extend-scripts))
|
||||||
|
-
|
||||||
|
type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: Operating system
|
||||||
|
description: Which operating system will the new script configure?
|
||||||
|
options:
|
||||||
|
- macOS
|
||||||
|
- Windows
|
||||||
|
- Linux
|
||||||
|
- All of them
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Name of the script
|
||||||
|
description: |-
|
||||||
|
Suggest a name for the script that clearly describes its function.
|
||||||
|
|
||||||
|
See [script naming conventions](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/script-guidelines.md#name) for best practices.
|
||||||
|
placeholder: E.g, "Disable error data submission"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Documentation/References
|
||||||
|
description: |-
|
||||||
|
Provide any relevant documentation or references.
|
||||||
|
Prefer high-quality sources such as vendor documentation.
|
||||||
|
|
||||||
|
See [documentation guidelines](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/script-guidelines.md#documentation) for best practices.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "This script will disable the error data submission, see https://microsoft.com/...".
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Code
|
||||||
|
description: |-
|
||||||
|
If possible, provide or explain the code that the script should execute.
|
||||||
|
|
||||||
|
See [script code guidelines](https://github.com/undergroundwires/privacy.sexy/blob/master/docs/script-guidelines.md#code).
|
||||||
|
placeholder: |-
|
||||||
|
For example: "Set registry key like this `reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" /v "AllowTelemetry" /t "REG_DWORD" /d "1"`".
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Revert code
|
||||||
|
description: |-
|
||||||
|
If applicable, provide revert code to restore the changes made by the script.
|
||||||
|
|
||||||
|
The revert code restores changes to their default state before script execution.
|
||||||
|
|
||||||
|
Leave blank for non-reversible scripts.
|
||||||
|
placeholder: |-
|
||||||
|
For example: "Revert to operating system default like this `reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" /v "AllowTelemetry" /t "REG_DWORD" /d "0"`".
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Suggested category
|
||||||
|
description: |-
|
||||||
|
Suggest a category for the script.
|
||||||
|
|
||||||
|
If unsure, leave blank for maintainers to decide.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Privacy Cleanup > Clear system logs"
|
||||||
|
-
|
||||||
|
type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: Recommendation level
|
||||||
|
description: |-
|
||||||
|
Suggest a recommendation level for the script:
|
||||||
|
|
||||||
|
- **Standard**: Recommended for most users without side-effects.
|
||||||
|
- **Strict**: Provides improved privacy at the cost of some functionality.
|
||||||
|
- **None**: For advanced users or specific needs.
|
||||||
|
|
||||||
|
If unsure, leave blank for maintainers to decide.
|
||||||
|
options:
|
||||||
|
- Standard
|
||||||
|
- Strict
|
||||||
|
- None (do not recommend)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: |-
|
||||||
|
If applicable, add any other context or screenshots about the script request here.
|
||||||
|
|
||||||
|
> **💡 Tip:** You can attach additional documents or screenshots by dragging them into this area or pasting directly.
|
||||||
|
placeholder: >-
|
||||||
|
For example: "Challenges can be ..., but I am unsure about ..."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
-
|
||||||
|
type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
---
|
||||||
|
|
||||||
|
**✉️ A friendly note from the maintainer:**
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> We are a small open-source project with a small community.
|
||||||
|
> It can sometimes take a long time for issues to be addressed, so please be patient.
|
||||||
|
> Consider [donating](https://undergroundwires.dev/donate) to keep privacy.sexy alive and improve support ❤️.
|
||||||
|
> But your issue will eventually get attention regardless.
|
||||||
|
> <p align="right">@undergroundwires</p>
|
||||||
|
|
||||||
|
---
|
||||||
6
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1 +1,7 @@
|
|||||||
|
# This file must be named `config.yml`. GitHub does not recognize the file if it is named `config.yaml`.
|
||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
|
contact_links:
|
||||||
|
- name: Donate
|
||||||
|
url: https://undergroundwires.dev/donate/
|
||||||
|
about: ❤️ Donate to support the free software you love to keep it alive.
|
||||||
|
# A separate link for reporting vulnerabilities is not included here because GitHub generates it automatically.
|
||||||
|
|||||||
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
@@ -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
@@ -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
|
||||||
12
.github/actions/npm-install-dependencies/action.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
required: false
|
||||||
|
default: '.'
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Run `npm ci` with retries
|
||||||
|
shell: bash
|
||||||
|
run: npm run install-deps -- --ci
|
||||||
|
working-directory: ${{ inputs.working-directory }}
|
||||||
5
.github/actions/setup-node/action.yml
vendored
@@ -3,6 +3,7 @@ runs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Setup node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 16.x
|
node-version: 20.x
|
||||||
|
# check-latest: true # Newest versions can potentially have undiscovered bugs or regressions
|
||||||
|
|||||||
86
.github/workflows/checks.build.yaml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: build-checks
|
name: checks.build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -9,67 +9,101 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ macos, ubuntu, windows ]
|
os: [ macos, ubuntu, windows ]
|
||||||
mode: [ development, test, production ]
|
mode: [
|
||||||
|
# Vite mode: https://vitejs.dev/guide/env-and-mode.html
|
||||||
|
development, # Used by `dev` command
|
||||||
|
production, # Used by `build` command
|
||||||
|
# Vitest mode: https://vitest.dev/guide/cli.html
|
||||||
|
test, # Used by Vitest
|
||||||
|
]
|
||||||
fail-fast: false # Allows to see results from other combinations
|
fail-fast: false # Allows to see results from other combinations
|
||||||
runs-on: ${{ matrix.os }}-latest
|
runs-on: ${{ matrix.os }}-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
run: npm ci
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build web
|
||||||
run: npm run build -- --mode ${{ matrix.mode }}
|
run: npm run build -- --mode ${{ matrix.mode }}
|
||||||
|
-
|
||||||
|
name: Verify web build artifacts
|
||||||
|
run: npm run check:verify-build-artifacts -- --web
|
||||||
|
|
||||||
# A new job is used due to environments/modes different from Vue CLI, https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1626
|
|
||||||
build-desktop:
|
build-desktop:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ macos, ubuntu, windows ]
|
os: [ macos, ubuntu, windows ]
|
||||||
mode: [ development, production ] # "test" is not supported https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1627
|
mode: [
|
||||||
|
# electron-vite modes: https://electron-vite.org/guide/env-and-mode.html#global-env-variables
|
||||||
|
development, # Used by `dev` command
|
||||||
|
production, # Used by `build` and `preview` commands
|
||||||
|
]
|
||||||
fail-fast: false # Allows to see results from other combinations
|
fail-fast: false # Allows to see results from other combinations
|
||||||
runs-on: ${{ matrix.os }}-latest
|
runs-on: ${{ matrix.os }}-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
run: npm ci
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
-
|
-
|
||||||
name: Install cross-env
|
name: Prebuild desktop
|
||||||
# Used to set NODE_ENV due to https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1626
|
run: npm run electron:prebuild -- --mode ${{ matrix.mode }}
|
||||||
run: npm install --global cross-env
|
|
||||||
-
|
-
|
||||||
name: Build
|
name: Verify unbundled desktop build artifacts
|
||||||
run: |-
|
run: npm run check:verify-build-artifacts -- --electron-unbundled
|
||||||
cross-env-shell NODE_ENV=${{ matrix.mode }}
|
-
|
||||||
npm run electron:build -- --publish never --mode ${{ matrix.mode }}
|
name: Build (bundle and package) desktop application
|
||||||
|
run: npm run electron:build -- --publish never
|
||||||
|
-
|
||||||
|
name: Verify bundled desktop build artifacts
|
||||||
|
run: npm run check:verify-build-artifacts -- --electron-bundled
|
||||||
|
|
||||||
create-icons:
|
build-docker:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ macos, ubuntu, windows ]
|
os:
|
||||||
|
- macos-13 # Downgraded due to lack of nested virtualization support in ARM-based runners (See: actions/runner-images#9460, actions/runner-images#9741, abiosoft/colima#1023)
|
||||||
|
- ubuntu-latest
|
||||||
|
# - windows-latest # Windows runners do not support Linux containers
|
||||||
fail-fast: false # Allows to see results from other combinations
|
fail-fast: false # Allows to see results from other combinations
|
||||||
runs-on: ${{ matrix.os }}-latest
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Install Docker on macOS
|
||||||
uses: ./.github/actions/setup-node
|
if: contains(matrix.os, 'macos') # macOS runner is missing Docker
|
||||||
|
run: |-
|
||||||
|
# Install Docker
|
||||||
|
brew install docker
|
||||||
|
# Docker on macOS misses daemon due to licensing, so install colima as runtime
|
||||||
|
brew install colima
|
||||||
|
# Start the daemon
|
||||||
|
colima start
|
||||||
-
|
-
|
||||||
name: Install dependencies
|
name: Build Docker image
|
||||||
run: npm ci
|
run: docker build -t undergroundwires/privacy.sexy:latest .
|
||||||
-
|
-
|
||||||
name: Create icons
|
name: Run Docker image on port 8080
|
||||||
run: npm run create-icons
|
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 \
|
||||||
|
--max-retries ${{ matrix.os == 'macos' && '90' || '30' }}
|
||||||
|
|||||||
76
.github/workflows/checks.desktop-runtime-errors.yaml
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: checks.desktop-runtime-errors
|
||||||
|
# Verifies desktop builds for Electron applications across multiple OS platforms (macOS ,Ubuntu, and Windows).
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-check:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- macos-latest # Apple silicon (ARM64)
|
||||||
|
- macos-13 # Intel-based (x86-64)
|
||||||
|
- ubuntu-latest
|
||||||
|
- windows-latest
|
||||||
|
fail-fast: false # Allows to see results from other combinations
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Setup node
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
-
|
||||||
|
name: Install dependencies
|
||||||
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
|
-
|
||||||
|
name: Configure Ubuntu
|
||||||
|
if: contains(matrix.os, 'ubuntu') # macOS runner is missing Docker
|
||||||
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
sudo apt update
|
||||||
|
|
||||||
|
# Configure AppImage dependencies
|
||||||
|
sudo apt install -y libfuse2
|
||||||
|
|
||||||
|
# Configure DBUS (fixes `Failed to connect to the bus: Could not parse server address: Unknown address type`)
|
||||||
|
if ! command -v 'dbus-launch' &> /dev/null; then
|
||||||
|
echo 'DBUS does not exist, installing...'
|
||||||
|
sudo apt install -y dbus-x11 # Gives both dbus and dbus-launch utility
|
||||||
|
fi
|
||||||
|
sudo systemctl start dbus
|
||||||
|
DBUS_LAUNCH_OUTPUT=$(dbus-launch)
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "${DBUS_LAUNCH_OUTPUT}" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo 'Error: dbus-launch command did not execute successfully. Exiting.' >&2
|
||||||
|
echo "${DBUS_LAUNCH_OUTPUT}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure fake (virtual) display
|
||||||
|
sudo apt install -y xvfb
|
||||||
|
sudo Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||||
|
echo "DISPLAY=:99" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Install ImageMagick for screenshots
|
||||||
|
sudo apt install -y imagemagick
|
||||||
|
|
||||||
|
# Install xdotool and xprop (from x11-utils) for window title capturing
|
||||||
|
sudo apt install -y xdotool x11-utils
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
export SCREENSHOT=true
|
||||||
|
npm run check:desktop
|
||||||
|
-
|
||||||
|
name: Upload screenshot
|
||||||
|
if: always() # Run even if previous step fails
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: screenshot-${{ matrix.os }}
|
||||||
|
path: screenshot.png
|
||||||
30
.github/workflows/checks.external-urls.yaml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: checks.external-urls
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # at 00:00 on every Sunday
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Setup node
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
-
|
||||||
|
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.
|
||||||
66
.github/workflows/checks.quality.yaml
vendored
@@ -1,10 +1,10 @@
|
|||||||
name: quality-checks
|
name: checks.quality
|
||||||
|
|
||||||
on: [ push, pull_request ]
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
lint-command:
|
lint-command:
|
||||||
@@ -16,11 +16,61 @@ jobs:
|
|||||||
os: [ macos, ubuntu, windows ]
|
os: [ macos, ubuntu, windows ]
|
||||||
fail-fast: false # Still interested to see results from other combinations
|
fail-fast: false # Still interested to see results from other combinations
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
-
|
||||||
uses: actions/checkout@v2
|
name: Checkout
|
||||||
- name: Setup node
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
- name: Install dependencies
|
-
|
||||||
run: npm ci
|
name: Install dependencies
|
||||||
- name: Lint
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
|
-
|
||||||
|
name: Lint
|
||||||
run: ${{ matrix.lint-command }}
|
run: ${{ matrix.lint-command }}
|
||||||
|
|
||||||
|
todo-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Scan latest commit for TODO comments
|
||||||
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
readonly todo_comment_search_pattern='TODO'':' # Define search pattern in parts to prevent IDE from flagging this script line as a TODO item
|
||||||
|
if git grep "$todo_comment_search_pattern" HEAD; then
|
||||||
|
echo 'TODO comments found in the latest commit.'
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo 'No TODO comments found in the latest commit.'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pylint:
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ macos, ubuntu, windows ]
|
||||||
|
fail-fast: false # Still interested to see results from other combinations
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Setup node
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
-
|
||||||
|
name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
-
|
||||||
|
name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install pylint
|
||||||
|
-
|
||||||
|
name: Analyzing the code with pylint
|
||||||
|
run: npm run lint:pylint
|
||||||
|
|||||||
87
.github/workflows/checks.scripts.yaml
vendored
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
name: checks.scripts
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
icons-build:
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ macos, ubuntu, windows ]
|
||||||
|
fail-fast: false # Still interested to see results from other combinations
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Install ImageMagick on macOS
|
||||||
|
if: matrix.os == 'macos'
|
||||||
|
run: brew install imagemagick
|
||||||
|
-
|
||||||
|
name: Setup node
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
-
|
||||||
|
name: Install dependencies
|
||||||
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
|
-
|
||||||
|
name: Create icons
|
||||||
|
run: npm run icons:build
|
||||||
|
|
||||||
|
install-deps:
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
install-deps-before: [true, false]
|
||||||
|
install-command:
|
||||||
|
- npm run install-deps
|
||||||
|
- npm run install-deps -- --no-errors
|
||||||
|
- npm run install-deps -- --ci
|
||||||
|
- npm run install-deps -- --fresh --non-deterministic
|
||||||
|
- npm run install-deps -- --fresh
|
||||||
|
- npm run install-deps -- --non-deterministic
|
||||||
|
os: [ macos, ubuntu, windows ]
|
||||||
|
fail-fast: false # Still interested to see results from other combinations
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Setup node
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
-
|
||||||
|
name: Install dependencies
|
||||||
|
if: matrix.install-deps-before == true
|
||||||
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
|
-
|
||||||
|
name: Run install-deps
|
||||||
|
run: ${{ matrix.install-command }}
|
||||||
|
|
||||||
|
configure-vscode:
|
||||||
|
runs-on: ${{ matrix.os.name }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- name: macos
|
||||||
|
install-vscode-command: brew install --cask visual-studio-code
|
||||||
|
- name: ubuntu
|
||||||
|
install-vscode-command: sudo snap install code --classic
|
||||||
|
- name: windows
|
||||||
|
install-vscode-command: choco install vscode
|
||||||
|
fail-fast: false # Still interested to see results from other combinations
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
-
|
||||||
|
name: Install VSCode
|
||||||
|
run: ${{ matrix.os.install-vscode-command }}
|
||||||
|
-
|
||||||
|
name: Configure VSCode
|
||||||
|
run: python3 ./scripts/configure_vscode.py
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: security-checks
|
name: checks.security.dependencies
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -13,10 +13,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: NPM audit
|
name: NPM audit
|
||||||
run: exit "$(npm audit)" # Since node 15.x, it does not fail with error if we don't explicitly exit
|
run: npm audit --omit=dev
|
||||||
42
.github/workflows/checks.security.sast.yaml
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
name: checks.security.sast
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # at 00:00 on every Sunday
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [
|
||||||
|
javascript # analyzes code written in JavaScript, TypeScript and both.
|
||||||
|
]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
queries: +security-and-quality
|
||||||
|
-
|
||||||
|
name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
-
|
||||||
|
name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
with:
|
||||||
|
category: "/language:${{ matrix.language }}"
|
||||||
26
.github/workflows/release.desktop.yaml
vendored
@@ -13,20 +13,30 @@ jobs:
|
|||||||
fail-fast: false # So publish runs for other OSes if one fails
|
fail-fast: false # So publish runs for other OSes if one fails
|
||||||
runs-on: ${{ matrix.os }}-latest
|
runs-on: ${{ matrix.os }}-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
-
|
||||||
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: master # otherwise it defaults to the version tag missing bump commit
|
ref: master # otherwise it defaults to the version tag missing bump commit
|
||||||
fetch-depth: 0 # fetch all history
|
fetch-depth: 0 # fetch all history
|
||||||
- name: Checkout to bump commit
|
-
|
||||||
|
name: Checkout to bump commit
|
||||||
|
shell: bash
|
||||||
run: git checkout "$(git rev-list "${{ github.event.release.tag_name }}"..master | tail -1)"
|
run: git checkout "$(git rev-list "${{ github.event.release.tag_name }}"..master | tail -1)"
|
||||||
- name: Setup node
|
-
|
||||||
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
- name: Install dependencies
|
-
|
||||||
run: npm ci
|
name: Install dependencies
|
||||||
- name: Run unit tests
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
|
-
|
||||||
|
name: Run unit tests
|
||||||
run: npm run test:unit
|
run: npm run test:unit
|
||||||
- name: Publish desktop app
|
-
|
||||||
run: npm run electron:build -- -p always # https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/recipes.html#upload-release-to-github
|
name: Prebuild
|
||||||
|
run: npm run electron:prebuild
|
||||||
|
-
|
||||||
|
name: Build and publish
|
||||||
|
run: npm run electron:build -- --publish always
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
EP_GH_IGNORE_TIME: true # Otherwise publishing fails if GitHub release is more than 2 hours old https://github.com/electron-userland/electron-builder/issues/2074
|
EP_GH_IGNORE_TIME: true # Otherwise publishing fails if GitHub release is more than 2 hours old https://github.com/electron-userland/electron-builder/issues/2074
|
||||||
|
|||||||
23
.github/workflows/release.site.yaml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: "Infrastructure: Checkout"
|
name: "Infrastructure: Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: aws
|
path: aws
|
||||||
repository: undergroundwires/aws-static-site-with-cd
|
repository: undergroundwires/aws-static-site-with-cd
|
||||||
@@ -75,7 +75,7 @@ jobs:
|
|||||||
working-directory: aws
|
working-directory: aws
|
||||||
-
|
-
|
||||||
name: "App: Checkout"
|
name: "App: Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: app
|
path: app
|
||||||
ref: master # otherwise we don't get version bump commit
|
ref: master # otherwise we don't get version bump commit
|
||||||
@@ -84,8 +84,9 @@ jobs:
|
|||||||
uses: ./app/.github/actions/setup-node
|
uses: ./app/.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: "App: Install dependencies"
|
name: "App: Install dependencies"
|
||||||
run: npm ci
|
uses: ./app/.github/actions/npm-install-dependencies
|
||||||
working-directory: app
|
with:
|
||||||
|
working-directory: app
|
||||||
-
|
-
|
||||||
name: "App: Run unit tests"
|
name: "App: Run unit tests"
|
||||||
run: npm run test:unit
|
run: npm run test:unit
|
||||||
@@ -94,11 +95,21 @@ jobs:
|
|||||||
name: "App: Build"
|
name: "App: Build"
|
||||||
run: npm run build
|
run: npm run build
|
||||||
working-directory: app
|
working-directory: app
|
||||||
|
-
|
||||||
|
name: "App: Verify web build artifacts"
|
||||||
|
run: npm run check:verify-build-artifacts -- --web
|
||||||
|
working-directory: app
|
||||||
-
|
-
|
||||||
name: "App: Deploy to S3"
|
name: "App: Deploy to S3"
|
||||||
run: >-
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
declare web_output_dir
|
||||||
|
if ! web_output_dir=$(cd app && node scripts/print-dist-dir.js --web); then
|
||||||
|
echo 'Error: Could not determine distribution directory.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
bash "aws/scripts/deploy/deploy-to-s3.sh" \
|
bash "aws/scripts/deploy/deploy-to-s3.sh" \
|
||||||
--folder app/dist \
|
--folder "${web_output_dir}" \
|
||||||
--web-stack-name privacysexy-web-stack --web-stack-s3-name-output-name S3BucketName \
|
--web-stack-name privacysexy-web-stack --web-stack-s3-name-output-name S3BucketName \
|
||||||
--storage-class ONEZONE_IA \
|
--storage-class ONEZONE_IA \
|
||||||
--role-arn ${{secrets.AWS_S3_SITE_DEPLOYMENT_ROLE_ARN}} \
|
--role-arn ${{secrets.AWS_S3_SITE_DEPLOYMENT_ROLE_ARN}} \
|
||||||
|
|||||||
44
.github/workflows/tests.e2e.yaml
vendored
@@ -14,13 +14,51 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
run: npm ci
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
-
|
-
|
||||||
name: Run e2e tests
|
name: Run e2e tests
|
||||||
run: npm run test:e2e -- --headless
|
run: npm run test:cy:run
|
||||||
|
-
|
||||||
|
name: Output artifact directories
|
||||||
|
id: artifacts
|
||||||
|
if: always() # Run even if previous steps fail because test run video is always captured
|
||||||
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
declare -r dirs_json_file='cypress-dirs.json'
|
||||||
|
if [ ! -f "${dirs_json_file}" ]; then
|
||||||
|
echo "${dirs_json_file} does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCREENSHOTS_DIR=$(jq -r '.screenshots' "${dirs_json_file}")
|
||||||
|
VIDEOS_DIR=$(jq -r '.videos' "${dirs_json_file}")
|
||||||
|
|
||||||
|
for dir in "${SCREENSHOTS_DIR}" "${VIDEOS_DIR}"; do
|
||||||
|
if [ "${dir}" = 'null' ] || [ -z "${dir}" ]; then
|
||||||
|
echo "One or more directories are null or not specified in cypress-dirs.json"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "SCREENSHOTS_DIR=${SCREENSHOTS_DIR}" >> "${GITHUB_OUTPUT}"
|
||||||
|
echo "VIDEOS_DIR=${VIDEOS_DIR}" >> "${GITHUB_OUTPUT}"
|
||||||
|
-
|
||||||
|
name: Upload screenshots
|
||||||
|
if: failure() # Run only if previous steps fail because screenshots will be generated only if E2E test failed
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: e2e-screenshots-${{ matrix.os }}
|
||||||
|
path: ${{ steps.artifacts.outputs.SCREENSHOTS_DIR }}
|
||||||
|
-
|
||||||
|
name: Upload videos
|
||||||
|
if: always() # Run even if previous steps fail because test run video is always captured
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: e2e-videos-${{ matrix.os }}
|
||||||
|
path: ${{ steps.artifacts.outputs.VIDEOS_DIR }}
|
||||||
|
|||||||
4
.github/workflows/tests.integration.yaml
vendored
@@ -16,13 +16,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Setup node
|
name: Setup node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
run: npm ci
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
-
|
-
|
||||||
name: Run integration tests
|
name: Run integration tests
|
||||||
run: npm run test:integration
|
run: npm run test:integration
|
||||||
|
|||||||
4
.github/workflows/tests.unit.yaml
vendored
@@ -14,13 +14,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Set-up node
|
name: Set-up node
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
-
|
-
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
run: npm ci
|
uses: ./.github/actions/npm-install-dependencies
|
||||||
-
|
-
|
||||||
name: Run unit tests
|
name: Run unit tests
|
||||||
run: npm run test:unit
|
run: npm run test:unit
|
||||||
|
|||||||
20
.gitignore
vendored
@@ -1,10 +1,16 @@
|
|||||||
|
# Application build artifacts
|
||||||
|
/dist-*/
|
||||||
|
|
||||||
|
# npm
|
||||||
node_modules
|
node_modules
|
||||||
dist/
|
|
||||||
.vs
|
# Visual Studio Code
|
||||||
.vscode/**/*
|
.vscode/**/*
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
#Electron-builder output
|
|
||||||
/dist_electron
|
# draw.io
|
||||||
# Cypress
|
*.bkp
|
||||||
/tests/e2e/screenshots
|
*.dtmp
|
||||||
/tests/e2e/videos
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|||||||
7
.vscode/extensions.json
vendored
@@ -11,12 +11,13 @@
|
|||||||
"dbaeumer.vscode-eslint", // Lints JavaScript/TypeScript.
|
"dbaeumer.vscode-eslint", // Lints JavaScript/TypeScript.
|
||||||
"pmneo.tsimporter", // Provides better auto-complete for TypeScripts imports.
|
"pmneo.tsimporter", // Provides better auto-complete for TypeScripts imports.
|
||||||
// Vue
|
// Vue
|
||||||
"jcbuisson.vue", // Highlights syntax.
|
"Vue.volar", // Official Vue extensions
|
||||||
"octref.vetur", // Adds Vetur, Vue tooling support.
|
"Vue.vscode-typescript-vue-plugin", // Official TypeScript Vue Plugin
|
||||||
// Scripting
|
// Scripting
|
||||||
"timonwong.shellcheck", // Lints bash files.
|
"timonwong.shellcheck", // Lints bash files.
|
||||||
"ms-vscode.powershell", // Lints PowerShell files.
|
"ms-vscode.powershell", // Lints PowerShell files.
|
||||||
"ms-python.python", // Lints Python files.
|
"ms-python.python", // Python IntelliSense, debugging, and basic linting.
|
||||||
|
"ms-python.pylint", // Lints Python files
|
||||||
// Distribution
|
// Distribution
|
||||||
"ms-azuretools.vscode-docker" // Adds Docker support.
|
"ms-azuretools.vscode-docker" // Adds Docker support.
|
||||||
]
|
]
|
||||||
|
|||||||
296
CHANGELOG.md
@@ -1,5 +1,301 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.13.3 (2024-05-11)
|
||||||
|
|
||||||
|
* win: organize and document network disablement | [2eed6f4](https://github.com/undergroundwires/privacy.sexy/commit/2eed6f4afb6cf85fdc1d6acb808f82405a35cafd)
|
||||||
|
* win: improve disabling SMBv1 protocol | [f584fab](https://github.com/undergroundwires/privacy.sexy/commit/f584fabb50c7de70ba43751d721af94d8fa2fa8a)
|
||||||
|
* win: improve disabling insecure renegotiations | [f261ab4](https://github.com/undergroundwires/privacy.sexy/commit/f261ab4cd9a53e31325e5c6da9129542971fe84b)
|
||||||
|
* win: doc, improve, encourage cipher disabling | [8b224ee](https://github.com/undergroundwires/privacy.sexy/commit/8b224eefe71be6a556a1085d8fe20dbd4b889430)
|
||||||
|
* ci/cd: add check for TODO comments | [4e21f05](https://github.com/undergroundwires/privacy.sexy/commit/4e21f05031d6cc90cda684bd598bec4735f8103b)
|
||||||
|
* win: improve 'Snipping Tool' removal #343 | [e18907c](https://github.com/undergroundwires/privacy.sexy/commit/e18907ca91e483255b44d14d7d923d7eef92afbd)
|
||||||
|
* ci/cd: lint Python scripts using `pylint` | [23bac0f](https://github.com/undergroundwires/privacy.sexy/commit/23bac0fc76ad697abb34f3fb327df5cdeb40286a)
|
||||||
|
* win: improve disabling insecure hashes #131 | [d19dde6](https://github.com/undergroundwires/privacy.sexy/commit/d19dde603ddac47022ee2e0ea865d53857560c26)
|
||||||
|
* Add system requirements documentation #134 | [0fc2ffc](https://github.com/undergroundwires/privacy.sexy/commit/0fc2ffc1ea36a9248c6a92da85a29f7b04b33796)
|
||||||
|
* win, linux, mac: fix various typos #349 | [694bf1a](https://github.com/undergroundwires/privacy.sexy/commit/694bf1a74d935531d7cd46891823af1fa58c3c8c)
|
||||||
|
* Fix script cancellation with new dialog on Linux | [8c17396](https://github.com/undergroundwires/privacy.sexy/commit/8c173962857a39dc0c9e5886cb2af4937e6618e7)
|
||||||
|
* win: improve disabling protocols | [4ef16ce](https://github.com/undergroundwires/privacy.sexy/commit/4ef16cea56789120cd041412d86b5577cccf0725)
|
||||||
|
* win: fix Copilot by excluding `r.bing.com` #329 | [66a5688](https://github.com/undergroundwires/privacy.sexy/commit/66a56888a4b3ead1a6bfef0feffa0218535701fe)
|
||||||
|
* Fix blank window on load on desktop version #348 | [813d820](https://github.com/undergroundwires/privacy.sexy/commit/813d820b85e1b623c50f8e0325ad372bf2f344f9)
|
||||||
|
* Improve desktop icon quality and generation | [ab25e0a](https://github.com/undergroundwires/privacy.sexy/commit/ab25e0a066be14ea979dafd0f80e1091bd5d33f8)
|
||||||
|
* win: improve enabling secure connections #175 | [c75df1c](https://github.com/undergroundwires/privacy.sexy/commit/c75df1c8c1151b64cbf014383dea0b748a8c78b3)
|
||||||
|
* Fix VSCode script issues with added CI/CD tests | [1d7cafc](https://github.com/undergroundwires/privacy.sexy/commit/1d7cafc831dcc339a10646794410dad7096bfe60)
|
||||||
|
* Fix win execution with whitespace in username #351 | [a334320](https://github.com/undergroundwires/privacy.sexy/commit/a3343205b1196d5a81fd3cee2ae661ce871a7bef)
|
||||||
|
* Fix misaligned tooltip positions in modal dialogs | [dd71536](https://github.com/undergroundwires/privacy.sexy/commit/dd71536316ec819caeb418b8635d544ac80e58ad)
|
||||||
|
* Fix Chromium scrollbar-induced layout shifts | [bc4879c](https://github.com/undergroundwires/privacy.sexy/commit/bc4879cfe97becac3c54f6b40780a89464d3b772)
|
||||||
|
* ci/cd: remove `check-latest` from `setup-node` | [52a4730](https://github.com/undergroundwires/privacy.sexy/commit/52a4730073b8ebfb2ce9d530b44e4a179f5849fe)
|
||||||
|
* win: categorize and rename network security #131 | [9fd193e](https://github.com/undergroundwires/privacy.sexy/commit/9fd193e676f1f0646898f5130fbfaaf25050b2e3)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.13.2...0.13.3)
|
||||||
|
|
||||||
|
## 0.13.2 (2024-04-15)
|
||||||
|
|
||||||
|
* Update documentation for `logo-update.js` script | [4a9b430](https://github.com/undergroundwires/privacy.sexy/commit/4a9b430702bc6082426b50ecc3a06362b5720796)
|
||||||
|
* win: improve and document removing Phone apps #279 | [8924337](https://github.com/undergroundwires/privacy.sexy/commit/89243371faa5d6aef5fce52b0d54a442143cdd39)
|
||||||
|
* Fix bottom gap in card expansion panel | [79183d6](https://github.com/undergroundwires/privacy.sexy/commit/79183d64173e588d88bf074d5b50a52a71c2d885)
|
||||||
|
* ci/cd: Fix macOS Docker build reliability issues | [8a5592f](https://github.com/undergroundwires/privacy.sexy/commit/8a5592f92be4366a806afc9eee9135696a1dd993)
|
||||||
|
* ci/cd: fix IPv6 timeouts with `force-ipv4` action | [52fadcd](https://github.com/undergroundwires/privacy.sexy/commit/52fadcd6177ed06216be9c67dad57192ae02a4f9)
|
||||||
|
* ci/cd: bump Node.js environment to 20.x | [59decd1](https://github.com/undergroundwires/privacy.sexy/commit/59decd17e273bada1493eaa855c43cbabf90308f)
|
||||||
|
* ci/cd: trigger URL checks more, and limit amount | [4fb6302](https://github.com/undergroundwires/privacy.sexy/commit/4fb6302c67f2a3fedff419e8c22872593cf800ef)
|
||||||
|
* Fix overflow in tree node content on small screens | [557cea3](https://github.com/undergroundwires/privacy.sexy/commit/557cea3f4866dc33236874f5fe4d2d69ee963dae)
|
||||||
|
* Fix horizontal layout shift after script selection | [bc7e1fa](https://github.com/undergroundwires/privacy.sexy/commit/bc7e1faa1c3f2b61bf2046fdd6d6a4141b484662)
|
||||||
|
* Fix card header expansion glitch on card collapse | [5d940b5](https://github.com/undergroundwires/privacy.sexy/commit/5d940b57ef2a4c219932cd15201401f8550cfb41)
|
||||||
|
* Ignore `ResizeObserver` errors in Cypress tests | [4472c28](https://github.com/undergroundwires/privacy.sexy/commit/4472c2852e4b87083bda7979471ab9f377d17a01)
|
||||||
|
* win: improve and document secret key scripts | [49f22f0](https://github.com/undergroundwires/privacy.sexy/commit/49f22f048f39e7388633c488b5fe59101b831984)
|
||||||
|
* Fix card arrow not being animated in sync | [7b546c5](https://github.com/undergroundwires/privacy.sexy/commit/7b546c567c4683a37fe94595362f4c2bf92ffd59)
|
||||||
|
* win: improve Windows feature disablement scripts | [b68711e](https://github.com/undergroundwires/privacy.sexy/commit/b68711ef88982c0ee2b1d41b4452e899821adc64)
|
||||||
|
* Fix top script menu overflow on small screens | [b7a20d9](https://github.com/undergroundwires/privacy.sexy/commit/b7a20d9d41ea8bcefdd553b87641f3c22b4cde97)
|
||||||
|
* win: fix Visual Studio remote analysis script #327 | [4142d08](https://github.com/undergroundwires/privacy.sexy/commit/4142d084f64a3b540487ff68b28032977d12006d)
|
||||||
|
* win: improve firewall docs /w `winget` impact #142 | [ffd647d](https://github.com/undergroundwires/privacy.sexy/commit/ffd647d1529375474b81900cc7bee4c32fbf861f)
|
||||||
|
* Centralize and use global spacing variables | [ae17200](https://github.com/undergroundwires/privacy.sexy/commit/ae172000a64416e5a3e2b2e32b7846f039f445f0)
|
||||||
|
* win: improve service revert and docs | [b87b7aa](https://github.com/undergroundwires/privacy.sexy/commit/b87b7aac7d118a23a0d1bfb881e385347de4adb7)
|
||||||
|
* Bump dependencies to latest, hold ESLint | [f3571ab](https://github.com/undergroundwires/privacy.sexy/commit/f3571abeafdbe1e6d152958fab26de91a9c08bc3)
|
||||||
|
* Fix inability to tap outside modal on mobile | [cb144ae](https://github.com/undergroundwires/privacy.sexy/commit/cb144ae47273deeb7058d4b1380e480ebccdaf81)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.13.1...0.13.2)
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
* Improve security by isolating code execution more | [efa05f4](https://github.com/undergroundwires/privacy.sexy/commit/efa05f42bc53c44a352152b7c272bc0bda363070)
|
||||||
|
* Fix unresponsive circle icon in revert button | [645c333](https://github.com/undergroundwires/privacy.sexy/commit/645c33378769969c525a1552c65f8d0005e25fcf)
|
||||||
|
* Improve documentation for contribution guidelines | [fc9dd23](https://github.com/undergroundwires/privacy.sexy/commit/fc9dd234e9c749247f42289432ebb92dbe0a5f64)
|
||||||
|
* Bump Node.js environment to 18.x | [2f06043](https://github.com/undergroundwires/privacy.sexy/commit/2f0604355988a421690bb275375c3df280af7ee6)
|
||||||
|
* Fix button inconsistencies and macOS layout shifts | [86fde6d](https://github.com/undergroundwires/privacy.sexy/commit/86fde6d7dc61bbeeb3088cd24e37451181cc4e01)
|
||||||
|
* win: fix language dependent delete script #149 | [8f4b34f](https://github.com/undergroundwires/privacy.sexy/commit/8f4b34f8f156476f56fb7dde8e7c762f4455518b)
|
||||||
|
* Improve desktop script runs with timestamps & logs | [cdc32d1](https://github.com/undergroundwires/privacy.sexy/commit/cdc32d1f12c938966238c9569c91b64b23cd6f26)
|
||||||
|
* win: improve store app docs and add research #279 | [fac72ed](https://github.com/undergroundwires/privacy.sexy/commit/fac72edd551264320ed97194e7ecb3fcc34139f7)
|
||||||
|
* Fix handling special chars in script paths | [40f5eb8](https://github.com/undergroundwires/privacy.sexy/commit/40f5eb8334b27e958eee63e2141ded7d5861d960)
|
||||||
|
* Fix macOS detection in desktop app and Chromium | [dc30825](https://github.com/undergroundwires/privacy.sexy/commit/dc30825232a1355a325e364c8cd9fde78ffa3b1a)
|
||||||
|
* Bump ESLint Typescript dependencies to latest | [bf7fb07](https://github.com/undergroundwires/privacy.sexy/commit/bf7fb0732c52745521c1a89b963bdbf3394d9e63)
|
||||||
|
* Fix script deletion during execution on desktop | [c84a1bb](https://github.com/undergroundwires/privacy.sexy/commit/c84a1bb74ccb7a53bd493684b63a9e04f40e0b8b)
|
||||||
|
* Fix script execution for Linux VSCode development | [3b1a89c](https://github.com/undergroundwires/privacy.sexy/commit/3b1a89ce863c18c32be7d0b22dba566f692d81d1)
|
||||||
|
* Fix touch, cursor and accessibility in slider | [7285842](https://github.com/undergroundwires/privacy.sexy/commit/728584240cae6b3857abca4d3ddaaa7f6bb4a66e)
|
||||||
|
* Fix invisible script execution on Windows #264 | [b404a91](https://github.com/undergroundwires/privacy.sexy/commit/b404a91ada509e19a287d026d55db0035ff6233b)
|
||||||
|
* win: add missing extension apps, improve docs #279 | [da4be50](https://github.com/undergroundwires/privacy.sexy/commit/da4be500da7b0b5897a8b3e0525d9e50c9159fe0)
|
||||||
|
* Show native save dialogs in desktop app #50, #264 | [c546a33](https://github.com/undergroundwires/privacy.sexy/commit/c546a33eff7506550c7bcf03bb1f227a7c091816)
|
||||||
|
* Show save/execution error dialogs on desktop #264 | [e09db0f](https://github.com/undergroundwires/privacy.sexy/commit/e09db0f1bd73503204d8e5375a9cfe693f174a57)
|
||||||
|
* Add Windows save instructions UI and fix URL #296 | [756c736](https://github.com/undergroundwires/privacy.sexy/commit/756c736e21d713b8d2651cf2a9d7cf0678badde0)
|
||||||
|
* Add AD detection on desktop app #264, #304 | [f03fc24](https://github.com/undergroundwires/privacy.sexy/commit/f03fc2409832ddf904bc6bd4e19274a8d40745dc)
|
||||||
|
* Improve script error dialogs #304 | [6ada8d4](https://github.com/undergroundwires/privacy.sexy/commit/6ada8d425c4a7df88490756187c84b5c57ed1dcc)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.9...0.12.10)
|
||||||
|
|
||||||
|
## 0.12.9 (2023-12-16)
|
||||||
|
|
||||||
|
* win: improve docs and category of jump lists #146 | [40ae8a8](https://github.com/undergroundwires/privacy.sexy/commit/40ae8a8addaeb834ee26eabd330fda5cbb495324)
|
||||||
|
* mac: improve clearing privacy permissions | [5a7d7d8](https://github.com/undergroundwires/privacy.sexy/commit/5a7d7d88ff2f3e8862b18c94d062f692ee4b690b)
|
||||||
|
* win: fix logic for terminating processes | [807ae6a](https://github.com/undergroundwires/privacy.sexy/commit/807ae6a8f8ca724d781169f3ecb40f43ccd3fe10)
|
||||||
|
* win: improve documentation for "Get Help" app #280 | [8f5d7ed](https://github.com/undergroundwires/privacy.sexy/commit/8f5d7ed3cfa57f66dded9b72374006c9b6df2ce9)
|
||||||
|
* Centralize log file and refactor desktop logging | [08dbfea](https://github.com/undergroundwires/privacy.sexy/commit/08dbfead7ca7b55fe85f7dded01f2d4b88906c72)
|
||||||
|
* win: fix revert and improve docs for SAM enum #255 | [25e23c8](https://github.com/undergroundwires/privacy.sexy/commit/25e23c89c3f86897d5661a24a774997c924d3b2d)
|
||||||
|
* Improve security and reliability of macOS updates | [4765752](https://github.com/undergroundwires/privacy.sexy/commit/4765752ee3a36301b3d97317c570432424de8460)
|
||||||
|
* win: fix Win 11 Windows Security app removal #195 | [daa6230](https://github.com/undergroundwires/privacy.sexy/commit/daa6230fc96f2cf7210bc8c165106c0d5544e5fb)
|
||||||
|
* Improve security and privacy with strict meta tags | [ba5b29a](https://github.com/undergroundwires/privacy.sexy/commit/ba5b29a35dd7665aeea430aec4aaa8ff5ca811de)
|
||||||
|
* win: document and discourage admin shares #249 | [e747ee5](https://github.com/undergroundwires/privacy.sexy/commit/e747ee5cbc7cf5f0fe28a87fe7d02457d777373e)
|
||||||
|
* win: discourage XboxIdentityProvider #64, #79 #181 | [c72f9f5](https://github.com/undergroundwires/privacy.sexy/commit/c72f9f501680c1d880a0b560d02451a9e31063b4)
|
||||||
|
* win: improve disabling update healing #272 | [47b4823](https://github.com/undergroundwires/privacy.sexy/commit/47b4823bc5e487188b12cbea67db2525260af497)
|
||||||
|
* Fix tooltip overflow on smaller screens | [916c9d6](https://github.com/undergroundwires/privacy.sexy/commit/916c9d62d9fce27c3cd3feaf90c66df584d4f04a)
|
||||||
|
* Fix touch state not being activated in iOS Safari | [a985127](https://github.com/undergroundwires/privacy.sexy/commit/a9851272ae14eb1b374767b0eed3eb68e6dd1560)
|
||||||
|
* Fix tree view alignment and padding issues | [15134ea](https://github.com/undergroundwires/privacy.sexy/commit/15134ea04bc46e8cb13977d75b788f5ff71c800e)
|
||||||
|
* win: improve disabling of Application Experience | [fe3de49](https://github.com/undergroundwires/privacy.sexy/commit/fe3de498c8a1394efd6517d436797a08f938bb57)
|
||||||
|
* Fix OS switching not working on tree view UI | [3457fe1](https://github.com/undergroundwires/privacy.sexy/commit/3457fe18cf8193883f45b50ecbc9638c91ace2fb)
|
||||||
|
* Fix touch-enabled Chromium highlight on tree nodes | [2063397](https://github.com/undergroundwires/privacy.sexy/commit/20633972e9b56bdc102357129e74df30a95cefa9)
|
||||||
|
* win: add scripts to postpone auto-updates #272 | [e95b2ba](https://github.com/undergroundwires/privacy.sexy/commit/e95b2ba2179e40c0033a51b0087871dbfdc32d78)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.8...0.12.9)
|
||||||
|
|
||||||
|
## 0.12.8 (2023-11-27)
|
||||||
|
|
||||||
|
* Remove duplicated `index.html` file | [aab0f7e](https://github.com/undergroundwires/privacy.sexy/commit/aab0f7ea4680f377c610066bd0e99011eed8b506)
|
||||||
|
* Refactor DI for simplicity and type safety | [7770a9b](https://github.com/undergroundwires/privacy.sexy/commit/7770a9b5211d7208cfb2bfa5f737d46dc90b7946)
|
||||||
|
* Refactor user selection state handling using hook | [58cd551](https://github.com/undergroundwires/privacy.sexy/commit/58cd551a304a03e42637e6858982f8c5dfd9f598)
|
||||||
|
* Refactor watch sources for reliability | [7ab16ec](https://github.com/undergroundwires/privacy.sexy/commit/7ab16ecccb31b2d54e5b634520a8246fbbc248c1)
|
||||||
|
* Refactor to enforce strictNullChecks | [949fac1](https://github.com/undergroundwires/privacy.sexy/commit/949fac1a7cbc962ed63058e6a896695cfb4d35c8)
|
||||||
|
* Fix icon tooltip alignment on instructions modal | [bd383ed](https://github.com/undergroundwires/privacy.sexy/commit/bd383ed273ca95c10ea1cce765c0aa6836ec508c)
|
||||||
|
* Fix mobile layout overflow caused by tooltips | [e541a35](https://github.com/undergroundwires/privacy.sexy/commit/e541a35e86c0eff83f84dd002b46de7c55ebbcac)
|
||||||
|
* win: improve disabling of scheduled tasks | [3864f04](https://github.com/undergroundwires/privacy.sexy/commit/3864f042180f62afe469fdfe36010b018f84f4b3)
|
||||||
|
* Fix card list UI layout shifts (jumps) on load | [bf3426f](https://github.com/undergroundwires/privacy.sexy/commit/bf3426f91b6b7dbcad58d58507222559a8d14242)
|
||||||
|
* Refactor to Vue 3 recommended ESLint rules | [4531645](https://github.com/undergroundwires/privacy.sexy/commit/4531645b4c0c5143f15240652368bb9b9ddb48a4)
|
||||||
|
* Fix code highlighting and optimize category select | [cb42f11](https://github.com/undergroundwires/privacy.sexy/commit/cb42f11b9785e74719338a0a80a50d81dfccb4b6)
|
||||||
|
* Fix layout jumps/shifts and overflow on modals | [e299d40](https://github.com/undergroundwires/privacy.sexy/commit/e299d40fa1d71d921d4dac37e469fe299c9da3af)
|
||||||
|
* win: fix and improve Store app categorization #190 | [094dbb0](https://github.com/undergroundwires/privacy.sexy/commit/094dbb01b83bce9925fafab778b922f64390c2be)
|
||||||
|
* win: fix persistent update disabling /w tasks #272 | [dee3279](https://github.com/undergroundwires/privacy.sexy/commit/dee3279f85c99a9c62201a093b1afa41ec2412ec)
|
||||||
|
* win: discourage IntelliCode disabling #267, #286 | [7f7a84e](https://github.com/undergroundwires/privacy.sexy/commit/7f7a84e3ba259fade22d4838563d16129a1585e6)
|
||||||
|
* Fix spacing in documentation for readability | [1442f62](https://github.com/undergroundwires/privacy.sexy/commit/1442f626335e30e3a8d74e4e13e561c41f073ef8)
|
||||||
|
* win: fix system app removal affecting updates #287 | [7c632f7](https://github.com/undergroundwires/privacy.sexy/commit/7c632f738853b32fd90952bb4ca1ac924f962eb0)
|
||||||
|
* Fix rendering of inline code blocks for docs | [9845a7c](https://github.com/undergroundwires/privacy.sexy/commit/9845a7cd68a9920c96da739b58238bb1fdb1251d)
|
||||||
|
* linux: fix Firefox settings not reverting #282 | [bcad357](https://github.com/undergroundwires/privacy.sexy/commit/bcad357017d9f29ce77e706ca943107dd9caefb6)
|
||||||
|
* Fix incorrect URL rendering in documentation texts | [d328f08](https://github.com/undergroundwires/privacy.sexy/commit/d328f0895244d998e885ad8df335b6444b9ac66b)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.7...0.12.8)
|
||||||
|
|
||||||
|
## 0.12.7 (2023-11-07)
|
||||||
|
|
||||||
|
* Add winget download instructions | [b2ffc90](https://github.com/undergroundwires/privacy.sexy/commit/b2ffc90da70367b9e65c82556e8f440f865ceb98)
|
||||||
|
* Fix unresponsive copy button on instructions modal | [8ccaec7](https://github.com/undergroundwires/privacy.sexy/commit/8ccaec7af6ea3ecfd46bab5c13b90f71d55e32c1)
|
||||||
|
* Fix tree node check states not being updated | [af7219f](https://github.com/undergroundwires/privacy.sexy/commit/af7219f6e12ab4a65ce07190f691cf3234e87e35)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.6...0.12.7)
|
||||||
|
|
||||||
|
## 0.12.6 (2023-11-03)
|
||||||
|
|
||||||
|
* Bump dependencies to latest | [25d7f7b](https://github.com/undergroundwires/privacy.sexy/commit/25d7f7b2a479e51e092881cc2751e67a7d3f179f)
|
||||||
|
* win: improve system app uninstall cleanup #73 | [dbe3c5c](https://github.com/undergroundwires/privacy.sexy/commit/dbe3c5cfb91ba8a1657838b69117858843c8fbc8)
|
||||||
|
* win: improve system app uninstall /w fallback #260 | [98a26f9](https://github.com/undergroundwires/privacy.sexy/commit/98a26f9ae47af2668aa53f39d1768983036048ce)
|
||||||
|
* Improve performance of rendering during search | [79b46bf](https://github.com/undergroundwires/privacy.sexy/commit/79b46bf21004d96d31551439e5db5d698a3f71f3)
|
||||||
|
* Fix YAML error for site release in CI/CD | [237d994](https://github.com/undergroundwires/privacy.sexy/commit/237d9944f900f5172366868d75219224ff0542b0)
|
||||||
|
* win: fix Microsoft Advertising app removal #200 | [e40b9a3](https://github.com/undergroundwires/privacy.sexy/commit/e40b9a3cf53c341f2e84023a9f0e9680ac08f3fa)
|
||||||
|
* win: improve directory cleanup security | [060e789](https://github.com/undergroundwires/privacy.sexy/commit/060e7896624309aebd25e8b190c127282de177e8)
|
||||||
|
* Centralize Electron entry file path configuration | [d6da406](https://github.com/undergroundwires/privacy.sexy/commit/d6da406c61e5b9f5408851d1302d6d7398157a2e)
|
||||||
|
* win: prevent updates from reinstalling apps #260 | [8570b02](https://github.com/undergroundwires/privacy.sexy/commit/8570b02dde14ffad64863f614682c3fc1f87b6c2)
|
||||||
|
* win: improve script environment robustness #221 | [dfd4451](https://github.com/undergroundwires/privacy.sexy/commit/dfd44515613f38abe5a806bda36f44e7b715b50b)
|
||||||
|
* Fix compiler failing with nested `with` expression | [80821fc](https://github.com/undergroundwires/privacy.sexy/commit/80821fca0769e5fd2c6338918fbdcea12fbe83d2)
|
||||||
|
* win: improve soft file/app delete security #260 | [f4a74f0](https://github.com/undergroundwires/privacy.sexy/commit/f4a74f058db9b5bcbcbe438785db5ec88ecc1657)
|
||||||
|
* Fix incorrect tooltip position after window resize | [f8e5f1a](https://github.com/undergroundwires/privacy.sexy/commit/f8e5f1a5a2afa1f18567e6d965359b6a1f082367)
|
||||||
|
* linux: fix string formatting of Firefox configs | [e775d68](https://github.com/undergroundwires/privacy.sexy/commit/e775d68a9b4a5f9e893ff0e3500dade036185193)
|
||||||
|
* win: improve file delete | [e72c1c1](https://github.com/undergroundwires/privacy.sexy/commit/e72c1c13ea2d73ebfc7a8da5a21254fdfc0e5b59)
|
||||||
|
* win: change system app removal to hard delete #260 | [77123d8](https://github.com/undergroundwires/privacy.sexy/commit/77123d8c929d23676a9cb21d7b697703fd1b6e82)
|
||||||
|
* Improve UI performance by optimizing reactivity | [4995e49](https://github.com/undergroundwires/privacy.sexy/commit/4995e49c469211404dac9fcb79b75eb121f80bce)
|
||||||
|
* Migrate to Vue 3.0 #230 | [ca81f68](https://github.com/undergroundwires/privacy.sexy/commit/ca81f68ff1c3bbe5b22981096ae9220b0b5851c7)
|
||||||
|
* win, linux: unify & improve Firefox clean-up #273 | [0466b86](https://github.com/undergroundwires/privacy.sexy/commit/0466b86f1013341c966a9bbf6513990337b16598)
|
||||||
|
* win: fix store revert for multiple installs #260 | [5bb13e3](https://github.com/undergroundwires/privacy.sexy/commit/5bb13e34f8de2e2a7ba943ff72b12c0569435e62)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.5...0.12.6)
|
||||||
|
|
||||||
|
## 0.12.5 (2023-10-13)
|
||||||
|
|
||||||
|
* Fix Docker build and improve checks #220 | [7669985](https://github.com/undergroundwires/privacy.sexy/commit/7669985f8e1446e726a95626ecf35b3ce6b60a16)
|
||||||
|
* Add SAST security checks with SECURITY.md #178 | [3e5239f](https://github.com/undergroundwires/privacy.sexy/commit/3e5239f7d35e57749c01adf3dbbcd365aebb39c8)
|
||||||
|
* Add Scoop download instructions #174 | [cf55ca9](https://github.com/undergroundwires/privacy.sexy/commit/cf55ca9e28b064fa7a516077a9da23e3a8e3f534)
|
||||||
|
* win: fix and improve temp dir cleanup #176, #89 | [d457504](https://github.com/undergroundwires/privacy.sexy/commit/d45750428cca010daf2721b33a8ae3a01b28813b)
|
||||||
|
* win, linux: improve VSCode setting robustness #196 | [e8a52f7](https://github.com/undergroundwires/privacy.sexy/commit/e8a52f717dc799b34ceeb1c27c2b8219391dff6a)
|
||||||
|
* linux: fix obsolete Firefox DPI script #239 | [e5f6edf](https://github.com/undergroundwires/privacy.sexy/commit/e5f6edf405bcec7c29ea4d7932d1910620fa15f8)
|
||||||
|
* win: add removal of Edge assocations #64 | [888c916](https://github.com/undergroundwires/privacy.sexy/commit/888c9166fc66a2094137fa8be739cc21bafef5f6)
|
||||||
|
* win: improve Edge & OneDrive shortcut removal #73 | [8501495](https://github.com/undergroundwires/privacy.sexy/commit/8501495c170af61913288a63dbd369db5bbc5003)
|
||||||
|
* win: relocate and document SecHealthUI #190 | [2862951](https://github.com/undergroundwires/privacy.sexy/commit/286295128d0179358e0c6b7b6415d752175a1aed)
|
||||||
|
* Add developer toolkit UI component | [2147eae](https://github.com/undergroundwires/privacy.sexy/commit/2147eae687b82d05bc43bb4605d9068f148bb92a)
|
||||||
|
* win: fix and improve network data usage reset #265 | [5e359c2](https://github.com/undergroundwires/privacy.sexy/commit/5e359c2fb82a08e6acf7159b70ca86a8234b359b)
|
||||||
|
* win: improve app reversion and docs #260 | [a3f11df](https://github.com/undergroundwires/privacy.sexy/commit/a3f11dff187c821a00910c20dac05e285cda9073)
|
||||||
|
* Fix working directory in CI/CD web release | [698b570](https://github.com/undergroundwires/privacy.sexy/commit/698b570ee6e300d6703015464f4345b5e706f1cb)
|
||||||
|
* Implement new UI component for icons #230 | [48730bc](https://github.com/undergroundwires/privacy.sexy/commit/48730bca0506120bca4bf3a23545d59f2b1a9009)
|
||||||
|
* win: fix and improve AppCompat disabling #255 | [bab6316](https://github.com/undergroundwires/privacy.sexy/commit/bab6316e7625230cf4a4cf67c3aca417347db75c)
|
||||||
|
* win, linux, mac: fix typos and improve naming | [67c3677](https://github.com/undergroundwires/privacy.sexy/commit/67c3677621b201525a813e8a26f07d607176e89b)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.4...0.12.5)
|
||||||
|
|
||||||
|
## 0.12.4 (2023-09-25)
|
||||||
|
|
||||||
|
* win: fix Windows spotlight revert, docs, recommend | [659fea7](https://github.com/undergroundwires/privacy.sexy/commit/659fea7afcabcd0ea273cfdcc8c4bae190c126f3)
|
||||||
|
* win: fix Edge telemetry disabling for v116+ #242 | [6d301f9](https://github.com/undergroundwires/privacy.sexy/commit/6d301f99616ed49975876803d0098eafe4d3cb2e)
|
||||||
|
* win: fix, improve disabling automatic updates #252 | [6e9b65d](https://github.com/undergroundwires/privacy.sexy/commit/6e9b65d8b1b481c1471dde90876c37838b4ac4e5)
|
||||||
|
* win: refactor `update.mode` key for VSCode #215 | [c27172c](https://github.com/undergroundwires/privacy.sexy/commit/c27172c32e7c316b7cb0f44cab611eed89ca034e)
|
||||||
|
* Fix wrong action path in website CI deployment | [a1f2497](https://github.com/undergroundwires/privacy.sexy/commit/a1f24973813ccbdd7e1f06c64e1912a991a6bb64)
|
||||||
|
* Fix compiler bug with nested optional arguments | [53222fd](https://github.com/undergroundwires/privacy.sexy/commit/53222fd83c2846089746a217482195806f960d18)
|
||||||
|
* Fix no spacing after lists in documentation text | [f810ed0](https://github.com/undergroundwires/privacy.sexy/commit/f810ed0c147c2a46cae3b70b635ed81128646fff)
|
||||||
|
* Rewrite tooltip UI for efficiency and Vue 3.0 #230 | [8b930fc](https://github.com/undergroundwires/privacy.sexy/commit/8b930fc57c8ee6691ed6165bcb27d97e64a1a0c0)
|
||||||
|
* win: fix uninstallation of newer Edge #236 | [60dde11](https://github.com/undergroundwires/privacy.sexy/commit/60dde11311a2409537f5965f370b0daaaec53339)
|
||||||
|
* win: fix delivery optimization side-effects #173 | [203daeb](https://github.com/undergroundwires/privacy.sexy/commit/203daeb4a2fca0a0295cbc2a736394f9f87725e6)
|
||||||
|
* win: fix Defender scan artifacts removal #246 | [cb21a97](https://github.com/undergroundwires/privacy.sexy/commit/cb21a970b6b867e1476a5eb8a72b9a7fdd53a744)
|
||||||
|
* Fix outdated and broken links in README #161 | [0303ef2](https://github.com/undergroundwires/privacy.sexy/commit/0303ef2fd98b36306523e2a0c5f5ae812a4c6c99)
|
||||||
|
* Fix loss of tree node state when switching views | [8f188ac](https://github.com/undergroundwires/privacy.sexy/commit/8f188acd3c2d93e40c89569c74bc5cff992f0052)
|
||||||
|
* Fix slow appearance of nodes on tree view | [bd2082e](https://github.com/undergroundwires/privacy.sexy/commit/bd2082e8c574db065bb4462f30ea3ace2cb028cb)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.3...0.12.4)
|
||||||
|
|
||||||
|
## 0.12.3 (2023-09-09)
|
||||||
|
|
||||||
|
* linux: use user.js over prefs.js for Firefox #232 | [dae6d11](https://github.com/undergroundwires/privacy.sexy/commit/dae6d114daab6857d773071211eb57619b136281)
|
||||||
|
* win: fix typo in Defender retention script #213 | [35be05d](https://github.com/undergroundwires/privacy.sexy/commit/35be05df2094ea8bba4ee4725e6fa4956a79493d)
|
||||||
|
* Improve desktop runtime execution tests | [ad0576a](https://github.com/undergroundwires/privacy.sexy/commit/ad0576a752f8fd6ea2f917a59173fe61f9951246)
|
||||||
|
* Fix Windows artifact naming in desktop packaging | [f4d86fc](https://github.com/undergroundwires/privacy.sexy/commit/f4d86fccfd0e73e94c8c6e400a33514900bc5abe)
|
||||||
|
* Refactor and improve external URL checks | [19e42c9](https://github.com/undergroundwires/privacy.sexy/commit/19e42c9c52a18c813ded4265e687e01032cdd4c8)
|
||||||
|
* Fix memory leaks via auto-unsubscribing and DI | [eb096d0](https://github.com/undergroundwires/privacy.sexy/commit/eb096d07e276e1b4c8040220c47f186d02841e14)
|
||||||
|
* Refactor build configs and improve CI/CD checks | [0a2a1a0](https://github.com/undergroundwires/privacy.sexy/commit/0a2a1a026b0efb29624be82b06536c518c1ea439)
|
||||||
|
* Introduce retry mechanism for npm install in CI/CD | [4beb1bb](https://github.com/undergroundwires/privacy.sexy/commit/4beb1bb5748a60886210187ca3cdc7f4b41067c0)
|
||||||
|
* win: fix disable recent apps revert #211, #248 | [4ce327e](https://github.com/undergroundwires/privacy.sexy/commit/4ce327eb6af542ed2916d649553e5e1ba5833882)
|
||||||
|
* Change license to AGPLv3 | [821cc62](https://github.com/undergroundwires/privacy.sexy/commit/821cc62c4c8347cb76d041f82f574754e4d948c5)
|
||||||
|
* Introduce new TreeView UI component | [65f121c](https://github.com/undergroundwires/privacy.sexy/commit/65f121c451af87315e1c91df4198562e0445b2c2)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.2...0.12.3)
|
||||||
|
|
||||||
|
## 0.12.2 (2023-08-25)
|
||||||
|
|
||||||
|
* Add automated checks for desktop app runtime #233 | [04b3133](https://github.com/undergroundwires/privacy.sexy/commit/04b3133500485d0d278a81a177a1677134131405)
|
||||||
|
* win: fix automatic updates revert #234 | [0873769](https://github.com/undergroundwires/privacy.sexy/commit/08737698c2283bdf535d1611a730031ebfc7c0df)
|
||||||
|
* Migrate unit/integration tests to Vitest with Vite | [5f11c8d](https://github.com/undergroundwires/privacy.sexy/commit/5f11c8d98f782dd7c77f27649a1685fb7bd06e13)
|
||||||
|
* Remove Vue ESLint plugin for Vite compatibility | [6e40edd](https://github.com/undergroundwires/privacy.sexy/commit/6e40edd3f8a063c1b7482c27d8368e14c2fbcfbf)
|
||||||
|
* Migrate web builds from Vue CLI to Vite | [7365905](https://github.com/undergroundwires/privacy.sexy/commit/736590558be51a09435bb87e78b6655e8533bc2e)
|
||||||
|
* Migrate Cypress (E2E) tests to Vite and TypeScript | [ec98d84](https://github.com/undergroundwires/privacy.sexy/commit/ec98d8417f779fa818ccdda6bb90f521e1738002)
|
||||||
|
* Migrate to `electron-vite` and `electron-builder` | [75c9b51](https://github.com/undergroundwires/privacy.sexy/commit/75c9b51bf2d1dc7269adfd7b5ed71acfb5031299)
|
||||||
|
* Fix searching/filtering bugs #235 | [62f8bfa](https://github.com/undergroundwires/privacy.sexy/commit/62f8bfac2f481c93598fe19a51594769f522d684)
|
||||||
|
* Improve desktop security by isolating Electron | [e9e0001](https://github.com/undergroundwires/privacy.sexy/commit/e9e0001ef845fa6935c59a4e20a89aac9e71756a)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.1...0.12.2)
|
||||||
|
|
||||||
|
## 0.12.1 (2023-08-17)
|
||||||
|
|
||||||
|
* Transition to eslint-config-airbnb-with-typescript | [ff84f56](https://github.com/undergroundwires/privacy.sexy/commit/ff84f5676e496dd7ec5b3599e34ec9627d181ea2)
|
||||||
|
* Improve user privacy with secure outbound links | [3a594ac](https://github.com/undergroundwires/privacy.sexy/commit/3a594ac7fd708dc1e98155ffb9b21acd4e1fcf2d)
|
||||||
|
* Refactor Vue components using Composition API #230 | [1b9be8f](https://github.com/undergroundwires/privacy.sexy/commit/1b9be8fe2d72d8fb5cf1fed6dcc0b9777171aa98)
|
||||||
|
* Fix failing security tests | [3bc8da4](https://github.com/undergroundwires/privacy.sexy/commit/3bc8da4cbf1e2bd758dc3fffe4b1e62dc3beb7b3)
|
||||||
|
* Improve Defender scripts #201 | [061afad](https://github.com/undergroundwires/privacy.sexy/commit/061afad9673a41454c2421c318898f2b4f4cf504)
|
||||||
|
* Fix failing tests due to failed error logging | [986ba07](https://github.com/undergroundwires/privacy.sexy/commit/986ba078a643de6acbee50fff9cf77494ca7ea7f)
|
||||||
|
* Implement custom lightweight modal #230 | [9e5491f](https://github.com/undergroundwires/privacy.sexy/commit/9e5491fdbf2d9d40d974f5ad0e879a6d5c6d1e55)
|
||||||
|
* Refactor usage of tooltips for flexibility | [bc91237](https://github.com/undergroundwires/privacy.sexy/commit/bc91237d7c54bdcd15c5c39a55def50d172bb659)
|
||||||
|
* Fix revert toggle partial rendering | [39e650c](https://github.com/undergroundwires/privacy.sexy/commit/39e650cf110bee6b1b21d9b2902b36b0e2568d54)
|
||||||
|
* Increase testability through dependency injection | [ae75059](https://github.com/undergroundwires/privacy.sexy/commit/ae75059cc14db41f55dd2056f528442c7d319dd2)
|
||||||
|
* Refactor filter (search query) event handling | [6a20d80](https://github.com/undergroundwires/privacy.sexy/commit/6a20d804dc365d22c1248d787f9912271f508eeb)
|
||||||
|
* Migrate to ES6 modules | [a14929a](https://github.com/undergroundwires/privacy.sexy/commit/a14929a13cc6260b514692d9b4f1cdf5fb85d8b2)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.0...0.12.1)
|
||||||
|
|
||||||
## 0.12.0 (2023-08-03)
|
## 0.12.0 (2023-08-03)
|
||||||
|
|
||||||
* Improve script/category name validation | [b210aad](https://github.com/undergroundwires/privacy.sexy/commit/b210aaddf26629179f77fe19f62f65d8a0ca2b87)
|
* Improve script/category name validation | [b210aad](https://github.com/undergroundwires/privacy.sexy/commit/b210aaddf26629179f77fe19f62f65d8a0ca2b87)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Love your input! Contributing to this project should be as easy and transparent as possible, whether it's:
|
Love your input ❤️! Contributing to this project should be as easy and transparent as possible, whether it's:
|
||||||
|
|
||||||
- reporting a bug,
|
- reporting a bug,
|
||||||
- discussing the current state of the code,
|
- discussing the current state of the code,
|
||||||
@@ -16,7 +16,7 @@ Your pull requests are actively welcomed. We collaborate using [GitHub flow](htt
|
|||||||
|
|
||||||
The steps:
|
The steps:
|
||||||
|
|
||||||
1. Fork the repo and create your branch from master.
|
1. Fork the repository and create your branch from `master`.
|
||||||
2. If you've added code that requires testing, add tests. See [tests.md](./docs/tests.md).
|
2. If you've added code that requires testing, add tests. See [tests.md](./docs/tests.md).
|
||||||
3. If you've done a major change, update the documentation. See [docs/](./docs/).
|
3. If you've done a major change, update the documentation. See [docs/](./docs/).
|
||||||
4. Ensure the test suite passes. See [development.md | Testing](./docs/development.md#testing) for commands.
|
4. Ensure the test suite passes. See [development.md | Testing](./docs/development.md#testing) for commands.
|
||||||
@@ -37,15 +37,44 @@ Automated pipelines will run to control your PR and they will publish your code
|
|||||||
|
|
||||||
## Extend scripts
|
## Extend scripts
|
||||||
|
|
||||||
Here's quick information for you who want to add more scripts.
|
If you're interested in adding new scripts to privacy.sexy:
|
||||||
|
|
||||||
You have two alternatives:
|
1. Read [guidelines for a good script](./docs/script-guidelines.md)
|
||||||
|
2. Choose one of two ways to contribute:
|
||||||
|
1. [Create an issue](https://github.com/undergroundwires/privacy.sexy/issues/new/choose) requesting the addition of a new script. This allows other contributors to develop and add it for you. This will take longer time.
|
||||||
|
2. Submit a pull request with your script. This is the faster route to seeing your script included in the project. Add your scripts to the appropriate OS directory in the [collections](src/application/collections/) (for syntax guidance, see [collection-files.md](docs/collection-files.md)) folder, and follow the [pull request process](#pull-request-process).
|
||||||
|
|
||||||
1. [Create an issue](https://github.com/undergroundwires/privacy.sexy/issues/new/choose) and ask for someone else to add the script for you.
|
## Commit conventions
|
||||||
2. Or send a PR yourself. This would make it faster to get your code into the project. You need to add scripts to related OS in [collections](src/application/collections/) folder. Then you'd sent a pull request, see [pull request process](#pull-request-process).
|
|
||||||
- 📖 If you're unsure about the syntax, check [collection-files.md](docs/collection-files.md).
|
- Adhere to the 50/72 rule:
|
||||||
- 📖 If you wish to use templates, use [templating.md](./docs/templating.md).
|
- Commit titles should not exceed 50 characters.
|
||||||
|
- Limit description lines to 72 characters, except for code blocks or inline codes.
|
||||||
|
- Avoid including delta (such as `git diff` information) or a list of changed files in the commit message. This information is redundant as it's already part of the commit.
|
||||||
|
- Focus on explaining the WHY and HOW of the changes, rather than WHAT changes are.
|
||||||
|
- Begin the commit message with a concise summary of what the commit accomplishes.
|
||||||
|
- Use imperative language in the commit title. For example, use "add" instead of "added".
|
||||||
|
- Commit prefixes:
|
||||||
|
- Prefix bug fixes with `fix:` or `Fix ...`.
|
||||||
|
- For commits affecting scripts of specific operating systems:
|
||||||
|
- Prefix the commit title with an OS-specific tag such as `win:` for Windows scripts, `mac:` for macOS scripts, and `linux:` for Linux scripts.
|
||||||
|
- Combine prefixes for commits affecting more than one operating system, e.g., `win, mac: ...`.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
We base versioning on the release's content rather than strictly following semantic versioning.
|
||||||
|
|
||||||
|
There are two main types of releases:
|
||||||
|
|
||||||
|
1. **Patch Releases:** These focus on minor UI improvements, bug fixes, refactorings, dependency updates, and documentation updates. For scripts, they involve adjusting recommendation levels, enhancing functionality, and dividing scripts for more precise control. Patch releases may ship minor feature additions if they are essential for fixing a bug. For these updates, we increment the patch number in the `MAJOR.MINOR.PATCH`.
|
||||||
|
|
||||||
|
2. **Feature Releases:** These releases bring significant updates that change how users interact with privacy.sexy. They include major UI enhancements, the introduction of new scripts, and features. For these updates, we increment the minor number in the `MAJOR.MINOR.PATCH`.
|
||||||
|
|
||||||
|
Maintainers tag specific commits with a version number to trigger a release, and [bump-everywhere](https://github.com/undergroundwires/bump-everywhere) automates the release process including updating version numbers throughout the project.
|
||||||
|
|
||||||
|
## Refactoring
|
||||||
|
|
||||||
|
Opportunistic refactoring is welcome. If you're adding a feature or fixing a bug, feel free to also clean up and optimize the related code. Your contributions should leave the code in a better state than when you found it.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
By contributing, you agree that your [GNU General Public License v3.0](./LICENSE) will be the license for your contributions.
|
By contributing to this project, you agree that your contributions are licensed under the [GNU Affero General Public License](./LICENSE) as currently specified. Additionally, you expressly consent to the project maintainers having full authority to modify the licensing terms or relicense your contributions under different terms in the future.
|
||||||
|
|||||||
15
Dockerfile
@@ -1,13 +1,16 @@
|
|||||||
# Build
|
# Build
|
||||||
FROM node:lts-alpine as build-stage
|
FROM node:lts-alpine AS build-stage
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm install
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run build
|
RUN npm run install-deps
|
||||||
|
RUN npm run build \
|
||||||
|
&& npm run check:verify-build-artifacts -- --web
|
||||||
|
RUN mkdir /dist \
|
||||||
|
&& dist_directory=$(node 'scripts/print-dist-dir.js' --web) \
|
||||||
|
&& cp -a "${dist_directory}/." '/dist'
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM nginx:stable-alpine as production-stage
|
FROM nginx:stable-alpine AS production-stage
|
||||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
COPY --from=build-stage /dist /usr/share/nginx/html
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
141
LICENSE
@@ -1,5 +1,5 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
@@ -7,17 +7,15 @@
|
|||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
software and other kinds of works.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
share and change all versions of a program--to make sure it remains free
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
software for all its users.
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
@@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
|||||||
want it, that you can change the software or use pieces of it in new
|
want it, that you can change the software or use pieces of it in new
|
||||||
free programs, and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
Developers that use our General Public Licenses protect your rights
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
you this License which gives you legal permission to copy, distribute
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
and/or modify the software.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
A secondary benefit of defending all users' freedom is that
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
improvements made in alternate versions of the program, if they
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
receive widespread use, become available for other developers to
|
||||||
or can get the source code. And you must show them these terms so they
|
incorporate. Many developers of free software are heartened and
|
||||||
know their rights.
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
The GNU Affero General Public License is designed specifically to
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
ensure that, in such cases, the modified source code becomes available
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
An older license, called the Affero General Public License and
|
||||||
that there is no warranty for this free software. For both users' and
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
changed, so that their problems will not be attributed erroneously to
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
authors of previous versions.
|
this license.
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
@@ -72,7 +60,7 @@ modification follow.
|
|||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
@@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
|||||||
the Program, the only way you could satisfy both those terms and this
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
under version 3 of the GNU General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
combined work, and to convey the resulting work. The terms of this
|
||||||
License will continue to apply to the part which is the covered work,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the special requirements of the GNU Affero General Public License,
|
but the work with which it is combined will remain governed by version
|
||||||
section 13, concerning interaction through a network will apply to the
|
3 of the GNU General Public License.
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
the GNU General Public License from time to time. Such new versions will
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU General
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU General Public License, you may choose any version ever published
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
@@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
Copyright (C) <year> <name of author>
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
If your software can interact with users remotely through a computer
|
||||||
notice like this when it starts in an interactive mode:
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
<program> Copyright (C) <year> <name of author>
|
interface could display a "Source" link that leads users to an archive
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
of the code. There are many ways you could offer source, and different
|
||||||
This is free software, and you are welcome to redistribute it
|
solutions will be better for different programs; see section 13 for the
|
||||||
under certain conditions; type `show c' for details.
|
specific requirements.
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
<https://www.gnu.org/licenses/>.
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
||||||
|
|||||||
111
README.md
@@ -1,30 +1,22 @@
|
|||||||
# privacy.sexy — Now you have the choice
|
# privacy.sexy — Privacy is sexy
|
||||||
|
|
||||||
> Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy 🍑🍆
|
> Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy.
|
||||||
|
|
||||||
<!-- markdownlint-disable MD033 -->
|
<!-- markdownlint-disable MD033 -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://undergroundwires.dev/donate?project=privacy.sexy">
|
<a href="https://undergroundwires.dev/donate?project=privacy.sexy" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="donation badge"
|
alt="donation badge"
|
||||||
src="https://undergroundwires.dev/img/badges/donate/flat.svg"
|
src="https://undergroundwires.dev/img/badges/donate/flat.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/blob/master/CONTRIBUTING.md">
|
<a href="https://github.com/undergroundwires/privacy.sexy/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="contributions are welcome"
|
alt="contributions are welcome"
|
||||||
src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat"
|
src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<!-- Code quality -->
|
<a href="https://codeclimate.com/github/undergroundwires/privacy.sexy/maintainability" target="_blank" rel="noopener noreferrer">
|
||||||
<br />
|
|
||||||
<a href="https://lgtm.com/projects/g/undergroundwires/privacy.sexy/context:javascript">
|
|
||||||
<img
|
|
||||||
alt="Language grade: JavaScript/TypeScript"
|
|
||||||
src="https://img.shields.io/lgtm/grade/javascript/g/undergroundwires/privacy.sexy.svg?logo=lgtm&logoWidth=18"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="https://codeclimate.com/github/undergroundwires/privacy.sexy/maintainability">
|
|
||||||
<img
|
<img
|
||||||
alt="Maintainability"
|
alt="Maintainability"
|
||||||
src="https://api.codeclimate.com/v1/badges/3a70b7ef602e2264342c/maintainability"
|
src="https://api.codeclimate.com/v1/badges/3a70b7ef602e2264342c/maintainability"
|
||||||
@@ -32,59 +24,85 @@
|
|||||||
</a>
|
</a>
|
||||||
<!-- Tests -->
|
<!-- Tests -->
|
||||||
<br />
|
<br />
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/tests.unit.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/tests.unit.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Unit tests status"
|
alt="Unit tests status"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/unit-tests/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/unit-tests/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/tests.integration.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/tests.integration.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Integration tests status"
|
alt="Integration tests status"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/integration-tests/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/integration-tests/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/tests.e2e.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/tests.e2e.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="E2E tests status"
|
alt="E2E tests status"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/e2e-tests/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/e2e-tests/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
<!-- Security checks -->
|
||||||
|
<br />
|
||||||
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.security.sast.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img
|
||||||
|
alt="Status of dependency security checks"
|
||||||
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.security.sast/badge.svg"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.security.dependencies.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img
|
||||||
|
alt="Status of Static Analysis Security Testing (SAST)"
|
||||||
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.security.dependencies/badge.svg"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
<!-- Checks -->
|
<!-- Checks -->
|
||||||
<br />
|
<br />
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.quality.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.quality.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Quality checks status"
|
alt="Status of quality checks"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/quality-checks/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.quality/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.security.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.build.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Security checks status"
|
alt="Status of build checks"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/security-checks/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.build/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.build.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.desktop-runtime-errors.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Build checks status"
|
alt="Status of runtime error checks for the desktop application"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/build-checks/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.desktop-runtime-errors/badge.svg"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.scripts.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img
|
||||||
|
alt="Status of script checks"
|
||||||
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.scripts/badge.svg"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.external-urls.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img
|
||||||
|
alt="Status of external URL checks"
|
||||||
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.external-urls/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<!-- Release -->
|
<!-- Release -->
|
||||||
<br />
|
<br />
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/release.git.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/release.git.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Git release status"
|
alt="Git release status"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/release-git/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/release-git/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/release.site.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/release.site.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Site release status"
|
alt="Site release status"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/release-site/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/release-site/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/release.desktop.yaml">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/release.desktop.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Desktop application release status"
|
alt="Desktop application release status"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/release-desktop/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/release-desktop/badge.svg"
|
||||||
@@ -92,7 +110,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<!-- Others -->
|
<!-- Others -->
|
||||||
<br />
|
<br />
|
||||||
<a href="https://github.com/undergroundwires/bump-everywhere">
|
<a href="https://github.com/undergroundwires/bump-everywhere" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Auto-versioned by bump-everywhere"
|
alt="Auto-versioned by bump-everywhere"
|
||||||
src="https://github.com/undergroundwires/bump-everywhere/blob/master/badge.svg?raw=true"
|
src="https://github.com/undergroundwires/bump-everywhere/blob/master/badge.svg?raw=true"
|
||||||
@@ -104,11 +122,14 @@
|
|||||||
## Get started
|
## Get started
|
||||||
|
|
||||||
- 🌍️ **Online**: [https://privacy.sexy](https://privacy.sexy).
|
- 🌍️ **Online**: [https://privacy.sexy](https://privacy.sexy).
|
||||||
- 🖥️ **Offline**: Check [releases page](https://github.com/undergroundwires/privacy.sexy/releases), or download directly for: [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.11.2/privacy.sexy-Setup-0.11.2.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.11.2/privacy.sexy-0.11.2.dmg), [Linux](https://github.com/undergroundwires/pr.vacy.sexy/releases/download/0.11.2/privacy.sexy-0.11.2.AppImage).
|
- 🖥️ **Offline**: Download directly for: [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.13.3/privacy.sexy-Setup-0.13.3.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.13.3/privacy.sexy-0.13.3.dmg), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.13.3/privacy.sexy-0.13.3.AppImage). For more options, see [here](#additional-install-options).
|
||||||
|
|
||||||
Online version does not require to run any software on your computer. Offline version has more functions such as running the scripts directly.
|
See also:
|
||||||
|
|
||||||
💡 You should apply your configuration from time to time (more than once). It would strengthen your privacy and security control because privacy.sexy and its scripts get better and stronger in every new version.
|
- [Desktop vs. Web Features](./docs/desktop/desktop-vs-web-features.md): Differences and unique aspects of desktop and web versions.
|
||||||
|
- [System Requirements](./docs/desktop/system-requirements.md): Hardware and software requirements for the desktop version.
|
||||||
|
|
||||||
|
💡 Regularly applying your configuration with privacy.sexy is recommended, especially after each new release and major operating system updates. Each version updates scripts to enhance stability, privacy, and security.
|
||||||
|
|
||||||
[](https://privacy.sexy)
|
[](https://privacy.sexy)
|
||||||
|
|
||||||
@@ -119,6 +140,7 @@ Online version does not require to run any software on your computer. Offline ve
|
|||||||
- **Transparent**. Have full visibility into what the tweaks do as you enable them.
|
- **Transparent**. Have full visibility into what the tweaks do as you enable them.
|
||||||
- **Reversible**. Revert if something feels wrong.
|
- **Reversible**. Revert if something feels wrong.
|
||||||
- **Accessible**. No need to run any compiled software on your computer with web version.
|
- **Accessible**. No need to run any compiled software on your computer with web version.
|
||||||
|
- **Secure**: Security is a top priority at privacy.sexy with [comprehensive safeguards](./SECURITY.md#security-practices) in place.
|
||||||
- **Open**. What you see as code in this repository is what you get. The application itself, its infrastructure and deployments are open-source and automated thanks to [bump-everywhere](https://github.com/undergroundwires/bump-everywhere).
|
- **Open**. What you see as code in this repository is what you get. The application itself, its infrastructure and deployments are open-source and automated thanks to [bump-everywhere](https://github.com/undergroundwires/bump-everywhere).
|
||||||
- **Tested**. A lot of tests. Automated and manual. Community-testing and verification. Stability improvements comes before new features.
|
- **Tested**. A lot of tests. Automated and manual. Community-testing and verification. Stability improvements comes before new features.
|
||||||
- **Extensible**. Effortlessly [extend scripts](./CONTRIBUTING.md#extend-scripts) with a custom designed [templating language](./docs/templating.md).
|
- **Extensible**. Effortlessly [extend scripts](./CONTRIBUTING.md#extend-scripts) with a custom designed [templating language](./docs/templating.md).
|
||||||
@@ -132,6 +154,25 @@ Online version does not require to run any software on your computer. Offline ve
|
|||||||
|
|
||||||
**Contribute 👷**. Contributions of any type are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) as the starting point. It includes useful information like [how to add new scripts](./CONTRIBUTING.md#extend-scripts).
|
**Contribute 👷**. Contributions of any type are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) as the starting point. It includes useful information like [how to add new scripts](./CONTRIBUTING.md#extend-scripts).
|
||||||
|
|
||||||
|
## Additional Install Options
|
||||||
|
|
||||||
|
- Check the [releases page](https://github.com/undergroundwires/privacy.sexy/releases) for all available versions.
|
||||||
|
- Other unofficial channels (not maintained by privacy.sexy) for Windows include:
|
||||||
|
- [Scoop 🥄](https://scoop.sh/#/apps?q=privacy.sexy&s=2&d=1&o=true) (latest version):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop bucket add extras
|
||||||
|
scoop install privacy.sexy
|
||||||
|
```
|
||||||
|
|
||||||
|
- [winget 🪟](https://winget.run/pkg/undergroundwires/privacy.sexy) (may be outdated):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
winget install -e --id undergroundwires.privacy.sexy
|
||||||
|
```
|
||||||
|
|
||||||
|
With winget, updates require manual submission; the auto-update feature within privacy.sexy will notify you of new releases post-installation.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Refer to [development.md](./docs/development.md) for Docker usage and reading more about setting up your development environment.
|
Refer to [development.md](./docs/development.md) for Docker usage and reading more about setting up your development environment.
|
||||||
@@ -139,3 +180,9 @@ Refer to [development.md](./docs/development.md) for Docker usage and reading mo
|
|||||||
Check [architecture.md](./docs/architecture.md) for an overview of design and how different parts and layers work together. You can refer to [application.md](./docs/application.md) for a closer look at application layer codebase and [presentation.md](./docs/presentation.md) for code related to GUI layer. [collection-files.md](./docs/collection-files.md) explains the YAML files that are the core of the application and [templating.md](./docs/templating.md) documents how to use templating language in those files. In [ci-cd.md](./docs/ci-cd.md), you can read more about the pipelines that automates maintenance tasks and ensures you get what see.
|
Check [architecture.md](./docs/architecture.md) for an overview of design and how different parts and layers work together. You can refer to [application.md](./docs/application.md) for a closer look at application layer codebase and [presentation.md](./docs/presentation.md) for code related to GUI layer. [collection-files.md](./docs/collection-files.md) explains the YAML files that are the core of the application and [templating.md](./docs/templating.md) documents how to use templating language in those files. In [ci-cd.md](./docs/ci-cd.md), you can read more about the pipelines that automates maintenance tasks and ensures you get what see.
|
||||||
|
|
||||||
[docs/](./docs/) folder includes all other documentation.
|
[docs/](./docs/) folder includes all other documentation.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Security is a top priority at privacy.sexy.
|
||||||
|
An extensive commitment to security verification ensures this priority.
|
||||||
|
For any security concerns or vulnerabilities, please consult the [Security Policy](./SECURITY.md).
|
||||||
|
|||||||
77
SECURITY.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
Security is a top priority at privacy.sexy.
|
||||||
|
Please report any discovered vulnerabilities responsibly.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Efforts to responsibly disclose findings are greatly appreciated. To report a security vulnerability, follow these steps:
|
||||||
|
|
||||||
|
- For general vulnerabilities, [open an issue](https://github.com/undergroundwires/privacy.sexy/issues/new/choose) using the bug report template.
|
||||||
|
- For sensitive matters, [contact the developer directly](https://undergroundwires.dev).
|
||||||
|
|
||||||
|
## Security Report Handling
|
||||||
|
|
||||||
|
Upon receiving a security report, the process involves:
|
||||||
|
|
||||||
|
- Confirming the report and identifying affected components.
|
||||||
|
- Assessing the impact and severity of the issue.
|
||||||
|
- Fixing the vulnerability and planning a release to address it.
|
||||||
|
- Keeping the reporter informed about progress.
|
||||||
|
|
||||||
|
## Security Practices
|
||||||
|
|
||||||
|
### Application Security
|
||||||
|
|
||||||
|
privacy.sexy adopts a defense in depth strategy to protect users on multiple layers:
|
||||||
|
|
||||||
|
- **Link Protection:**
|
||||||
|
privacy.sexy ensures each external link has special attributes for your privacy and security.
|
||||||
|
These attributes block the new site from accessing the privacy.sexy page, increasing your online safety and privacy.
|
||||||
|
- **Content Security Policies (CSP):**
|
||||||
|
privacy.sexy actively follows security guidelines from the Open Web Application Security Project (OWASP) at strictest level.
|
||||||
|
This approach protects against attacks like Cross Site Scripting (XSS) and data injection.
|
||||||
|
- **Host System Access Control:**
|
||||||
|
The desktop application segregates and isolates code sections based on their access levels through sandboxing.
|
||||||
|
This provides a critical defense mechanism, prevents attackers from introducing harmful code into the app, known as injection attacks.
|
||||||
|
- **Auditing and Transparency:**
|
||||||
|
The desktop application improves security and transparency by logging application activities and retaining files of executed scripts
|
||||||
|
This facilitates detailed auditability and effective troubleshooting, contributing to the integrity and reliability of the application.
|
||||||
|
Recognizing that some users prefer not to keep these records, privacy.sexy provides specialized scripts for deletion of these logs.
|
||||||
|
- **Privilege Management:**
|
||||||
|
The desktop application operates without persistent administrative or `sudo` privileges, reinforcing its security posture. It requests
|
||||||
|
elevation of privileges for system modifications with explicit user consent and logs every action taken with high privileges. This
|
||||||
|
approach actively minimizes potential security risks by limiting privileged operations and aligning with the principle of least privilege.
|
||||||
|
- **Secure Script Execution/Storage:**
|
||||||
|
- **Antivirus scans:**
|
||||||
|
Before executing any script, the desktop application stores a copy to allow antivirus software to perform scans.
|
||||||
|
This step allows confirming that the scripts are secure and safe to use.
|
||||||
|
- **Tamper protection:**
|
||||||
|
The application incorporates integrity checks for tamper protection.
|
||||||
|
If the script file differs from the user's selected script, the application will not execute or save the script, ensuring the processing
|
||||||
|
of authentic scripts.
|
||||||
|
This safeguards against any unwanted modifications.
|
||||||
|
- **Clean-up:**
|
||||||
|
Recognizing that some users prefer not to keep these records, privacy.sexy provides specialized scripts for deletion of these scripts.
|
||||||
|
This allows users to maintain their privacy by removing traces of their usage patterns or script preferences.
|
||||||
|
|
||||||
|
### Update Security and Integrity
|
||||||
|
|
||||||
|
privacy.sexy benefits from automated update processes including security tests. Automated deployments from source code ensure immediate and secure updates, mirroring the latest source code. This aligns the deployed application with the expected source code, enhancing transparency and trust. For more details, see [CI/CD Documentation](./docs/ci-cd.md).
|
||||||
|
|
||||||
|
Every desktop update undergoes a thorough verification process. Updates are cryptographically signed to ensure authenticity and integrity, preventing tampered versions from reaching your device. Version checks are conducted to prevent downgrade attacks.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
privacy.sexy's testing approach includes a mix of automated and community-driven tests.
|
||||||
|
Details on testing practices are available in the [Testing Documentation](./docs/tests.md).
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For help or any questions, [submit a GitHub issue](https://github.com/undergroundwires/privacy.sexy/issues/new/choose). Addressing security concerns is a priority, and we ensure the necessary support.
|
||||||
|
|
||||||
|
Support privacy.sexy's commitment to security by [making a donation ❤️](https://github.com/sponsors/undergroundwires). Your contributions aid in maintaining and enhancing the project's security features.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Active contribution to the safety and security of privacy.sexy is thanked. This collaborative effort keeps the project resilient and trustworthy for all.
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
'@vue/cli-plugin-babel/preset',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# build
|
|
||||||
|
|
||||||
This folder contains files that are used by Electron to serve the desktop version.
|
|
||||||
|
|
||||||
Icons are created from the main logo file and should not be changed manually, see [related documentation](./../img/README.md).
|
|
||||||
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 553 B |
|
Before Width: | Height: | Size: 963 B |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
5
cypress-dirs.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"base": "tests/e2e",
|
||||||
|
"videos": "tests/e2e/videos",
|
||||||
|
"screenshots": "tests/e2e/videos"
|
||||||
|
}
|
||||||
@@ -1,14 +1,31 @@
|
|||||||
import { defineConfig } from 'cypress'
|
import { defineConfig } from 'cypress';
|
||||||
|
import ViteConfig from './vite.config';
|
||||||
|
import cypressDirs from './cypress-dirs.json' assert { type: 'json' };
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
fixturesFolder: 'tests/e2e/fixtures',
|
fixturesFolder: `${cypressDirs.base}/fixtures`,
|
||||||
screenshotsFolder: 'tests/e2e/screenshots',
|
screenshotsFolder: cypressDirs.screenshots,
|
||||||
videosFolder: 'tests/e2e/videos',
|
|
||||||
|
video: true,
|
||||||
|
videosFolder: cypressDirs.videos,
|
||||||
|
|
||||||
e2e: {
|
e2e: {
|
||||||
setupNodeEvents(on, config) {
|
baseUrl: `http://localhost:${getApplicationPort()}/`,
|
||||||
return require('./tests/e2e/plugins/index.js')(on, config)
|
specPattern: `${cypressDirs.base}/**/*.cy.{js,jsx,ts,tsx}`, // Default: cypress/e2e/**/*.cy.{js,jsx,ts,tsx}
|
||||||
},
|
supportFile: `${cypressDirs.base}/support/e2e.ts`,
|
||||||
specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}',
|
|
||||||
supportFile: 'tests/e2e/support/index.js',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Disabling Chrome's web security to allow for faster DOM queries to access DOM earlier than
|
||||||
|
`cy.get()`. It bypasses the usual same-origin policy constraints
|
||||||
|
*/
|
||||||
|
chromeWebSecurity: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getApplicationPort(): number {
|
||||||
|
const port = ViteConfig.server?.port;
|
||||||
|
if (port === undefined) {
|
||||||
|
throw new Error('Unknown application port');
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|||||||
5
dist-dirs.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"electronUnbundled": "dist-electron-unbundled",
|
||||||
|
"electronBundled": "dist-electron-bundled",
|
||||||
|
"web": "dist-web"
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ Application layer enables [data-driven programming](https://en.wikipedia.org/wik
|
|||||||
|
|
||||||
Application layer parses the application data to compile the domain object [`Application.ts`](./../src/domain/Application.ts).
|
Application layer parses the application data to compile the domain object [`Application.ts`](./../src/domain/Application.ts).
|
||||||
|
|
||||||
A webpack loader loads (or injects) application data ([collection yaml files](./../src/application/collections/)) into the application layer in compile time. Application layer ([`ApplicationFactory.ts`](./../src/application/ApplicationFactory.ts)) parses and compiles this data in runtime.
|
The build tool loads (or injects) application data ([collection yaml files](./../src/application/collections/)) into the application layer in compile time. Application layer ([`ApplicationFactory.ts`](./../src/application/ApplicationFactory.ts)) parses and compiles this data in runtime.
|
||||||
|
|
||||||
Application layer compiles templating syntax during parsing to create the end scripts. You can read more about templating syntax in [templating.md](./templating.md) and how application data uses them through functions in [collection-files.md | Function](./collection-files.md#function).
|
Application layer compiles templating syntax during parsing to create the end scripts. You can read more about templating syntax in [templating.md](./templating.md) and how application data uses them through functions in [collection-files.md | Function](./collection-files.md#function).
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,33 @@ Application is
|
|||||||
|
|
||||||
Application uses highly decoupled models & services in different DDD layers:
|
Application uses highly decoupled models & services in different DDD layers:
|
||||||
|
|
||||||
- presentation layer (see [presentation.md](./presentation.md)),
|
**Application layer** (see [application.md](./application.md)):
|
||||||
- application layer (see [application.md](./application.md)),
|
|
||||||
- and domain layer.
|
|
||||||
|
|
||||||
Application layer depends on and consumes domain layer. [Presentation layer](./presentation.md) consumes and depends on application layer along with domain layer. Application and presentation layers can communicate through domain model.
|
- Coordinates application activities and consumes the domain layer.
|
||||||
|
|
||||||

|
**Presentation layer** (see [presentation.md](./presentation.md)):
|
||||||
|
|
||||||
|
- Handles UI/UX, consumes both the application and domain layers.
|
||||||
|
- May communicate directly with the infrastructure layer for technical needs, but avoids domain logic.
|
||||||
|
|
||||||
|
**Domain layer**:
|
||||||
|
|
||||||
|
- Serves as the system's core and central truth.
|
||||||
|
- It should be independent of other layers and encapsulate the core business concepts.
|
||||||
|
|
||||||
|
**Infrastructure layer**:
|
||||||
|
|
||||||
|
- Provides technical implementations.
|
||||||
|
- Depends on the application and domain layers in terms of interfaces and contracts but should not include business logic.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### Application state
|
### Application state
|
||||||
|
|
||||||
State handling uses an event-driven subscription model to signal state changes and special functions to register changes. It does not depend on third party packages.
|
State handling uses an event-driven subscription model to signal state changes and special functions to register changes. It does not depend on third party packages.
|
||||||
|
|
||||||
|
The presentation layer can read and modify state through the context. State changes trigger events that components can subscribe to for reactivity.
|
||||||
|
|
||||||
Each layer treat application layer differently.
|
Each layer treat application layer differently.
|
||||||
|
|
||||||

|

|
||||||
@@ -45,7 +60,7 @@ Each layer treat application layer differently.
|
|||||||
- So state is mutable, and fires related events when mutated.
|
- So state is mutable, and fires related events when mutated.
|
||||||
- 📖 Read more: [application.md | Application state](./application.md#application-state).
|
- 📖 Read more: [application.md | Application state](./application.md#application-state).
|
||||||
|
|
||||||
It's comparable with flux ([`redux`](https://redux.js.org/)) or flux-like ([`vuex`](https://vuex.vuejs.org/)) patterns. Flux component "view" is [presentation layer](./presentation.md) in Vue. Flux functions "dispatcher", "store" and "action creation" functions lie in the [application layer](./application.md). A difference is that application state in privacy.sexy is mutable and lies in single flux "store" that holds app state and logic. The "actions" mutate the state directly which in turns act as dispatcher to notify its own event subscriptions (callbacks).
|
It's comparable with `flux`, `vuex`, and `pinia`. A difference is that mutable application layer state in privacy.sexy is mutable and lies in single "store" that holds app state and logic. The "actions" mutate the state directly which in turns act as dispatcher to notify its own event subscriptions (callbacks).
|
||||||
|
|
||||||
## AWS infrastructure
|
## AWS infrastructure
|
||||||
|
|
||||||
|
|||||||
@@ -1,176 +1,164 @@
|
|||||||
# Collection files
|
# Collection files
|
||||||
|
|
||||||
- privacy.sexy is a data-driven application where it reads the necessary OS-specific logic from yaml files in [`application/collections`](./../src/application/collections/)
|
privacy.sexy is a data-driven application that reads YAML files.
|
||||||
- 💡 Best practices
|
This document details the structure and syntax of the YAML files located in [`application/collections`](./../src/application/collections/), which form the backbone of the application's data model.
|
||||||
- If you repeat yourself, try to utilize [YAML-defined functions](#function)
|
|
||||||
- Always try to add documentation and a way to revert a tweak in [scripts](#script)
|
Related documentation:
|
||||||
- 📖 Types in code: [`collection.yaml.d.ts`](./../src/application/collections/collection.yaml.d.ts)
|
|
||||||
|
- 📖 [`collection.yaml.d.ts`](./../src/application/collections/collection.yaml.d.ts) outlines code types.
|
||||||
|
- 📖 [Script Guidelines](./script-guidelines.md) provide guidance on script creation including best-practices.
|
||||||
|
|
||||||
## Objects
|
## Objects
|
||||||
|
|
||||||
### `Collection`
|
### `Collection`
|
||||||
|
|
||||||
- A collection simply defines:
|
- Defines categories, scripts, and OS-specific details in a tree structure.
|
||||||
- different categories and their scripts in a tree structure
|
- Allows defining common [functions](#function) for code reuse.
|
||||||
- OS specific details
|
|
||||||
- Also allows defining common [function](#function)s to be used throughout the collection if you'd like different scripts to share same code.
|
|
||||||
|
|
||||||
#### `Collection` syntax
|
#### `Collection` syntax
|
||||||
|
|
||||||
- `os:` *`string`* (**required**)
|
- `os:` *`string`* **(required)**
|
||||||
- Operating system that the [Collection](#collection) is written for.
|
- Operating system for the collection.
|
||||||
- 📖 See [OperatingSystem.ts](./../src/domain/OperatingSystem.ts) enumeration for allowed values.
|
- 📖 See [`OperatingSystem.ts`](./../src/domain/OperatingSystem.ts) for possible values.
|
||||||
- `actions: [` ***[`Category`](#category)*** `, ... ]` **(required)**
|
- `actions: [` ***[`Category`](#category)*** `, ... ]` **(required)**
|
||||||
- Each [category](#category) is rendered as different cards in card presentation.
|
- Renders each parent category as cards in the user interface.
|
||||||
- ❗ A [Collection](#collection) must consist of at least one category.
|
- ❗ A [Collection](#collection) must consist of at least one category.
|
||||||
- `functions: [` ***[`Function`](#function)*** `, ... ]`
|
- `functions: [` ***[`Function`](#function)*** `, ... ]`
|
||||||
- Functions are optionally defined to re-use the same code throughout different scripts.
|
- Optional for code reuse.
|
||||||
- `scripting:` ***[`ScriptingDefinition`](#scriptingdefinition)*** **(required)**
|
- `scripting:` ***[`ScriptingDefinition`](#scriptingdefinition)*** **(required)**
|
||||||
- Defines the scripting language that the code of other action uses.
|
- Sets the scripting language for all inline code used within the collection.
|
||||||
|
|
||||||
### `Category`
|
### `Category`
|
||||||
|
|
||||||
- Category has a parent that has tree-like structure where it can have subcategories or subscripts.
|
Represents a logical group of scripts and subcategories.
|
||||||
- It's a logical grouping of different scripts and other categories.
|
|
||||||
|
|
||||||
#### `Category` syntax
|
#### `Category` syntax
|
||||||
|
|
||||||
- `category:` *`string`* (**required**)
|
- `category:` *`string`* **(required)**
|
||||||
- Name of the category
|
- Name of the category.
|
||||||
- ❗ Must be unique throughout the [Collection](#collection)
|
- ❗ Must be unique throughout the [collection](#collection).
|
||||||
- `children: [` ***[`Category`](#category)*** `|` [***`Script`***](#script) `, ... ]` (**required**)
|
- `children: [` ***[`Category`](#category)*** `|` [***`Script`***](#script) `, ... ]` **(required)**
|
||||||
- ❗ Category must consist of at least one subcategory or script.
|
- ❗ Category must consist of at least one subcategory or script.
|
||||||
- Children can be combination of scripts and subcategories.
|
- Children can be combination of scripts and subcategories.
|
||||||
- `docs`: *`string`* | `[`*`string`*`, ... ]`
|
- `docs`: *`string`* | `[`*`string`*`, ... ]`
|
||||||
- Documentation pieces related to the category.
|
- Markdown-formatted documentation related to the category.
|
||||||
- Rendered as markdown.
|
|
||||||
|
|
||||||
### `Script`
|
### `Script`
|
||||||
|
|
||||||
- Script represents a single tweak.
|
Represents an individual tweak.
|
||||||
- A script can be of two different types (just like [functions](#function)):
|
|
||||||
1. Inline script; a script with an inline code
|
Types (like [functions](#function)):
|
||||||
- Must define `code` property and optionally `revertCode` but not `call`
|
|
||||||
2. Caller script; a script that calls other functions
|
1. Inline script:
|
||||||
- Must define `call` property but not `code` or `revertCode`
|
- Direct code.
|
||||||
- 🙏 For any new script, please add `revertCode` and `docs` values if possible.
|
- ❗ Requires `code` and optional `revertCode`.
|
||||||
|
2. Caller script:
|
||||||
|
- Calls other [functions](#function).
|
||||||
|
- ❗ Requires `call`, but not `code` or `revertCode`.
|
||||||
|
|
||||||
|
📖 For detailed guidelines, see [Script Guidelines](./script-guidelines.md).
|
||||||
|
|
||||||
#### `Script` syntax
|
#### `Script` syntax
|
||||||
|
|
||||||
- `name`: *`string`* (**required**)
|
- `name`: *`string`* **(required)**
|
||||||
- Name of the script
|
- Script name.
|
||||||
- ❗ Must be unique throughout the [Collection](#collection)
|
- ❗ Must be unique throughout the [Collection](#collection).
|
||||||
- E.g. `Disable targeted ads`
|
- `code`: *`string`* **(conditionally required)**
|
||||||
- `code`: *`string`* (may be **required**)
|
- Code to execute when the user selects the script.
|
||||||
- Batch file commands that will be executed
|
- 💡 If defined, it's best practice to also define `revertCode`.
|
||||||
- 💡 If defined, best practice to also define `revertCode`
|
- ❗ Cannot co-exist with `call`, define either `code` with optional `revertCode` or `call`.
|
||||||
- ❗ If not defined `call` must be defined, do not define if `call` is defined.
|
- `revertCode`: *`string`*
|
||||||
- `revertCode`: `string`
|
- Reverts changes made by `code`.
|
||||||
- Code that'll undo the change done by `code` property.
|
- ❗ Cannot co-exist with `call`, define `revertCode` with `code` or `call`.
|
||||||
- E.g. let's say `code` sets an environment variable as `setx POWERSHELL_TELEMETRY_OPTOUT 1`
|
- `call`: ***[`FunctionCall`](#functioncall)*** | `[` ***[`FunctionCall`](#functioncall)*** `, ... ]` **(conditionally required)**
|
||||||
- then `revertCode` should be doing `setx POWERSHELL_TELEMETRY_OPTOUT 0`
|
- A shared function or sequence of functions to call (called in order).
|
||||||
- ❗ Do not define if `call` is defined.
|
- ❗ Cannot co-exist with `code` or `revertCode`, define `code` with optional `revertCode` or `call`.
|
||||||
- `call`: ***[`FunctionCall`](#functioncall)*** | `[` ***[`FunctionCall`](#functioncall)*** `, ... ]` (may be **required**)
|
|
||||||
- A shared function or sequence of functions to call (called in order)
|
|
||||||
- ❗ If not defined `code` must be defined
|
|
||||||
- `docs`: *`string`* | `[`*`string`*`, ... ]`
|
- `docs`: *`string`* | `[`*`string`*`, ... ]`
|
||||||
- Documentation pieces related to the script.
|
- Markdown-formatted documentation related to the script.
|
||||||
- Rendered as markdown.
|
- `recommend`: *`"standard"`* | *`"strict"`* | *`undefined`* (default: `undefined`)
|
||||||
- `recommend`: `"standard"` | `"strict"` | `undefined` (default)
|
- Sets recommendation level.
|
||||||
- If not defined then the script will not be recommended
|
- Application will not recommend the script if `undefined`.
|
||||||
- If defined it can be either
|
|
||||||
- `standard`: Only non-breaking scripts without limiting OS functionality
|
📖 For detailed guidelines, see [Script Guidelines](./script-guidelines.md).
|
||||||
- `strict`: Scripts that can break certain functionality in favor of privacy and security
|
|
||||||
|
|
||||||
### `FunctionCall`
|
### `FunctionCall`
|
||||||
|
|
||||||
- Describes a single call to a function by optionally providing values to its parameters.
|
Specifies a function call. It may require providing argument values to its parameters.
|
||||||
- 👀 See [parameter substitution](./templating.md#parameter-substitution) for an example usage
|
|
||||||
|
|
||||||
#### `FunctionCall` syntax
|
#### `FunctionCall` syntax
|
||||||
|
|
||||||
- `function`: *`string`* (**required**)
|
- `function`: *`string`* **(required)**
|
||||||
- Name of the function to call.
|
- Name of the function to call.
|
||||||
- ❗ Function with same name must defined in `functions` property of [Collection](#collection)
|
- ❗ Function with same name must defined in `functions` property of [Collection](#collection).
|
||||||
- `parameters`: `[ parameterName:` *`parameterValue`*`, ... ]`
|
- `parameters`: `[` *`parameterName: parameterValue`* `, ... ]`
|
||||||
- Defines key value dictionary for each parameter and its value
|
- Key-value pairs representing function parameters and their corresponding argument values.
|
||||||
- E.g.
|
- 📖 See [parameter substitution](./templating.md#parameter-substitution) for an example usage.
|
||||||
|
- 💡 You can use [expressions (templating)](./templating.md#expressions) when providing argument values for parameters.
|
||||||
```yaml
|
|
||||||
parameters:
|
|
||||||
userDefinedParameterName: parameterValue
|
|
||||||
# ...
|
|
||||||
appName: Microsoft.WindowsFeedbackHub
|
|
||||||
```
|
|
||||||
|
|
||||||
- 💡 [Expressions (templating)](./templating.md#expressions) can be used as parameter value
|
|
||||||
|
|
||||||
### `Function`
|
### `Function`
|
||||||
|
|
||||||
- Functions allow re-usable code throughout the defined scripts.
|
- Enables reusable code in scripts.
|
||||||
- Functions are templates compiled by privacy.sexy and uses special expression expressions.
|
- Functions are templates compiled by privacy.sexy and uses special expression expressions.
|
||||||
- A function can be of two different types (just like [scripts](#script)):
|
- A function can be of two different types (like [scripts](#script)):
|
||||||
1. Inline function: a function with an inline code.
|
1. Inline function: a function with an inline code.
|
||||||
- Must define `code` property and optionally `revertCode` but not `call`.
|
- ❗ Requires `code` and optionally `revertCode`, but not `call`.
|
||||||
2. Caller function: a function that calls other functions.
|
2. Caller function: a function that calls other functions.
|
||||||
- Must define `call` property but not `code` or `revertCode`.
|
- ❗ Requires `call`, but not `code` or `revertCode`.
|
||||||
- 👀 Read more on [Templating](./templating.md) for function expressions and [example usages](./templating.md#parameter-substitution).
|
- 📖 Read about function expressions in [Templating](./templating.md) with [example usages](./templating.md#parameter-substitution).
|
||||||
|
|
||||||
#### `Function` syntax
|
#### `Function` syntax
|
||||||
|
|
||||||
- `name`: *`string`* (**required**)
|
- `name`: *`string`* **(required)**
|
||||||
- Name of the function that scripts will use.
|
- Name of the function that scripts will use.
|
||||||
- Convention is to use camelCase, and be verbs.
|
- ❗ Function names must be unique.
|
||||||
- E.g. `uninstallStoreApp`
|
- ❗ Function names must follow camelCase and start with verbs (e.g., `uninstallStoreApp`).
|
||||||
- ❗ Function names must be unique
|
- `parameters`: `[` ***[`FunctionParameter`](#functionparameter)*** `, ... ]` **(conditionally required)**
|
||||||
- `parameters`: `[` ***[`FunctionParameter`](#functionparameter)*** `, ... ]`
|
- Lists parameters used.
|
||||||
- List of parameters that function code refers to.
|
- ❗ Required to be able use in [`FunctionCall`](#functioncall) or [expressions (templating)](./templating.md#expressions).
|
||||||
- ❗ Must be defined to be able use in [`FunctionCall`](#functioncall) or [expressions (templating)](./templating.md#expressions)
|
- `code`: *`string`* **(conditionally required)**
|
||||||
`code`: *`string`* (**required** if `call` is undefined)
|
- Code to execute when the user selects the script.
|
||||||
- Batch file commands that will be executed
|
- 💡 You can use [expressions (templating)](./templating.md#expressions) in its value.
|
||||||
- 💡 [Expressions (templating)](./templating.md#expressions) can be used in its value
|
- 💡 If defined, it's best practice to also define `revertCode`.
|
||||||
- 💡 If defined, best practice to also define `revertCode`
|
- ❗ Cannot co-exist with `call`, define either `code` with optional `revertCode` or `call`.
|
||||||
- ❗ If not defined `call` must be defined
|
|
||||||
- `revertCode`: *`string`*
|
- `revertCode`: *`string`*
|
||||||
- Code that'll undo the change done by `code` property.
|
- Reverts changes made by `code`.
|
||||||
- E.g. let's say `code` sets an environment variable as `setx POWERSHELL_TELEMETRY_OPTOUT 1`
|
- 💡 You can use [expressions (templating)](./templating.md#expressions) in its value.
|
||||||
- then `revertCode` should be doing `setx POWERSHELL_TELEMETRY_OPTOUT 0`
|
- ❗ Cannot co-exist with `call`, define `revertCode` with `code` or `call`.
|
||||||
- 💡 [Expressions (templating)](./templating.md#expressions) can be used in code
|
- `call`: ***[`FunctionCall`](#functioncall)*** | `[` ***[`FunctionCall`](#functioncall)*** `, ... ]` **(conditionally required)**
|
||||||
- `call`: ***[`FunctionCall`](#functioncall)*** | `[` ***[`FunctionCall`](#functioncall)*** `, ... ]` (may be **required**)
|
- A shared function or sequence of functions to call (called in order).
|
||||||
- A shared function or sequence of functions to call (called in order)
|
- 💡 You can use [expressions (templating)](./templating.md#expressions) in argument values provided for parameters.
|
||||||
- The parameter values that are sent can use [expressions (templating)](./templating.md#expressions)
|
- ❗ Cannot co-exist with `code` or `revertCode`, define `code` with optional `revertCode` or `call`.
|
||||||
- ❗ If not defined `code` must be defined
|
|
||||||
|
|
||||||
### `FunctionParameter`
|
### `FunctionParameter`
|
||||||
|
|
||||||
- Defines a parameter that function requires optionally or mandatory.
|
- Defines a single parameter that may require an argument value optionally or mandatory.
|
||||||
- Its arguments are provided by a [Script](#script) through a [FunctionCall](#functioncall).
|
- A [`FunctionCall`](#functioncall) provides argument values by a caller.
|
||||||
|
- A caller can be a [Script](#script) or [Function](#function).
|
||||||
|
|
||||||
#### `FunctionParameter` syntax
|
#### `FunctionParameter` syntax
|
||||||
|
|
||||||
- `name`: *`string`* (**required**)
|
- `name`: *`string`* **(required)**
|
||||||
- Name of the parameters that the function has.
|
- Name of the parameter that the function has.
|
||||||
- Parameter names must be defined to be used in [expressions (templating)](./templating.md#expressions).
|
- ❗ Required for [expressions (templating)](./templating.md#expressions).
|
||||||
- ❗ Parameter names must be unique and include alphanumeric characters only.
|
- ❗ Must be unique and consists of alphanumeric characters.
|
||||||
- `optional`: *`boolean`* (default: `false`)
|
- `optional`: *`boolean`* (default: `false`)
|
||||||
- Specifies whether the caller [Script](#script) must provide any value for the parameter.
|
- Indicates the caller must provide and argument value for the parameter.
|
||||||
- If set to `false` i.e. an argument value is not optional then it expects a non-empty value for the variable;
|
- 💡 If set to `false` i.e. an argument value is not optional then it expects a non-empty value for the variable.
|
||||||
- Otherwise it throws.
|
- E.g., in a [`with` expression](./templating.md#with).
|
||||||
- 💡 Set it to `true` if a parameter is used conditionally;
|
- 💡 Set it to `true` if you will use its argument value conditionally;
|
||||||
- Or else set it to `false` for verbosity or do not define it as default value is `false` anyway.
|
- Or else set it to `false` for verbosity or do not define it as default value is `false` anyway.
|
||||||
- 💡 Can be used in conjunction with [`with` expression](./templating.md#with).
|
|
||||||
|
|
||||||
### `ScriptingDefinition`
|
### `ScriptingDefinition`
|
||||||
|
|
||||||
- Defines global properties for scripting that's used throughout its parent [Collection](#collection).
|
Sets global scripting properties for a [Collection](#collection).
|
||||||
|
|
||||||
#### `ScriptingDefinition` syntax
|
#### `ScriptingDefinition` syntax
|
||||||
|
|
||||||
- `language:` *`string`* (**required**)
|
- `language:` *`string`* **(required)**
|
||||||
- 📖 See [ScriptingLanguage.ts](./../src/domain/ScriptingLanguage.ts) enumeration for allowed values.
|
- 📖 See [`ScriptingLanguage.ts`](./../src/domain/ScriptingLanguage.ts) enumeration for allowed values.
|
||||||
- `startCode:` *`string`* (**required**)
|
- `startCode:` *`string`* **(required)**
|
||||||
- Code that'll be inserted on top of user created script.
|
- Prepends the given code to the generated script file.
|
||||||
- Global variables such as `$homepage`, `$version`, `$date` can be used using [parameter substitution](./templating.md#parameter-substitution) code syntax such as `Welcome to {{ $homepage }}!`
|
- 💡 You can use global variables such as `$homepage`, `$version`, `$date` via [parameter substitution](./templating.md#parameter-substitution) code syntax such as `Welcome to {{ $homepage }}!`.
|
||||||
- `endCode:` *`string`* (**required**)
|
- `endCode:` *`string`* **(required)**
|
||||||
- Code that'll be inserted at the end of user created script.
|
- Appends to the given code to the generated script file.
|
||||||
- Global variables such as `$homepage`, `$version`, `$date` can be used using [parameter substitution](./templating.md#parameter-substitution) code syntax such as `Welcome to {{ $homepage }}!`
|
- 💡 You can use global variables such as `$homepage`, `$version`, `$date` via [parameter substitution](./templating.md#parameter-substitution) code syntax such as `Welcome to {{ $homepage }}!`.
|
||||||
|
|||||||
93
docs/desktop/desktop-vs-web-features.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Desktop vs. Web Features
|
||||||
|
|
||||||
|
This table outlines the differences between the desktop and web versions of `privacy.sexy`.
|
||||||
|
|
||||||
|
| Feature | Desktop | Web |
|
||||||
|
| ------- | ------- | --- |
|
||||||
|
| [Usage without installation](#usage-without-installation) | 🔴 Not available | 🟢 Available |
|
||||||
|
| [Offline usage](#offline-usage) | 🟢 Available | 🟡 Partially available |
|
||||||
|
| [Auto-updates](#auto-updates) | 🟢 Available | 🟢 Available |
|
||||||
|
| [Logging](#logging) | 🟢 Available | 🔴 Not available |
|
||||||
|
| [Secure script execution/storage](#secure-script-executionstorage) | 🟢 Available | 🔴 Not available |
|
||||||
|
| [Native dialogs](#native-dialogs) | 🟢 Available | 🔴 Not available |
|
||||||
|
|
||||||
|
## Feature descriptions
|
||||||
|
|
||||||
|
### Usage without installation
|
||||||
|
|
||||||
|
You can use the web version directly in a browser without installation.
|
||||||
|
The desktop version requires download and installation.
|
||||||
|
|
||||||
|
> **Note for Linux users:** On Linux, privacy.sexy is available as an `AppImage`, a portable format that doesn't need traditional installation.
|
||||||
|
> This allows Linux users to use the desktop version without full installation, akin to the web version.
|
||||||
|
|
||||||
|
### Offline usage
|
||||||
|
|
||||||
|
The web version, once loaded, supports offline use.
|
||||||
|
Desktop version inherently allows offline usage.
|
||||||
|
|
||||||
|
### Auto-updates
|
||||||
|
|
||||||
|
Both the desktop and web versions of privacy.sexy provide timely access to the latest features and security improvements. The updates are automatically deployed from source code, reflecting the latest changes for enhanced security and reliability. For more details, see [CI/CD documentation](./../ci-cd.md).
|
||||||
|
|
||||||
|
The desktop version ensures secure delivery through cryptographic signatures and version checks.
|
||||||
|
|
||||||
|
[Security is a top priority](./../../SECURITY.md#update-security-and-integrity) at privacy.sexy.
|
||||||
|
|
||||||
|
> **Note for macOS users:** On macOS, the desktop version's auto-update process involves manual steps due to Apple's code signing costs.
|
||||||
|
> Users get notified about updates but might need to complete the installation manually.
|
||||||
|
> Consider [donating](https://github.com/sponsors/undergroundwires) to help improve this process ❤️.
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
The desktop version supports logging of activities to aid in troubleshooting.
|
||||||
|
This feature is not available in the web version.
|
||||||
|
|
||||||
|
Log file locations vary by operating system:
|
||||||
|
|
||||||
|
- macOS: `$HOME/Library/Logs/privacy.sexy`
|
||||||
|
- Linux: `$HOME/.config/privacy.sexy/logs`
|
||||||
|
- Windows: `%APPDATA%\privacy.sexy\logs`
|
||||||
|
|
||||||
|
> 💡 privacy.sexy provides scripts to securely erase these logs.
|
||||||
|
|
||||||
|
### Secure script execution/storage
|
||||||
|
|
||||||
|
The desktop version of privacy.sexy enables direct script execution, providing a seamless and integrated experience.
|
||||||
|
This direct execution capability isn't available in the web version due to inherent browser restrictions.
|
||||||
|
|
||||||
|
**Script execution history:**
|
||||||
|
|
||||||
|
For enhanced auditability and easier troubleshooting, the desktop version keeps a record of executed scripts in designated directories.
|
||||||
|
These locations vary based on the operating system:
|
||||||
|
|
||||||
|
- macOS: `$HOME/Library/Application Support/privacy.sexy/runs`
|
||||||
|
- Linux: `$HOME/.config/privacy.sexy/runs`
|
||||||
|
- Windows: `%APPDATA%\privacy.sexy\runs`
|
||||||
|
|
||||||
|
> 💡 privacy.sexy provides scripts to securely erase your script execution history.
|
||||||
|
|
||||||
|
**Script antivirus scans:**
|
||||||
|
|
||||||
|
To enhance system protection, the desktop version of privacy.sexy automatically verifies the security of script
|
||||||
|
execution files by reading them back.
|
||||||
|
This process triggers antivirus scans to verify that scripts are safe before the execution.
|
||||||
|
|
||||||
|
**Script integrity checks:**
|
||||||
|
|
||||||
|
The desktop version of privacy.sexy implements robust integrity checks for both script execution and storage.
|
||||||
|
Featuring tamper protection, the application actively verifies the integrity of script files before executing or saving them.
|
||||||
|
If the actual contents of a script file do not align with the expected contents, the application refuses to execute or save the script.
|
||||||
|
This proactive approach ensures only unaltered and verified scripts undergo processing, thereby enhancing both security and reliability.
|
||||||
|
|
||||||
|
**Error handling:**
|
||||||
|
|
||||||
|
The desktop version of privacy.sexy features advanced error handling capabilities.
|
||||||
|
In scenarios where script execution or storage encounters failure, the desktop application initiates automated troubleshooting and self-healing processes.
|
||||||
|
It employs robust and reliable execution strategies, including self-healing mechanisms, and provides guidance and troubleshooting information to resolve issues effectively.
|
||||||
|
This proactive error handling and user guidance enhances the application's security and reliability.
|
||||||
|
|
||||||
|
### Native dialogs
|
||||||
|
|
||||||
|
The desktop version uses native dialogs, offering more features and reliability compared to the browser's file system dialogs.
|
||||||
|
These native dialogs provide a more integrated and user-friendly experience, aligning with the operating system's standard interface and functionalities.
|
||||||
36
docs/desktop/system-requirements.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# System Requirements for the Desktop Version
|
||||||
|
|
||||||
|
The following system requirements are the official ones for the desktop version.
|
||||||
|
While we have tested and confirmed these requirements, the application might also work on other
|
||||||
|
systems or configurations that haven't undergone official testing.
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
- **Version:** Windows 10 and later.
|
||||||
|
- **Processor:** Intel Pentium 4 or later.
|
||||||
|
- **Architecture:** 64-bit (x86-64), ARM (ARM64).
|
||||||
|
|
||||||
|
> **⚠️ Compatibility Note:**
|
||||||
|
> ARM version is only compatible with Windows 11 and later.
|
||||||
|
> It runs non-natively, leading to slower performance due to emulation [1].
|
||||||
|
|
||||||
|
## macOS
|
||||||
|
|
||||||
|
- **Version:** macOS Catalina (10.15) and later.
|
||||||
|
- **Architecture:** Intel-based (x86-64), Apple silicon (ARM64).
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
|
||||||
|
- **Version:** Ubuntu 18.04 and later, Fedora 32 and later, and Debian 10 and later.
|
||||||
|
- **Processor:** Intel Pentium 4 or later.
|
||||||
|
- **Architecture:** 64-bit (x86-64).
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
System requirements reflect Electron's platform capabilities [2] and Chromium's recommended configurations [3].
|
||||||
|
|
||||||
|
For details on the build process, see [electron-builder configuration file](./../../electron-builder.cjs).
|
||||||
|
|
||||||
|
[1]: https://web.archive.org/web/20240428082726/https://learn.microsoft.com/en-us/windows/arm/add-arm-support#emulation-on-arm-based-devices-for-x86-or-x64-windows-apps "Add support Arm devices to your Windows app | Microsoft Learn | learn.microsoft.com"
|
||||||
|
[2]: https://archive.ph/2024.04.28-082958/https://github.com/electron/electron/blob/main/README.md#platform-support "Platform Support | electron/README.md at main · electron/electron · GitHub | github.com"
|
||||||
|
[3]: https://web.archive.org/web/20240428082945/https://support.google.com/chrome/a/answer/7100626?hl=en "Chrome browser system requirements - Chrome Enterprise and Education Help | support.google.com"
|
||||||
@@ -5,22 +5,31 @@ Before your commit, a good practice is to:
|
|||||||
1. [Run unit tests](#testing)
|
1. [Run unit tests](#testing)
|
||||||
2. [Lint your code](#linting)
|
2. [Lint your code](#linting)
|
||||||
|
|
||||||
You could run other types of tests as well, but they may take longer time and overkill for your changes. Automated actions executes the tests for a pull request or change in the main branch. See [ci-cd.md](./ci-cd.md) for more information.
|
You could run other types of tests as well, but they may take longer time and overkill for your changes.
|
||||||
|
Automated actions are set up to execute these tests as necessary.
|
||||||
|
See [ci-cd.md](./ci-cd.md) for more information.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- Install node >15.x.
|
- Install Node.js:
|
||||||
- Install dependencies using `npm install`.
|
- Refer to [action.yml](./../.github/actions/setup-node/action.yml) for the minimum required version compatible with the automated workflows.
|
||||||
|
- 💡 Recommended: Use [`nvm`](https://github.com/nvm-sh/nvm) CLI to install and switch between Node.js versions.
|
||||||
|
- Install dependencies using `npm install` (or [`npm run install-deps`](#utility-scripts) for more options).
|
||||||
|
- For Visual Studio Code users, running the configuration script is recommended to optimize the IDE settings, as detailed in [utility scripts](#utility-scripts).
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- Run unit tests: `npm run test:unit`
|
- Run unit tests: `npm run test:unit`
|
||||||
- Run integration tests: `npm run test:integration`
|
- Run integration tests: `npm run test:integration`
|
||||||
- Run e2e (end-to-end) tests
|
- Run end-to-end (e2e) tests:
|
||||||
- Interactive mode with GUI: `npm run test:e2e`
|
- `npm run test:cy:open`: Run tests interactively using the development server with hot-reloading.
|
||||||
- Headless mode without GUI: `npm run test:e2e -- --headless`
|
- `npm run test:cy:run`: Run tests on the production build in a headless mode.
|
||||||
|
- Run checks:
|
||||||
|
- `npm run check:desktop`: Run runtime checks for packaged desktop applications ([README.md](./../tests/checks/desktop-runtime-errors/check-desktop-runtime-errors/README.md)).
|
||||||
|
- You can set environment variables active its flags such as `BUILD=true SCREENSHOT=true npm run check:desktop`
|
||||||
|
- `npm run check:external-urls`: Test whether external URLs used in applications are alive.
|
||||||
|
|
||||||
📖 Read more about testing in [tests](./tests.md).
|
📖 Read more about testing in [tests](./tests.md).
|
||||||
|
|
||||||
@@ -35,11 +44,26 @@ You could run other types of tests as well, but they may take longer time and ov
|
|||||||
|
|
||||||
### Running
|
### Running
|
||||||
|
|
||||||
- Run in local server: `npm run serve`
|
**Web:**
|
||||||
|
|
||||||
|
- Run in local server: `npm run dev`
|
||||||
- 💡 Meant for local development with features such as hot-reloading.
|
- 💡 Meant for local development with features such as hot-reloading.
|
||||||
- Run using Docker:
|
- Preview production build: `npm run preview`
|
||||||
1. Build: `docker build -t undergroundwires/privacy.sexy:latest .`
|
- Start a local web server that serves the built solution from `./dist`.
|
||||||
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy undergroundwires/privacy.sexy:latest`
|
- 💡 Run `npm run build` before `npm run preview`.
|
||||||
|
|
||||||
|
**Desktop apps:**
|
||||||
|
|
||||||
|
- `npm run electron:dev`: The command will build the main process and preload scripts source code, and start a dev server for the renderer, and start the Electron app.
|
||||||
|
- `npm run electron:preview`: The command will build the main process, preload scripts and renderer source code, and start the Electron app to preview.
|
||||||
|
- `npm run electron:prebuild`: The command will build the main process, preload scripts and renderer source code. Usually before packaging the Electron application, you need to execute this command.
|
||||||
|
- `npm run electron:build`: Prebuilds the Electron application, packages and publishes it through `electron-builder`.
|
||||||
|
|
||||||
|
**Docker:**
|
||||||
|
|
||||||
|
1. Build: `docker build -t undergroundwires/privacy.sexy:latest .`
|
||||||
|
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy undergroundwires/privacy.sexy:latest`
|
||||||
|
3. Application should be available at [`http://localhost:8080`](http://localhost:8080)
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
@@ -47,15 +71,30 @@ You could run other types of tests as well, but they may take longer time and ov
|
|||||||
- Build desktop application: `npm run electron:build`
|
- Build desktop application: `npm run electron:build`
|
||||||
- (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons`
|
- (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons`
|
||||||
|
|
||||||
### Utility Scripts
|
### Scripts
|
||||||
|
|
||||||
- Run fresh NPM install: [`./scripts/fresh-npm-install.sh`](../scripts/fresh-npm-install.sh)
|
📖 For detailed options and behavior for any of the following scripts, please refer to the script file itself.
|
||||||
- This script provides a clean NPM install, removing existing node modules and optionally the package-lock.json (when run with -n), then installs dependencies and runs unit tests.
|
|
||||||
- Configure VSCode: [`./scripts/configure-vscode.sh`](../scripts/configure-vscode.sh)
|
#### Utility scripts
|
||||||
- This script checks and sets the necessary configurations for VSCode in `settings.json` file.
|
|
||||||
|
- [**`npm run install-deps [-- <options>]`**](../scripts/npm-install.js):
|
||||||
|
- Manages NPM dependency installation, it offers capabilities like doing a fresh install, retries on network errors, and other features.
|
||||||
|
- For example, you can run `npm run install-deps -- --fresh` to do clean installation of dependencies.
|
||||||
|
- [**`python ./scripts/configure_vscode.py`**](../scripts/configure_vscode.py):
|
||||||
|
- Optimizes Visual Studio Code settings and installs essential extensions, enhancing the development environment.
|
||||||
|
|
||||||
|
#### Automation scripts
|
||||||
|
|
||||||
|
- [**`node scripts/print-dist-dir.js [<options>]`**](../scripts/print-dist-dir.js):
|
||||||
|
- Determines the absolute path of a distribution directory based on CLI arguments and outputs its absolute path.
|
||||||
|
- [**`npm run check:verify-build-artifacts [-- <options>]`**](../scripts/verify-build-artifacts.js):
|
||||||
|
- Verifies the existence and content of build artifacts. Useful for ensuring that the build process is generating the expected output.
|
||||||
|
- [**`node scripts/verify-web-server-status.js --url [URL]`**](../scripts/verify-web-server-status.js):
|
||||||
|
- Checks if a specified server is up with retries and returns an HTTP 200 status code.
|
||||||
|
|
||||||
## Recommended extensions
|
## Recommended extensions
|
||||||
|
|
||||||
You should use EditorConfig to follow project style.
|
You should use EditorConfig to follow project style.
|
||||||
|
|
||||||
For Visual Studio Code, [`.vscode/extensions.json`](./../.vscode/extensions.json) includes list of recommended extensions.
|
For Visual Studio Code, [`.vscode/extensions.json`](./../.vscode/extensions.json) includes list of recommended extensions.
|
||||||
|
You can use [VSCode configuration script](#utility-scripts) to automatically install those.
|
||||||
|
|||||||
@@ -1,38 +1,55 @@
|
|||||||
# Presentation layer
|
# Presentation layer
|
||||||
|
|
||||||
Presentation layer consists of UI-related code. It uses Vue.js as JavaScript framework and includes Vue.js components. It also includes [Electron](https://www.electronjs.org/) to provide functionality to desktop application.
|
The presentation layer handles UI concerns using Vue as JavaScript framework and Electron to provide desktop functionality.
|
||||||
|
|
||||||
It's designed event-driven from bottom to top. It listens user events (from top) and state events (from bottom) to update state or the GUI.
|
It reflects the [application state](./application.md#application-state) and allows user interactions to modify it. Components manage their own local UI state.
|
||||||
|
|
||||||
|
The presentation layer uses an event-driven architecture for bidirectional reactivity between the application state and UI. State change events flow bottom-up to trigger UI updates, while user events flow top-down through components, some ultimately modifying the application state.
|
||||||
|
|
||||||
📖 Refer to [architecture.md (Layered Application)](./architecture.md#layered-application) to read more about the layered architecture.
|
📖 Refer to [architecture.md (Layered Application)](./architecture.md#layered-application) to read more about the layered architecture.
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
- [`/src/` **`presentation/`**](./../src/presentation/): Contains all presentation related code including Vue and Electron configurations
|
- [`/src/` **`presentation/`**](./../src/presentation/): Contains Vue and Electron code.
|
||||||
- [**`bootstrapping/`**](./../src/presentation/bootstrapping/): Registers Vue global objects including components and plugins.
|
- [**`main.ts`**](./../src/presentation/main.ts): Starts Vue app.
|
||||||
- [**`components/`**](./../src/presentation/components/): Contains all Vue components and their helper classes.
|
- [**`index.html`**](./../src/presentation/index.html): The `index.html` entry file, located at the root of the project as required by Vite
|
||||||
- [**`Shared/`**](./../src/presentation/components/Shared): Contains Vue components and component helpers that other components share.
|
- [**`bootstrapping/`**](./../src/presentation/bootstrapping/): Registers Vue components and plugins.
|
||||||
- [**`assets/`**](./../src/presentation/assets/styles/): Contains assets that webpack will process.
|
- [**`components/`**](./../src/presentation/components/): Contains Vue components, helpers and styles coupled to Vue components.
|
||||||
- [**`fonts/`**](./../src/presentation/assets/fonts/): Contains fonts
|
- [**`Shared/`**](./../src/presentation/components/Shared): Contains shared Vue components and helpers.
|
||||||
- [**`styles/`**](./../src/presentation/assets/styles/): Contains shared styles used throughout different components.
|
- [**`Hooks`**](../src/presentation/components/Shared/Hooks): Hooks used by components through [dependency injection](#dependency-injections).
|
||||||
- [**`components/`**](./../src/presentation/assets/styles/components): Contains reusable styles coupled to a Vue/HTML component.
|
- [**`/public/`**](../src/presentation/public/): Contains static assets.
|
||||||
- [**`vendors-extensions/`**](./../src/presentation/assets/styles/third-party-extensions): Contains styles that override third-party components used.
|
- [**`assets/`**](./../src/presentation/assets/styles/): Contains assets processed by Vite.
|
||||||
- [**`main.scss`**](./../src/presentation/assets/styles/main.scss): Primary Sass file, passes along all other styles, should be the single file used from other components.
|
- [**`fonts/`**](./../src/presentation/assets/fonts/): Contains fonts.
|
||||||
- [**`main.ts`**](./../src/presentation/main.ts): Application entry point that mounts and starts Vue application.
|
- [**`styles/`**](./../src/presentation/assets/styles/): Contains shared styles.
|
||||||
- [**`electron/`**](./../src/presentation/electron/): Electron configuration for the desktop application.
|
- [**`main.scss`**](./../src/presentation/assets/styles/main.scss): Main Sass file, imported by other components as single entrypoint..
|
||||||
- [**`main.ts`**](./../src/presentation/main.ts): Main process of Electron, started as first thing when app starts.
|
- [**`electron/`**](./../src/presentation/electron/): Contains Electron code.
|
||||||
- [**`/public/`**](./../public/): Contains static assets that are directly copied and do not go through webpack.
|
- [`/main/` **`index.ts`**](./../src/presentation/electron/main/index.ts): Main entry for Electron, managing application windows and lifecycle events.
|
||||||
- [**`/vue.config.js`**](./../vue.config.js): Global Vue CLI configurations loaded by `@vue/cli-service`.
|
- [`/preload/` **`index.ts`**](./../src/presentation/electron/preload/index.ts): Script executed before the renderer, securing Node.js features for renderer use.
|
||||||
- [**`/postcss.config.js`**](./../postcss.config.js): PostCSS configurations used by Vue CLI internally.
|
- [**`/shared/`**](./../src/presentation/electron/shared/): Shared logic between different Electron processes.
|
||||||
- [**`/babel.config.js`**](./../babel.config.js): Babel configurations for polyfills used by `@vue/cli-plugin-babel`.
|
- [**`/build/`**](./../src/presentation/electron/build/): `electron-builder` build resources directory, [README.md](./../src/presentation/electron/build/README.md).
|
||||||
|
- [**`/vite.config.ts`**](./../vite.config.ts): Contains Vite configurations for building web application.
|
||||||
|
- [**`/electron.vite.config.ts`**](./../electron.vite.config.ts): Contains Vite configurations for building desktop applications.
|
||||||
|
- [**`/postcss.config.cjs`**](./../postcss.config.cjs): Contains PostCSS configurations for Vite.
|
||||||
|
|
||||||
## Visual design best-practices
|
## Visual design best-practices
|
||||||
|
|
||||||
Add visual clues for clickable items. It should be as clear as possible that they're interactable at first look without hovering. They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility.
|
- **Clickables**:
|
||||||
|
Add visual clues for clickable items.
|
||||||
|
It should be as clear as possible that they're interactable at first look without hovering.
|
||||||
|
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
|
## Application data
|
||||||
|
|
||||||
Components (should) use [ApplicationFactory](./../src/application/ApplicationFactory.ts) singleton to reach the application domain to avoid [parsing and compiling](./application.md#parsing-and-compiling) the application again.
|
Components (should) use [`UseApplication`](./../src/presentation/components/Shared/Hooks/UseApplication.ts) to reach the application domain to avoid [parsing and compiling](./application.md#parsing-and-compiling) the application again.
|
||||||
|
|
||||||
[Application.ts](../src/domain/Application.ts) is an immutable domain model that represents application state. It includes:
|
[Application.ts](../src/domain/Application.ts) is an immutable domain model that represents application state. It includes:
|
||||||
|
|
||||||
@@ -43,34 +60,62 @@ You can read more about how application layer provides application data to he pr
|
|||||||
|
|
||||||
## Application state
|
## Application state
|
||||||
|
|
||||||
Inheritance of a Vue components marks whether it uses application state . Components that does not handle application state extends `Vue`. Stateful components mutate or/and react to state changes (such as user selection or search queries) in [ApplicationContext](./../src/application/Context/ApplicationContext.ts) extend [`StatefulVue`](./../src/presentation/components/Shared/StatefulVue.ts) class to access the context / state.
|
This project uses a singleton instance of the application state, making it available to all Vue components.
|
||||||
|
|
||||||
[`StatefulVue`](./../src/presentation/components/Shared/StatefulVue.ts) functions include:
|
The decision to not use third-party state management libraries like [`vuex`](https://web.archive.org/web/20230801191617/https://vuex.vuejs.org/) or [`pinia`](https://web.archive.org/web/20230801191743/https://pinia.vuejs.org/) was made to promote code independence and enhance portability.
|
||||||
|
|
||||||
- Creating a singleton of the state and makes it available to presentation layer as single source of truth.
|
Stateful components can mutate and/or react to state changes (e.g., user selection, search queries) in the [ApplicationContext](./../src/application/Context/ApplicationContext.ts). Vue components import [`CollectionState.ts`](./../src/presentation/components/Shared/Hooks/UseCollectionState.ts) to access both the application context and the state.
|
||||||
- Providing virtual abstract `handleCollectionState` callback that it calls when
|
|
||||||
- the Vue loads the component,
|
|
||||||
- and also every time when state changes.
|
|
||||||
- Providing `events` member to make lifecycling of state subscriptions events easier because it ensures that components unsubscribe from listening to state events when
|
|
||||||
- the component is no longer used (destroyed),
|
|
||||||
- an if [ApplicationContext](./../src/application/Context/ApplicationContext.ts) changes the active [collection](./collection-files.md) to a different one.
|
|
||||||
|
|
||||||
📖 Refer to [architecture.md | Application State](./architecture.md#application-state) to get an overview of event handling and [application.md | Application State](./presentation.md#application-state) for deeper look into how the application layer manages state.
|
[`UseCollectionState.ts`](./../src/presentation/components/Shared/Hooks/UseCollectionState.ts) provides several functionalities including:
|
||||||
|
|
||||||
## Modals
|
- **Singleton State Instance**: It creates a singleton instance of the state, which is shared across the presentation layer. The singleton instance ensures that there's a single source of truth for the application's state.
|
||||||
|
- **State Change Callback and Lifecycle Management**: It offers a mechanism to register callbacks, which will be invoked when the state initializes or mutates. It ensures that components unsubscribe from state events when they are no longer in use or when [ApplicationContext](./../src/application/Context/ApplicationContext.ts) switches the active [collection](./collection-files.md).
|
||||||
|
- **State Access and Modification**: It provides functions to read and mutate for accessing and modifying the state, encapsulating the details of these operations.
|
||||||
|
- **Event Subscription Lifecycle Management**: Includes an `events` member that simplifies state subscription lifecycle events. This ensures that components unsubscribe from state events when they are no longer in use, or when [ApplicationContext](./../src/application/Context/ApplicationContext.ts) switches the active [collection](./collection-files.md).
|
||||||
|
|
||||||
[Dialog.vue](./../src/presentation/components/Shared/Dialog.vue) is a shared component that other components used to show modal windows.
|
📖 Refer to [architecture.md | Application State](./architecture.md#application-state) for an overview of event handling and [application.md | Application State](./presentation.md#application-state) for an in-depth understanding of state management in the application layer.
|
||||||
|
|
||||||
You can use it by wrapping the content inside of its `slot` and call `.show()` function on its reference. For example:
|
## Dependency injections
|
||||||
|
|
||||||
```html
|
The presentation layer uses Vue's native dependency injection system to increase testability and decouple components.
|
||||||
<Dialog ref="testDialog">
|
|
||||||
<div>Hello world</div>
|
|
||||||
</Dialog>
|
|
||||||
<div @click="$refs.testDialog.show()">Show dialog</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sass naming convention
|
To add a new dependency:
|
||||||
|
|
||||||
|
1. **Define its symbol**: Define an associated symbol for every dependency in [`injectionSymbols.ts`](./../src/presentation/injectionSymbols.ts). Symbols are grouped into:
|
||||||
|
- **Singletons**: Shared across components, instantiated once.
|
||||||
|
- **Transients**: Factories yielding a new instance on every access.
|
||||||
|
2. **Provide the dependency**:
|
||||||
|
Modify the [`provideDependencies`](./../src/presentation/bootstrapping/DependencyProvider.ts) function to include the new dependency.
|
||||||
|
[`App.vue`](./../src/presentation/components/App.vue) calls this function within its `setup()` hook to register the dependencies.
|
||||||
|
3. **Inject the dependency**: Use `injectKey` to inject a dependency. Pass a selector function to `injectKey` that retrieves the appropriate symbol from the provided dependencies.
|
||||||
|
- Example usage: `injectKey((keys) => keys.useCollectionState)`;
|
||||||
|
|
||||||
|
## Shared UI components
|
||||||
|
|
||||||
|
Shared UI components ensure consistency and streamline front-end development.
|
||||||
|
|
||||||
|
We use homegrown components over third-party solutions or comprehensive UI frameworks like Quasar to maintain portability and easy maintenance.
|
||||||
|
|
||||||
|
Shared components include:
|
||||||
|
|
||||||
|
- [ModalDialog.vue](./../src/presentation/components/Shared/Modal/ModalDialog.vue): Renders modal windows.
|
||||||
|
- [TooltipWrapper.vue](./../src/presentation/components/Shared/TooltipWrapper.vue): Provides tooltip functionality for improved information accessibility.
|
||||||
|
- [FlatButton.vue](./../src/presentation/components/Shared/FlatButton.vue): Creates flat-style buttons for a unified and consistent user interface.
|
||||||
|
|
||||||
|
## Desktop builds
|
||||||
|
|
||||||
|
Desktop builds uses `electron-vite` to bundle the code, and `electron-builder` to build and publish the packages.
|
||||||
|
|
||||||
|
Host system access is strictly controlled. The [`preloader`](./../src/presentation/electron/preload/) isolates logic that interacts with the host system. These functionalities are then securely exposed to the renderer process (Vue application) using context-bridging. [`ApiContextBridge.ts`](./../src/presentation/electron/preload/ContextBridging/ApiContextBridge.ts) handles the configuration of the exposed APIs, ensuring a secure bridge between the Electron and Vue layers.
|
||||||
|
|
||||||
|
## Styles
|
||||||
|
|
||||||
|
### Style location
|
||||||
|
|
||||||
|
- **Global styles**: The [`assets/styles/`](#structure) directory is reserved for styles that have a broader scope, affecting multiple components or entire layouts. They are generic and should not be tightly coupled to a specific component's functionality.
|
||||||
|
- **Component-specific styles**: Styles closely tied to a particular component's functionality or appearance should reside near the component they are used by. This makes it easier to locate and modify styles when working on a specific component.
|
||||||
|
|
||||||
|
### Sass naming convention
|
||||||
|
|
||||||
- Use lowercase for variables/functions/mixins, e.g.:
|
- Use lowercase for variables/functions/mixins, e.g.:
|
||||||
- Variable: `$variable: value;`
|
- Variable: `$variable: value;`
|
||||||
|
|||||||
24
docs/research/README.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Research Documentation
|
||||||
|
|
||||||
|
Welcome to the research section of privacy.sexy.
|
||||||
|
This area houses in-depth technical research and analyses, serving as a resource for developers, contributors, and technology enthusiasts.
|
||||||
|
|
||||||
|
**Structure:**
|
||||||
|
|
||||||
|
This folder organizes research into topic-specific subdirectories like `windows`, `linux`, etc.
|
||||||
|
Each contains materials relevant to its subject.
|
||||||
|
|
||||||
|
**Contents:**
|
||||||
|
|
||||||
|
These documents offer comprehensive insights into the respective topics, supporting development and contributions.
|
||||||
|
|
||||||
|
**Contributing:**
|
||||||
|
|
||||||
|
Contributions to our research documentation are welcome.
|
||||||
|
If your research aligns with privacy.sexy goals, please consider adding it here.
|
||||||
|
See [`CONTRIBUTING.md`](./../../CONTRIBUTING.md) on more information about how to contribute.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
This information is available for educational and research purposes.
|
||||||
|
We support knowledge sharing and aim to enhance understanding of privacy and security technologies.
|
||||||
84
docs/research/windows/01-windows-10-1909-apps.txt
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
InputApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Messaging 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Microsoft3DViewer 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdge 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MixedReality.Portal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MSPaint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Office.OneNote 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.OneConnect 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.PPIProjection cw5n1h2txyewy System True
|
||||||
|
Microsoft.Print3D 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SkypeApp kzf8qxf38zg5c Provisioned False
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Wallet 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Cortana cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecHealthUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
85
docs/research/windows/02-windows-10-20H2-apps.txt
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
Microsoft.549981C3F5F10 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Microsoft3DViewer 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdge 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftEdge.Stable 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MixedReality.Portal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MSPaint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Office.OneNote 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SkypeApp kzf8qxf38zg5c Provisioned False
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VCLibs.140.00 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Wallet 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Search cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecHealthUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftWindows.Client.CBS cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.UndockedDevKit cw5n1h2txyewy System True
|
||||||
|
NcsiUwpApp 8wekyb3d8bbwe System True
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
85
docs/research/windows/03-windows-10-21H2-apps.txt
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
Microsoft.549981C3F5F10 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Microsoft3DViewer 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdge 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftEdge.Stable 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MixedReality.Portal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MSPaint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Office.OneNote 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SkypeApp kzf8qxf38zg5c Provisioned False
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VCLibs.140.00 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Wallet 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Search cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecHealthUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftWindows.Client.CBS cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.UndockedDevKit cw5n1h2txyewy System True
|
||||||
|
NcsiUwpApp 8wekyb3d8bbwe System True
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
85
docs/research/windows/04-windows-10-22H2-apps.txt
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
Microsoft.549981C3F5F10 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Microsoft3DViewer 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdge 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftEdge.Stable 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MixedReality.Portal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MSPaint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Office.OneNote 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SkypeApp kzf8qxf38zg5c Provisioned False
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VCLibs.140.00 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Wallet 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Search cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecHealthUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftWindows.Client.CBS cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.UndockedDevKit cw5n1h2txyewy System True
|
||||||
|
NcsiUwpApp 8wekyb3d8bbwe System True
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
88
docs/research/windows/05-windows-11-21H2-apps.txt
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
Microsoft.549981C3F5F10 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingNews 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned True
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GamingApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.MicrosoftEdge 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftEdge.Stable 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.OneDriveSync 8wekyb3d8bbwe Installed False
|
||||||
|
Microsoft.Paint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.PowerAutomateDesktop 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SecHealthUI 8wekyb3d8bbwe Provisioned True
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Todos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.UI.Xaml.2.4 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VCLibs.140.00 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Search cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsNotepad 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsTerminal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftWindows.Client.CBS cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.Client.WebExperience cw5n1h2txyewy Provisioned False
|
||||||
|
MicrosoftWindows.UndockedDevKit cw5n1h2txyewy System True
|
||||||
|
NcsiUwpApp 8wekyb3d8bbwe System True
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
91
docs/research/windows/06-windows-11-22H2-apps.txt
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
Clipchamp.Clipchamp yxz26nhyzhsrt Provisioned False
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
Microsoft.549981C3F5F10 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingNews 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned True
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GamingApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEVCVideoExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.MicrosoftEdge 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftEdge.Stable 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Paint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.PowerAutomateDesktop 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.RawImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SecHealthUI 8wekyb3d8bbwe Provisioned True
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Todos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VCLibs.140.00 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PrintQueueActionCenter cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsNotepad 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsTerminal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftCorporationII.QuickAssist 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftWindows.Client.CBS cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.Client.Core cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.Client.WebExperience cw5n1h2txyewy Provisioned False
|
||||||
|
MicrosoftWindows.UndockedDevKit cw5n1h2txyewy System True
|
||||||
|
NcsiUwpApp 8wekyb3d8bbwe System True
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
91
docs/research/windows/07-windows-11-23H2-apps.txt
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
Name PublisherId Category NonRemovable
|
||||||
|
---- ----------- -------- ------------
|
||||||
|
1527c705-839a-4832-9118-54d4Bd6a0c89 cw5n1h2txyewy System True
|
||||||
|
c5e2524a-ea46-4f67-841f-6a9465d9d515 cw5n1h2txyewy System True
|
||||||
|
Clipchamp.Clipchamp yxz26nhyzhsrt Provisioned False
|
||||||
|
E2A4F912-2574-4A75-9BB0-0D023378592B cw5n1h2txyewy System True
|
||||||
|
F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE cw5n1h2txyewy System True
|
||||||
|
Microsoft.549981C3F5F10 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.AAD.BrokerPlugin cw5n1h2txyewy System True
|
||||||
|
Microsoft.AccountsControl cw5n1h2txyewy System True
|
||||||
|
Microsoft.AsyncTextService 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.BingNews 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BingWeather 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.BioEnrollment cw5n1h2txyewy System True
|
||||||
|
Microsoft.CredDialogHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.DesktopAppInstaller 8wekyb3d8bbwe Provisioned True
|
||||||
|
Microsoft.ECApp 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.GamingApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.GetHelp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Getstarted 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEIFImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.HEVCVideoExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.LockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.MicrosoftEdge.Stable 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftEdgeDevToolsClient 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.MicrosoftOfficeHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftSolitaireCollection 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.MicrosoftStickyNotes 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Paint 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.People 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.PowerAutomateDesktop 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.RawImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ScreenSketch 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.SecHealthUI 8wekyb3d8bbwe Provisioned True
|
||||||
|
Microsoft.StorePurchaseApp 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Todos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VCLibs.140.00 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.VP9VideoExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebMediaExtensions 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WebpImageExtension 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Win32WebViewHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Apprep.ChxApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.AssignedAccessLockApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CallingShellApp cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CapturePicker cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.CloudExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ContentDeliveryManager cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.NarratorQuickStart 8wekyb3d8bbwe System True
|
||||||
|
Microsoft.Windows.OOBENetworkCaptivePortal cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.OOBENetworkConnectionFlow cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ParentalControls cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PeopleExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.Photos 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Windows.PinningConfirmationDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.PrintQueueActionCenter cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.SecureAssessmentBrowser cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.ShellExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.StartMenuExperienceHost cw5n1h2txyewy System True
|
||||||
|
Microsoft.Windows.XGpuEjectDialog cw5n1h2txyewy System True
|
||||||
|
Microsoft.WindowsAlarms 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCalculator 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsCamera 8wekyb3d8bbwe Provisioned False
|
||||||
|
microsoft.windowscommunicationsapps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsFeedbackHub 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsMaps 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsNotepad 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsSoundRecorder 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsStore 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.WindowsTerminal 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.Xbox.TCUI 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGameCallableUI cw5n1h2txyewy System True
|
||||||
|
Microsoft.XboxGameOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxGamingOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxIdentityProvider 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.XboxSpeechToTextOverlay 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.YourPhone 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneMusic 8wekyb3d8bbwe Provisioned False
|
||||||
|
Microsoft.ZuneVideo 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftCorporationII.QuickAssist 8wekyb3d8bbwe Provisioned False
|
||||||
|
MicrosoftWindows.Client.CBS cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.Client.Core cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.Client.FileExp cw5n1h2txyewy System True
|
||||||
|
MicrosoftWindows.Client.WebExperience cw5n1h2txyewy Provisioned False
|
||||||
|
MicrosoftWindows.UndockedDevKit cw5n1h2txyewy System True
|
||||||
|
NcsiUwpApp 8wekyb3d8bbwe System True
|
||||||
|
Windows.CBSPreview cw5n1h2txyewy System True
|
||||||
|
windows.immersivecontrolpanel cw5n1h2txyewy System True
|
||||||
|
Windows.PrintDialog cw5n1h2txyewy System True
|
||||||
|
|
||||||
|
|
||||||
46
docs/research/windows/README.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Research on Windows
|
||||||
|
|
||||||
|
In this section, we maintain a structured approach to our research on Windows.
|
||||||
|
The use of `01` prefixed file names aids in organizing and retrieving search results effectively.
|
||||||
|
|
||||||
|
## Apps
|
||||||
|
|
||||||
|
The PowerShell script below serves as a method for gathering detailed information about Windows packages.
|
||||||
|
|
||||||
|
```ps1
|
||||||
|
$allPackages = @()
|
||||||
|
$provisionedPackages = Get-AppxProvisionedPackage -Online
|
||||||
|
foreach ($installedPackage in Get-AppxPackage -AllUsers) {
|
||||||
|
if ($installedPackage.IsFramework -eq $true) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$allPackages += [PSCustomObject]@{
|
||||||
|
Name = $installedPackage.Name
|
||||||
|
PublisherId = $installedPackage.PublisherId
|
||||||
|
Category = if ($installedPackage.SignatureKind -eq "System") {
|
||||||
|
'System'
|
||||||
|
} elseif ($provisionedPackages | Where-Object { $_.DisplayName -eq $installedPackage.Name }) {
|
||||||
|
'Provisioned'
|
||||||
|
} else {
|
||||||
|
'Installed'
|
||||||
|
}
|
||||||
|
NonRemovable = $installedPackage.NonRemovable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($provisionedPackage in $provisionedPackages) {
|
||||||
|
if ($allPackages | Where-Object { $_.Name -eq $provisionedPackage.DisplayName }) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$allPackages += [PSCustomObject]@{
|
||||||
|
Name = $provisionedPackage.DisplayName
|
||||||
|
PublisherId = $provisionedPackage.PackageName -split '_' | Select-Object -Last 1
|
||||||
|
Category = 'Provisioned'
|
||||||
|
NonRemovable = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$allPackages `
|
||||||
|
| Sort-Object Name `
|
||||||
|
| Select-Object Name, PublisherId, Category, NonRemovable `
|
||||||
|
| Format-Table `
|
||||||
|
| Out-File -FilePath "$([System.Environment]::GetFolderPath('Desktop'))\apps.txt"
|
||||||
|
```
|
||||||
58
docs/script-guidelines.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# privacy.sexy Script Guidelines
|
||||||
|
|
||||||
|
Create a script for privacy.sexy by submitting a PR or creating an issue (details in [Extend Scripts](./../CONTRIBUTING.md#extend-scripts)).
|
||||||
|
As scripts are central to privacy.sexy and reach a global audience, their design is critical.
|
||||||
|
|
||||||
|
Key attributes of a good script:
|
||||||
|
|
||||||
|
- ✅ Well-referenced [documentation](#documentation).
|
||||||
|
- ✅ Utilizes [shared functions](#shared-functions).
|
||||||
|
- ✅ Has a [simple name](#name).
|
||||||
|
|
||||||
|
## Name
|
||||||
|
|
||||||
|
- Choose a title that is easy to understand for all users, regardless of technical skill, yet remains technically accurate.
|
||||||
|
- Focus on privacy implications, avoiding complex or overly technical jargon.
|
||||||
|
- Maintain consistency in naming, avoiding linguistic variations.
|
||||||
|
- Use action-oriented language for clarity and directness. Use an instruction format like "do this, do that" for clear, direct guidance.
|
||||||
|
- Respect the official casing of brand names.
|
||||||
|
- Choose clear and uncomplicated language.
|
||||||
|
- It should start with an imperative noun.
|
||||||
|
- Start with action verbs like `Clear`, `Disable`, `Remove`, `Configure`, `Minimize`, `Maximize`. While exceptions exist, these prefixes help maintain naming consistency.
|
||||||
|
- The scripts that modify hosts file should start with `Block ..`.
|
||||||
|
- Favor the terms:
|
||||||
|
- `Disable` over `Turn off`, `Stop`, `Prevent`
|
||||||
|
- `Configure` over `Set up`
|
||||||
|
- `Clear` over `Erase`, `Clean`
|
||||||
|
- `Minimize` over `Limit`, `Reduce`
|
||||||
|
- `Maximize` over `Extend`, `Delay`, `Postpone`, `Prolong`
|
||||||
|
- `Remove` over `Uninstall`
|
||||||
|
- `Improve` over `Increase`
|
||||||
|
- Structure your phrases for clarity, examples:
|
||||||
|
- Prefer `Disable XX telemetry` over `Disable telemetry in XX`
|
||||||
|
- Prefer `Clear XX data` over `Clear data from XX`, or `Clear data of XX`.
|
||||||
|
- Use sentence case rather than Title Case.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- Use credible and reputable sources for references.
|
||||||
|
- 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
|
||||||
|
|
||||||
|
Use existing shared functions when possible, like `DisableService` for disabling services,.
|
||||||
|
|
||||||
|
- 📖 Learn about templates in [templating.md](./templating.md).
|
||||||
|
- 📖 For syntax, see [collection-files.md](collection-files.md).
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
- Prefer [shared functions](#shared-functions); avoid custom code unless necessary.
|
||||||
|
- Keep code simple and compatible with older systems.
|
||||||
|
- Focus on reliability, ensuring the script is error-resistant, works on different locales and handles unexpected situations.
|
||||||
|
- Language selection:
|
||||||
|
- Windows: Use batch when simpler, otherwise PowerShell.
|
||||||
|
- macOS/Linux: Use bash when simpler, otherwise Python.
|
||||||
|
- Provide revert code to restore original/default settings when applicable.
|
||||||
@@ -2,79 +2,142 @@
|
|||||||
|
|
||||||
## Benefits of templating
|
## Benefits of templating
|
||||||
|
|
||||||
- Generating scripts by sharing code to increase best-practice usage and maintainability.
|
- **Code sharing:** Share code across scripts for consistent practices and easier maintenance.
|
||||||
- Creating self-contained scripts without cross-dependencies.
|
- **Script independence:** Generate self-contained scripts, eliminating the need for external code.
|
||||||
- Use of pipes for writing cleaner code and letting pipes do dirty work.
|
- **Cleaner code:** Use pipes for complex operations, resulting in more readable and streamlined code.
|
||||||
|
|
||||||
## Expressions
|
## Expressions
|
||||||
|
|
||||||
- Expressions start and end with mustaches (double brackets, `{{` and `}}`).
|
**Syntax:**
|
||||||
- E.g. `Hello {{ $name }} !`
|
|
||||||
- Syntax is close to [Go Templates ❤️](https://pkg.go.dev/text/template) but not the same.
|
|
||||||
- Functions enables usage of expressions.
|
|
||||||
- In script definition parts of a function, see [`Function`](./collection-files.md#Function).
|
|
||||||
- When doing a call as argument values, see [`FunctionCall`](./collection-files.md#Function).
|
|
||||||
- Expressions inside expressions (nested templates) are supported.
|
|
||||||
- An expression can output another expression that will also be compiled.
|
|
||||||
- E.g. following would compile first [with expression](#with), and then [parameter substitution](#parameter-substitution) in its output.
|
|
||||||
|
|
||||||
```go
|
Expressions are enclosed within `{{` and `}}`.
|
||||||
{{ with $condition }}
|
Example: `Hello {{ $name }}!`.
|
||||||
echo {{ $text }}
|
They are a core component of templating, enhancing scripts with dynamic capabilities and functionality.
|
||||||
{{ end }}
|
|
||||||
```
|
**Syntax similarity:**
|
||||||
|
|
||||||
|
The syntax shares similarities with [Go Templates ❤️](https://pkg.go.dev/text/template), but with some differences:
|
||||||
|
|
||||||
|
**Function definitions:**
|
||||||
|
|
||||||
|
You can use expressions in function definition.
|
||||||
|
Refer to [Function](./collection-files.md#function) for more details.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: GreetFunction
|
||||||
|
parameters:
|
||||||
|
- name: name
|
||||||
|
code: Hello {{ $name }}!
|
||||||
|
```
|
||||||
|
|
||||||
|
If you assign `name` the value `world`, invoking `GreetFunction` would result in `Hello world!`.
|
||||||
|
|
||||||
|
**Function arguments:**
|
||||||
|
|
||||||
|
You can also use expressions in arguments in nested function calls.
|
||||||
|
Refer to [`Function | collection-files.md`](./collection-files.md#functioncall) for more details.
|
||||||
|
|
||||||
|
Example with nested function calls:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
-
|
||||||
|
name: PrintMessageFunction
|
||||||
|
parameters:
|
||||||
|
- name: message
|
||||||
|
code: echo "{{ $message }}"
|
||||||
|
-
|
||||||
|
name: GreetUserFunction
|
||||||
|
parameters:
|
||||||
|
- name: userName
|
||||||
|
call:
|
||||||
|
name: PrintMessageFunction
|
||||||
|
parameters:
|
||||||
|
argument: 'Hello, {{ $userName }}!'
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, if `userName` is `Alice`, invoking `GreetUserFunction` would execute `echo "Hello, Alice!"`.
|
||||||
|
|
||||||
|
**Nested templates:**
|
||||||
|
|
||||||
|
You can nest expressions inside expressions (also called "nested templates").
|
||||||
|
This means that an expression can output another expression where compiler will compile both.
|
||||||
|
|
||||||
|
For example, following would compile first [with expression](#with), and then [parameter substitution](#parameter-substitution) in its output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
{{ with $condition }}
|
||||||
|
echo {{ $text }}
|
||||||
|
{{ end }}
|
||||||
|
```
|
||||||
|
|
||||||
### Parameter substitution
|
### Parameter substitution
|
||||||
|
|
||||||
A simple function example:
|
Parameter substitution dynamically replaces variable references with their corresponding values in the script.
|
||||||
|
|
||||||
|
**Example function:**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
function: EchoArgument
|
name: DisplayTextFunction
|
||||||
parameters:
|
parameters:
|
||||||
- name: 'argument'
|
- name: 'text'
|
||||||
code: Hello {{ $argument }} !
|
code: echo {{ $text }}
|
||||||
```
|
```
|
||||||
|
|
||||||
It would print "Hello world" if it's called in a [script](./collection-files.md#script) as following:
|
Invoking `DisplayTextFunction` with `text` set to `"Hello, world!"` would result in `echo "Hello, World!"`.
|
||||||
|
|
||||||
```yaml
|
|
||||||
script: Echo script
|
|
||||||
call:
|
|
||||||
function: EchoArgument
|
|
||||||
parameters:
|
|
||||||
argument: World
|
|
||||||
```
|
|
||||||
|
|
||||||
A function can call other functions such as:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
-
|
|
||||||
function: CallerFunction
|
|
||||||
parameters:
|
|
||||||
- name: 'value'
|
|
||||||
call:
|
|
||||||
function: EchoArgument
|
|
||||||
parameters:
|
|
||||||
argument: {{ $value }}
|
|
||||||
-
|
|
||||||
function: EchoArgument
|
|
||||||
parameters:
|
|
||||||
- name: 'argument'
|
|
||||||
code: Hello {{ $argument }} !
|
|
||||||
```
|
|
||||||
|
|
||||||
### with
|
### with
|
||||||
|
|
||||||
Skips its "block" if the variable is absent or empty. Its "block" is between `with` start (`{{ with .. }}`) and end (`{{ end }`}) expressions.
|
The `with` expression enables conditional rendering and provides a context variable for simpler code.
|
||||||
E.g. `{{ with $parameterName }} Hi, I'm a block! {{ end }}` would only output `Hi, I'm a block!` if `parameterName` has any value..
|
|
||||||
|
|
||||||
It binds its context (value of the provided parameter value) as arbitrary `.` value. It allows you to use the argument value of the given parameter when it is provided and not empty such as:
|
**Optional block rendering:**
|
||||||
|
|
||||||
|
If the provided variable is falsy (`false`, `null`, or empty), the compiler skips the enclosed block of code.
|
||||||
|
A "block" lies between the with start (`{{ with .. }}`) and end (`{{ end }}`) expressions, defining its boundaries.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
{{ with $optionalVariable }}
|
||||||
|
Hello
|
||||||
|
{{ end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
This would display `Hello` if `$optionalVariable` is truthy.
|
||||||
|
|
||||||
|
**Parameter declaration:**
|
||||||
|
|
||||||
|
You should set `optional: true` for the argument if you use it like `{{ with $argument }} .. {{ end }}`.
|
||||||
|
|
||||||
|
Declare parameters used for `with` condition as optional such as:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ConditionalOutputFunction
|
||||||
|
parameters:
|
||||||
|
- name: 'data'
|
||||||
|
optional: true
|
||||||
|
code: |-
|
||||||
|
{{ with $data }}
|
||||||
|
Data is: {{ . }}
|
||||||
|
{{ end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Context variable:**
|
||||||
|
|
||||||
|
`with` statement binds its context (value of the provided parameter value) as arbitrary `.` value.
|
||||||
|
`{{ . }}` syntax gives you access to the context variable.
|
||||||
|
This is optional to use, and not required to use `with` expressions.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
{{ with $parameterName }}Parameter value is {{ . }} here {{ end }}
|
{{ with $parameterName }}Parameter value is {{ . }} here {{ end }}
|
||||||
```
|
```
|
||||||
|
|
||||||
It supports multiline text inside the block. You can have something like:
|
**Multiline text:**
|
||||||
|
|
||||||
|
It supports multiline text inside the block. You can write something like:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
{{ with $argument }}
|
{{ with $argument }}
|
||||||
@@ -83,7 +146,9 @@ It supports multiline text inside the block. You can have something like:
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use other expressions inside its block, such as [parameter substitution](#parameter-substitution):
|
**Inner expressions:**
|
||||||
|
|
||||||
|
You can also embed other expressions inside its block, such as [parameter substitution](#parameter-substitution):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
{{ with $condition }}
|
{{ with $condition }}
|
||||||
@@ -91,32 +156,44 @@ You can also use other expressions inside its block, such as [parameter substitu
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
```
|
```
|
||||||
|
|
||||||
💡 Declare parameters used for `with` condition as optional. Set `optional: true` for the argument if you use it like `{{ with $argument }} .. {{ end }}`.
|
This also includes nesting `with` statements:
|
||||||
|
|
||||||
Example:
|
```go
|
||||||
|
{{ with $condition1 }}
|
||||||
```yaml
|
Value of $condition1: {{ . }}
|
||||||
function: FunctionThatOutputsConditionally
|
{{ with $condition2 }}
|
||||||
parameters:
|
Value of $condition2: {{ . }}
|
||||||
- name: 'argument'
|
|
||||||
optional: true
|
|
||||||
code: |-
|
|
||||||
{{ with $argument }}
|
|
||||||
Value is: {{ . }}
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pipes
|
### Pipes
|
||||||
|
|
||||||
- Pipes are functions available for handling text.
|
Pipes are functions designed for text manipulation.
|
||||||
- Allows stacking actions one after another also known as "chaining".
|
They allow for a sequential application of operations resembling [Unix pipelines](https://en.wikipedia.org/wiki/Pipeline_(Unix)), also known as "chaining".
|
||||||
- Like [Unix pipelines](https://en.wikipedia.org/wiki/Pipeline_(Unix)), the concept is simple: each pipeline's output becomes the input of the following pipe.
|
Each pipeline's output becomes the input of the following pipe.
|
||||||
- You cannot create pipes. [A dedicated compiler](./application.md#parsing-and-compiling) provides pre-defined pipes to consume in collection files.
|
|
||||||
- You can combine pipes with other expressions such as [parameter substitution](#parameter-substitution) and [with](#with) syntax.
|
**Pre-defined**:
|
||||||
- ❗ Pipe names must be camelCase without any space or special characters.
|
|
||||||
- **Existing pipes**
|
Pipes are pre-defined by the system.
|
||||||
- `inlinePowerShell`: Converts a multi-lined PowerShell script to a single line.
|
You cannot create pipes in [collection files](./collection-files.md).
|
||||||
- `escapeDoubleQuotes`: Escapes `"` characters, allows you to use them inside double quotes (`"`).
|
[A dedicated compiler](./application.md#parsing-and-compiling) provides pre-defined pipes to consume in collection files.
|
||||||
- **Example usages**
|
|
||||||
- `{{ with $code }} echo "{{ . | inlinePowerShell }}" {{ end }}`
|
**Compatibility:**
|
||||||
- `{{ with $code }} echo "{{ . | inlinePowerShell | escapeDoubleQuotes }}" {{ end }}`
|
|
||||||
|
You can combine pipes with other expressions such as [parameter substitution](#parameter-substitution) and [with](#with) syntax.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
{{ with $script }} echo "{{ . | inlinePowerShell | escapeDoubleQuotes }}" {{ end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Naming:**
|
||||||
|
|
||||||
|
❗ Pipe names must be camelCase without any space or special characters.
|
||||||
|
|
||||||
|
**Available pipes:**
|
||||||
|
|
||||||
|
- `inlinePowerShell`: Converts a multi-lined PowerShell script to a single line.
|
||||||
|
- `escapeDoubleQuotes`: Escapes `"` characters for batch command execution, allows you to use them inside double quotes (`"`).
|
||||||
|
|||||||
131
docs/tests.md
@@ -5,77 +5,88 @@ There are different types of tests executed:
|
|||||||
1. [Unit tests](#unit-tests)
|
1. [Unit tests](#unit-tests)
|
||||||
2. [Integration tests](#integration-tests)
|
2. [Integration tests](#integration-tests)
|
||||||
3. [End-to-end (E2E) tests](#e2e-tests)
|
3. [End-to-end (E2E) tests](#e2e-tests)
|
||||||
|
4. [Automated checks](#automated-checks)
|
||||||
|
|
||||||
Common aspects for all tests:
|
## Unit and integration tests
|
||||||
|
|
||||||
- They use [Mocha](https://mochajs.org/) and [Chai](https://www.chaijs.com/).
|
- They utilize [Vitest](https://vitest.dev/).
|
||||||
- Their files end with `.spec.{ts|js}` suffix.
|
- Test files are suffixed with `.spec.ts`.
|
||||||
|
|
||||||
💡 You can use path/module alias `@/tests` in import statements.
|
|
||||||
|
|
||||||
## Unit tests
|
|
||||||
|
|
||||||
- Unit tests test each component in isolation.
|
|
||||||
- All unit tests goes under [`./tests/unit`](./../tests/unit).
|
|
||||||
- They rely on [stubs](./../tests/unit/shared/Stubs) for isolation.
|
|
||||||
|
|
||||||
### Unit tests structure
|
|
||||||
|
|
||||||
- [`./src/`](./../src/)
|
|
||||||
- Includes source code that unit tests will test.
|
|
||||||
- [`./tests/unit/`](./../tests/unit/)
|
|
||||||
- Includes test code.
|
|
||||||
- Tests follow same folder structure as [`./src/`](./../src).
|
|
||||||
- E.g. if system under test lies in [`./src/application/ApplicationFactory.ts`](./../src/application/ApplicationFactory.ts) then its tests would be in test would be at [`./tests/unit/application/ApplicationFactory.spec.ts`](./../tests/unit/application/ApplicationFactory.spec.ts).
|
|
||||||
- [`shared/`](./../tests/unit/shared/)
|
|
||||||
- Includes common functionality that's shared across unit tests.
|
|
||||||
- [`Assertions/`](./../tests/unit/shared/Assertions):
|
|
||||||
- Common assertions that extend [Chai Assertion Library](https://www.chaijs.com/).
|
|
||||||
- Asserting functions should start with `expect` prefix.
|
|
||||||
- [`TestCases/`](./../tests/unit/shared/TestCases/)
|
|
||||||
- Shared test cases.
|
|
||||||
- Functions that calls `it()` from [Mocha test framework](https://mochajs.org/) should have `it` prefix.
|
|
||||||
- E.g. `itEachAbsentCollectionValue()`.
|
|
||||||
- [`Stubs/`](./../tests/unit/shared/Stubs)
|
|
||||||
- Includes stubs to be able to test components in isolation.
|
|
||||||
- Stubs have minimal and dummy behavior to be functional, they may also have spying or mocking functions.
|
|
||||||
|
|
||||||
### Unit tests naming
|
|
||||||
|
|
||||||
- Each test suite first describe the system under test.
|
|
||||||
- E.g. tests for class `Application.ts` are all inside `Application.spec.ts`.
|
|
||||||
- `describe` blocks tests for same function (if applicable).
|
|
||||||
- E.g. test for `run()` are inside `describe('run', () => ..)`.
|
|
||||||
|
|
||||||
### Act, arrange, assert
|
### Act, arrange, assert
|
||||||
|
|
||||||
- Tests use act, arrange and assert (AAA) pattern when applicable.
|
- Tests implement the act, arrange, and assert (AAA) pattern.
|
||||||
- **Arrange**
|
- **Arrange**
|
||||||
- Sets up the test case.
|
- Sets up the test scenario and environment.
|
||||||
- Starts with comment line `// arrange`.
|
- Begins with comment line `// arrange`.
|
||||||
- **Act**
|
- **Act**
|
||||||
- Executes the actual test.
|
- Executes the actual test.
|
||||||
- Starts with comment line `// act`.
|
- Begins with comment line `// act`.
|
||||||
- **Assert**
|
- **Assert**
|
||||||
- Elicit some sort of expectation.
|
- Sets an expectation for the test's outcome.
|
||||||
- Starts with comment line `// assert`.
|
- Begins with comment line `// assert`.
|
||||||
|
|
||||||
## Integration tests
|
### Unit tests
|
||||||
|
|
||||||
- Tests functionality of a component in combination with others (not isolated).
|
- Evaluate individual components in isolation.
|
||||||
- Ensure dependencies to third parties work as expected.
|
- Located in [`./tests/unit`](./../tests/unit).
|
||||||
- Defined in [./tests/integration](./../tests/integration).
|
- Achieve isolation using stubs where you place:
|
||||||
|
- Common stubs in [`./shared/Stubs`](./../tests/unit/shared/Stubs),
|
||||||
|
- Component-specific stubs in same folder as test file.
|
||||||
|
- Include Vue component tests, enabled by `@vue/test-utils`.
|
||||||
|
|
||||||
|
#### Unit tests naming
|
||||||
|
|
||||||
|
- Test suites start with a description of the component or system under test.
|
||||||
|
- E.g., tests for `Application.ts` are contained in `Application.spec.ts`.
|
||||||
|
- Whenever possible, `describe` blocks group tests of the same function.
|
||||||
|
- E.g., tests for `run()` are inside `describe('run', () => ...)`.
|
||||||
|
|
||||||
|
### Integration tests
|
||||||
|
|
||||||
|
- Assess the combined functionality of components.
|
||||||
|
- They verify that third-party dependencies function as anticipated.
|
||||||
|
|
||||||
## E2E tests
|
## E2E tests
|
||||||
|
|
||||||
- Test the functionality and performance of a running application.
|
- Examine the live web application's functionality and performance.
|
||||||
- Vue CLI plugin [`e2e-cypress`](https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-e2e-cypress#readme) configures E2E tests.
|
- Uses Cypress to run the tests.
|
||||||
- Test names and folders have logical structure based on tests executed.
|
|
||||||
- The structure is following:
|
## Automated checks
|
||||||
- [`cypress.config.ts`](./../cypress.config.ts): Cypress configuration file.
|
|
||||||
- [`./tests/e2e/`](./../tests/e2e/): Base Cypress folder.
|
These checks validate various qualities like runtime execution, building process, security testing, etc.
|
||||||
- [`/specs/`](./../tests/e2e/specs/): Test files named with `.spec.js` extension.
|
|
||||||
- [`/plugins/index.js`](./../tests/e2e/plugins/index.js): Plugin file executed before loading project.
|
- Use [various tools](./../package.json) and [scripts](./../scripts).
|
||||||
- [`/support/index.js`](./../tests/e2e/support/index.js): Support file, runs before every single spec file.
|
- Are automatically executed as [GitHub workflows](./../.github/workflows).
|
||||||
- *(Ignored)* `/videos`: Asset folder for videos taken during tests.
|
|
||||||
- *(Ignored)* `/screenshots`: Asset folder for Screenshots taken during tests.
|
### Security checks
|
||||||
|
|
||||||
|
- [`checks.security.sast`](./../.github/workflows/checks.security.sast.yaml): Utilizes CodeQL to conduct Static Analysis Security Testing (SAST) to ensure the secure integrity of the codebase.
|
||||||
|
- [`checks.security.dependencies`](./../.github/workflows/checks.security.dependencies.yaml): Performs audits on third-party dependencies to identify and mitigate potential vulnerabilities, safeguarding the project from exploitable weaknesses.
|
||||||
|
|
||||||
|
## Tests structure
|
||||||
|
|
||||||
|
- [`package.json`](./../package.json): Defines test commands and includes tools used in tests.
|
||||||
|
- [`vite.config.ts`](./../vite.config.ts): Configures `vitest` for unit and integration tests.
|
||||||
|
- [`./src/`](./../src/): Contains the code subject to testing.
|
||||||
|
- [`./tests/shared/`](./../tests/shared/): Contains code shared by different test categories.
|
||||||
|
- [`bootstrap/setup.ts`](./../tests/shared/bootstrap/setup.ts): Initializes unit and integration tests.
|
||||||
|
- [`Assertions/`](./../tests/shared/Assertions/): Contains common assertion functions, prefixed with `expect`.
|
||||||
|
- [`./tests/unit/`](./../tests/unit/)
|
||||||
|
- Stores unit test code.
|
||||||
|
- The directory structure mirrors [`./src/`](./../src).
|
||||||
|
- E.g., tests for [`./src/application/ApplicationFactory.ts`](./../src/application/ApplicationFactory.ts) reside in [`./tests/unit/application/ApplicationFactory.spec.ts`](./../tests/unit/application/ApplicationFactory.spec.ts).
|
||||||
|
- [`shared/`](./../tests/unit/shared/)
|
||||||
|
- Contains shared unit test functionalities.
|
||||||
|
- [`TestCases/`](./../tests/unit/shared/TestCases/)
|
||||||
|
- Shared test cases.
|
||||||
|
- Functions that calls `it()` from [Vitest](https://vitest.dev/) should have `it` prefix.
|
||||||
|
- [`Stubs/`](./../tests/unit/shared/Stubs): Maintains stubs for component isolation, equipped with basic functionalities and, when necessary, spying or mocking capabilities.
|
||||||
|
- [`./tests/integration/`](./../tests/integration/): Contains integration test files.
|
||||||
|
- [`cypress.config.ts`](./../cypress.config.ts): Cypress (E2E tests) configuration file.
|
||||||
|
- [`cypress-dirs.json`](./../cypress-dirs.json): A central definition of directories used by Cypress, designed for reuse across different configurations.
|
||||||
|
- [`./tests/e2e/`](./../tests/e2e/): Base Cypress folder, includes tests with `.cy.ts` extension.
|
||||||
|
- [`/tsconfig.json`]: TypeScript configuration for file Cypress code, improves IDE support, recommended to have by official documentation.
|
||||||
|
- *(git ignored)* `/videos`: Asset folder for videos taken during tests.
|
||||||
|
- *(git ignored)* `/screenshots`: Asset folder for Screenshots taken during tests.
|
||||||
|
- [`/support/e2e.ts`](./../tests/e2e/support/e2e.ts): Support file, runs before every single test file.
|
||||||
|
- [`/support/interactions/`](./../tests/e2e/support/interactions/): Contains reusable functions for simulating user interactions, enhancing test readability and maintainability.
|
||||||
|
|||||||
74
electron-builder.cjs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/* eslint-disable no-template-curly-in-string */
|
||||||
|
|
||||||
|
const { join, resolve } = require('node:path');
|
||||||
|
const { readdirSync, existsSync } = require('node: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: {
|
||||||
|
provider: 'github',
|
||||||
|
vPrefixedTagName: false, // default: true
|
||||||
|
releaseType: 'release', // default: draft
|
||||||
|
},
|
||||||
|
directories: {
|
||||||
|
output: electronBundled,
|
||||||
|
buildResources: resolvePathFromProjectRoot('src/presentation/electron/build'),
|
||||||
|
},
|
||||||
|
extraMetadata: {
|
||||||
|
main: findMainEntryFile(
|
||||||
|
join(electronUnbundled, 'main'), // do not `path.resolve`, it expects a relative path
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
// Windows
|
||||||
|
win: {
|
||||||
|
target: 'nsis',
|
||||||
|
},
|
||||||
|
nsis: {
|
||||||
|
artifactName: '${name}-Setup-${version}.${ext}',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Linux
|
||||||
|
linux: {
|
||||||
|
target: 'AppImage',
|
||||||
|
},
|
||||||
|
appImage: {
|
||||||
|
artifactName: '${name}-${version}.${ext}',
|
||||||
|
},
|
||||||
|
|
||||||
|
// macOS
|
||||||
|
mac: {
|
||||||
|
target: {
|
||||||
|
target: 'dmg',
|
||||||
|
arch: 'universal',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dmg: {
|
||||||
|
artifactName: '${name}-${version}.${ext}',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds by accommodating different JS file extensions and module formats.
|
||||||
|
*/
|
||||||
|
function findMainEntryFile(parentDirectory) {
|
||||||
|
const absoluteParentDirectory = resolvePathFromProjectRoot(parentDirectory);
|
||||||
|
if (!existsSync(absoluteParentDirectory)) {
|
||||||
|
return null; // Avoid disrupting other processes such `npm install`.
|
||||||
|
}
|
||||||
|
const files = readdirSync(absoluteParentDirectory);
|
||||||
|
const entryFile = files.find((file) => /^index\.(cjs|mjs|js)$/.test(file));
|
||||||
|
if (!entryFile) {
|
||||||
|
throw new Error(`Main entry file not found in ${absoluteParentDirectory}.`);
|
||||||
|
}
|
||||||
|
return join(parentDirectory, entryFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePathFromProjectRoot(pathSegment) {
|
||||||
|
return resolve(__dirname, pathSegment);
|
||||||
|
}
|
||||||
92
electron.vite.config.ts
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { mergeConfig, type UserConfig } from 'vite';
|
||||||
|
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
|
||||||
|
import { getAliases, getClientEnvironmentVariables } from './vite-config-helper';
|
||||||
|
import { createVueConfig } from './vite.config';
|
||||||
|
import distDirs from './dist-dirs.json' assert { type: 'json' };
|
||||||
|
|
||||||
|
const MAIN_ENTRY_FILE = resolvePathFromProjectRoot('src/presentation/electron/main/index.ts');
|
||||||
|
const PRELOAD_ENTRY_FILE = resolvePathFromProjectRoot('src/presentation/electron/preload/index.ts');
|
||||||
|
const WEB_INDEX_HTML_PATH = resolvePathFromProjectRoot('src/presentation/index.html');
|
||||||
|
const ELECTRON_DIST_SUBDIRECTORIES = {
|
||||||
|
main: resolveElectronDistSubdirectory('main'),
|
||||||
|
preload: resolveElectronDistSubdirectory('preload'),
|
||||||
|
renderer: resolveElectronDistSubdirectory('renderer'),
|
||||||
|
};
|
||||||
|
|
||||||
|
process.env.ELECTRON_ENTRY = resolve(ELECTRON_DIST_SUBDIRECTORIES.main, 'index.mjs');
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
main: getSharedElectronConfig({
|
||||||
|
distDirSubfolder: ELECTRON_DIST_SUBDIRECTORIES.main,
|
||||||
|
entryFilePath: MAIN_ENTRY_FILE,
|
||||||
|
}),
|
||||||
|
preload: getSharedElectronConfig({
|
||||||
|
distDirSubfolder: ELECTRON_DIST_SUBDIRECTORIES.preload,
|
||||||
|
entryFilePath: PRELOAD_ENTRY_FILE,
|
||||||
|
}),
|
||||||
|
renderer: mergeConfig(
|
||||||
|
createVueConfig({
|
||||||
|
supportLegacyBrowsers: false,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
build: {
|
||||||
|
outDir: ELECTRON_DIST_SUBDIRECTORIES.renderer,
|
||||||
|
rollupOptions: {
|
||||||
|
input: {
|
||||||
|
index: WEB_INDEX_HTML_PATH,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
function getSharedElectronConfig(options: {
|
||||||
|
readonly distDirSubfolder: string;
|
||||||
|
readonly entryFilePath: string;
|
||||||
|
}): UserConfig {
|
||||||
|
return {
|
||||||
|
build: {
|
||||||
|
outDir: options.distDirSubfolder,
|
||||||
|
lib: {
|
||||||
|
entry: options.entryFilePath,
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
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({
|
||||||
|
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(),
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
...getAliases(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePathFromProjectRoot(pathSegment: string): string {
|
||||||
|
return resolve(__dirname, pathSegment);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveElectronDistSubdirectory(subDirectory: string): string {
|
||||||
|
const electronDistDir = resolvePathFromProjectRoot(distDirs.electronUnbundled);
|
||||||
|
return resolve(electronDistDir, subDirectory);
|
||||||
|
}
|
||||||
@@ -4,9 +4,6 @@ This folder contains image files and other resources related to images.
|
|||||||
|
|
||||||
## logo.svg
|
## logo.svg
|
||||||
|
|
||||||
[logo.svg](./logo.svg) is the master logo from which all other icons or images are created from.
|
[`logo.svg`](./logo.svg) serves as the primary logo from which all other icons and images are derived.
|
||||||
It should be the only file that will be changed manually.
|
Only modify this file manually.
|
||||||
|
After making changes, execute `npm run build:icons` to regenerate logo files in various formats.
|
||||||
[`logo-update.mjs`](./logo-update.mjs) script in this folder updates all the logo files.
|
|
||||||
It should be executed everytime the logo is changed.
|
|
||||||
It automates recreation of logo files in different formats.
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<mxfile host="Electron" modified="2021-01-31T12:32:01.751Z" agent="5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="OTbSPW1ZOLwiPL6mt-j9" version="14.1.8" type="device"><diagram id="rhL8jzEM8kVVyiS98U7u" name="Page-1">3VtZd6JKF/01/dhZjA6PREjCXRbGFpM2L70QCYIoLsUI/PpvnwKcMD3cazrJl6wEqfHU3vvsKoz5Infm6e3KWU5ZPPGiL5IwSb/I+hdJUsUmflNBVhQoDaEo8FfBpCgS9wWDIPfKwqrZJph466OGSRxHSbA8LnTjxcJzk6MyZ7WKt8fNnuPoeNal43u1goHrRPXSx2CSTIvSlirsy++8wJ9WM4tCWTN3qsZlwXrqTOLtQZFsfJE7qzhOilfztONFhF2FS9Hv5pXaXWArb5H8Tofr+9ZNO9J+6A+Ljvr89N2aP5tflSq4JKtW7E0AQHkbr5Jp7McLJzL2pdereLOYeDSsgLt9m24cL1EoojD0kiQr2XQ2SYyiaTKPylovDZLv1P1KLe9GBzV6Wo7Mb7LqZpGssoNOdDs6rNt343dVv3WyimdeJ47iFV+f3OZfqKkDWGK6jjcr1/sJapUQnZXvJT9pJxXtCNGDCUp6br147iFSNFh5kZMEL8eSc0rl+rt2e3LxouT3T7iW3oXrHW9HrO1J/IC8yZfmjXfVVisnO2iwjINFsj4Y+Z4K0KD0TrnMzdI51ZP0/nlrSVRPBFNMv5fPbh3/QVHyu7rHgXcIV5L6m/bxeWSofCj7KMd9caJNOdP9yltj8Zg7XtSEcEzzdhok3mDpcFy2OCkcU/ocRNEBxhPVa02Uc+i3pLHcaFCPeJFUOjuzFVbBeqvES38KXlnbaB6nT5lN2/2eL1c7+/Rgv69OMxdHW268Z2qJR6n1m5klHmeW9B6pJb1Xav07h28fm7YoH5n2L9tLzebbm7zc+ixHxPcU1MWPDP/JPaSaV2vLZRS4l7DqI+OtWfezSt/nyGjwr3KEg/Li62ck/b6Lq8cuvnsYO7Rx6YyNN9/MxtXPkjwf6flK/pQHJLmWdHo8d4LLHo3G4mTyfBZ3UWjKbe8Njkbtk6Rq15NKUs4klfpWSaXUgDYXzysHiGzcZLPyLgr4c8v1XPcc4OOWqqjCGwDePDmLNs4A3vqbLtaoAe69eOXJ5hWgxT8H+tlrnAd60myPBeEyO0TrBNtmHdvmGWilt4K2WYN25S3jdZDE5eCfGl75zAb8V+Ft1a3CWCRB8hmxPfWFdwe3XQM3ma48ZxIs/P8DeN/dGsT6KX5Of165rO2OBU/2GufAFbyW0GpdBlwcTo7BFZQ6uOqVeAZe6a3grZ/X8DKY/OoZ6aNCLKniVfvDgazWQF4nTvKzI9qf42vo9H0ZFE9MQKze/XhHCP/K6euSGJ6+mXoORPHcu6lvh2H9mOUcviEiRLEfuJ8HULG+Nf1dQHdr2AOazamXG0eR5xKqH1efHw/N+lZUA289dZb0MpjzTywcQkUrh5QjLQr8BcoSeptoV9p1xl50T48UJHVZH8dJEs/RIKKKa8ed+ZyYowMXfaEJn0xbL4tPVtBBy6lunoOUqLwu49GnSUIfydAICenGnSyUq8CNF88BKF9duZhRusHe6uBC5VDHDZIuXn91FpOv4xV+U5FKh54budH88bDxwvUPaoKDUOtqWZ0pL/pk3aa/UpxyryhXap38fenl6a9vkp+ffvmP6f/qTOKxtxOB1Gr9GDjr9QXpl9TWVVP9PQlI5zUgvZkI6tv85xeB+EsRjBdb/AbFKX7wCtsyFdNbausLsS7LyhHlcuOqVT+QSO0zht9+K7Lr55HPT7bwS7Kf45XvLb6uvZg+TXDTAC83y4C/Z7v+Gi+TYB7k/ER2wZzfvUtSsS/XqK/0cUh9VfZfqH/Y3Hrj5vegr7fv2awhLwLh8cyf5n7J/CWIPS+Z8+Qe8V/RzamUteJWulm/gJzrlM58nfs7S3rKrpXxY7pxcyFw7r4Jrh6/dOWJPMlUmWXqizt3X1iobVmnnU/mbmDeTZZPd9/i+4GZWfYoMG+nkfM4iSe6ELBwKJnBteQ8Psj9eVtBm62paz4v103RCkzMfX/r+k/zaD1Gj/G8vXkamMV9R8wmj2l0P/gnmswfNmPp28wMldZIirKRlEbm7dNyfLttmwHL+uE/N0wwMLtFs6Qs9Om1unt9Z7bN0Mh6HfPlPkwXB33Vb7OH62/hLCjLEnfxsH6yi1i8+UM2zniUd9fTya3vPyFK2zawfkVkuulbubGxwijs2qbUBS7WQBC6oZtbgSBYgSJaobthoZl27SGVSyzQUqujCMweJqhPcfWZrW0se5Z17f6G5SMZ2KDtKLcGGq6mYOpMxb1gzY0MV8nKtOoKPA2fdajdKMOcVC4yiSVWpsiWbSbMZhjbxNgzxDFCHKZIYzEepylYmZAjnhx1PuJRmO6jD9aUz1LiqBsaQq8jpKjLMJZv6RjH9uWubaTd0M+tx3MxaRTTpmcPJawb8/Zlby4kWBvKZqqpu2jLtpbEUo4jxwBz2kOxWLshW4GWsUDJe3bfZ/kM8ZBmGOZkSq+j5bQ+FjJoiWL1wYO76el+jv4y4tiygaaijYR+GBu42po0sk1wxfEtr4hzoG27wIjpmkj4WzraZVgvjU9zow/TXQXrABY+8Qeeh4SJivi2TGcJHz830MYgvMCvoIBrzkcP2Fq8DeFPPDDU9WX0zxnVvcqpkHfDmQAN4DpUvYArdzv6/i02b/ttcyakPYo3NGl9W8xHvFPcWyg+QY5izQblGcadIXcFgc+n+xwP8CsWmhymLBBIu+grEB8CcEW8Ptqwck0zWgv0CDz1IepGGLt/Hs8O8BwoWyuc+Wifs9wKGdeARtio4C4j3Vvh0IfuVHALfg1gPEOsBtbaV0x9RPFluE8pZ4ABrn3oxkQe+FuKE30zWgt+gP1MfY1bU+8Tf9Ay8kDvS6RDi17nlAsjhWvtkdY7pHFIY4h1poInmluxOhrmdIUe8gXYiozj7UNrTCy4nAms0KqAssQKSQt96Jj0MiIfkICpwmwXGoWOwdPrsRJOrgz8ZCt/CLkubZYjZ0n3AmLJMJZq6W5i0Rj5CJgMEYNJmMiESY+0w/EeIUcpTkMs8sYAf8CNuAk06Arj5CbnGXy/ih/4Jx3JRR4b4hkdKtxrMi3t6S7laT7KMa+tCUUu+6RB4lXqwc8QP7h3eU739D7mIe0apPuUUUz6kDREeKo9e5T0qL3OuEYseFGXvIzy5/bVvCFNy/C3jPN2W3ohjYs1kkd0aT2hKUKLaW+gKD3ySfJpvQ//MEhjyG3kAvyD8XgE0qxI8XA/DYeUx7S2DJiCY7STXo0HOsB6uIZd1ZKXCTiBRkzu9z19BLwoj42kyEsT+qdYfLHUYIo4Ea+m0N6CeAXue1inRdjkM65dC+OAb8xtSow8PSM9ukmP+1c/ezVXqd4eCZQnaC+McoPvNSzTuIfhWuwPpF/eZkQ5grWT12jEPfj0aayUv87dpPBt4piwYrTPUR5R/iiv40T+oEHPtA/McuSpCK1k2DtoPInZ/4RYM+FAuSgSLvBZeBe45X7F84G4zfg+m1VtuYbLMu20n1/1IzzIO7G/kW/tvL+o2/Xf9ava0rqrGE777eYF5zx/4Iamfj0lbjAW4uvnZZ7Bi4wyV3gcx/WYAzGU9dcN2+7THqLynON7Vz8d5aSZ4UE8/dN4hAMcgAnXu0px4QwjHuC2679fB28LXWrJHhPe73DMPaaFXgn7Au+BdgbvPTZFjgAdySjXDB/RWbVu0jr5vQLfOq2vtFPUL+Kgmyst9/ZGcDrXM5wcLcxH5wHSqkjnLkv/Fv4Rd3WshDpW7BQr9V9j1flbWGEs7rczn2so9zOce6CxmVLstxo8XeBeWJwrNRWemvL9Jx8mHMP8aQo/ynCu86trNU9RT35J50BXIo/r2eRptNe78B/yf9pvyZ/orGls6ZxSxK3RtYxBK2OqYtCKmIr85vtOEdNTwwxadFLvtBf34fblCUroyniiyRV6hrrMnz8l+Uo9fuNJlurPoY0zz6GNP34Oxe3+v8qKTwHv/zVPNv4H</diagram></mxfile>
|
|
||||||
BIN
img/architecture/app-ddd.drawio.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 100 KiB |
@@ -1,127 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
import { resolve, join } from 'path';
|
|
||||||
import { rm, mkdtemp, stat } from 'fs/promises';
|
|
||||||
import { spawn } from 'child_process';
|
|
||||||
import { URL, fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
class Paths {
|
|
||||||
constructor(selfDirectory) {
|
|
||||||
const projectRoot = resolve(selfDirectory, '../');
|
|
||||||
this.sourceImage = join(projectRoot, 'img/logo.svg');
|
|
||||||
this.publicDirectory = join(projectRoot, 'public');
|
|
||||||
this.electronBuildDirectory = join(projectRoot, 'build');
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `Source image: ${this.sourceImage}\n`
|
|
||||||
+ `Public directory: ${this.publicDirectory}\n`
|
|
||||||
+ `Electron build directory: ${this.electronBuildDirectory}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const paths = new Paths(getCurrentScriptDirectory());
|
|
||||||
console.log(`Paths:\n\t${paths.toString().replaceAll('\n', '\n\t')}`);
|
|
||||||
await updateDesktopLauncherAndTrayIcon(paths.sourceImage, paths.publicDirectory);
|
|
||||||
await updateWebFavicon(paths.sourceImage, paths.publicDirectory);
|
|
||||||
await updateDesktopIcons(paths.sourceImage, paths.electronBuildDirectory);
|
|
||||||
console.log('🎉 (Re)created icons successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateDesktopLauncherAndTrayIcon(sourceImage, publicFolder) {
|
|
||||||
await ensureFileExists(sourceImage);
|
|
||||||
await ensureFolderExists(publicFolder);
|
|
||||||
const electronTrayIconFile = join(publicFolder, 'icon.png');
|
|
||||||
console.log(`Updating desktop launcher and tray icon at ${electronTrayIconFile}.`);
|
|
||||||
await runCommand(
|
|
||||||
'npx',
|
|
||||||
'svgexport',
|
|
||||||
sourceImage,
|
|
||||||
electronTrayIconFile,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateWebFavicon(sourceImage, faviconFolder) {
|
|
||||||
console.log('Updating favicon');
|
|
||||||
await ensureFileExists(sourceImage);
|
|
||||||
await ensureFolderExists(faviconFolder);
|
|
||||||
await runCommand(
|
|
||||||
'npx',
|
|
||||||
'icon-gen',
|
|
||||||
`--input ${sourceImage}`,
|
|
||||||
`--output ${faviconFolder}`,
|
|
||||||
'--ico',
|
|
||||||
'--ico-name \'favicon\'',
|
|
||||||
'--report',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateDesktopIcons(sourceImage, electronIconsDir) {
|
|
||||||
await ensureFileExists(sourceImage);
|
|
||||||
await ensureFolderExists(electronIconsDir);
|
|
||||||
const temporaryDir = await mkdtemp('icon-');
|
|
||||||
const temporaryPngFile = join(temporaryDir, 'icon.png');
|
|
||||||
console.log(`Converting from SVG (${sourceImage}) to PNG: ${temporaryPngFile}`); // required by icon-builder
|
|
||||||
await runCommand(
|
|
||||||
'npx',
|
|
||||||
'svgexport',
|
|
||||||
sourceImage,
|
|
||||||
temporaryPngFile,
|
|
||||||
'1024:1024',
|
|
||||||
);
|
|
||||||
console.log(`Creating electron icons to ${electronIconsDir}.`);
|
|
||||||
await runCommand(
|
|
||||||
'npx',
|
|
||||||
'electron-icon-builder',
|
|
||||||
`--input="${temporaryPngFile}"`,
|
|
||||||
`--output="${electronIconsDir}"`,
|
|
||||||
'--flatten',
|
|
||||||
);
|
|
||||||
console.log('Cleaning up temporary directory.');
|
|
||||||
await rm(temporaryDir, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ensureFileExists(filePath) {
|
|
||||||
const path = await stat(filePath);
|
|
||||||
if (!path.isFile()) {
|
|
||||||
throw new Error(`Not a file: ${filePath}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ensureFolderExists(folderPath) {
|
|
||||||
const path = await stat(folderPath);
|
|
||||||
if (!path.isDirectory()) {
|
|
||||||
throw new Error(`Not a directory: ${folderPath}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runCommand(...args) {
|
|
||||||
const command = args.join(' ');
|
|
||||||
console.log(`Running command: ${command}`);
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
const process = spawn(command, { shell: true });
|
|
||||||
process.stdout.on('data', (stdout) => {
|
|
||||||
console.log(stdout.toString());
|
|
||||||
});
|
|
||||||
process.stderr.on('data', (stderr) => {
|
|
||||||
console.error(stderr.toString());
|
|
||||||
});
|
|
||||||
process.on('error', (err) => {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
process.on('close', (exitCode) => {
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
reject(new Error(`Process exited with non-zero exit code: ${exitCode}`));
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
process.stdin.end();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentScriptDirectory() {
|
|
||||||
return fileURLToPath(new URL('.', import.meta.url));
|
|
||||||
}
|
|
||||||
|
|
||||||
await main();
|
|
||||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 116 KiB |
41573
package-lock.json
generated
164
package.json
@@ -1,112 +1,106 @@
|
|||||||
{
|
{
|
||||||
"name": "privacy.sexy",
|
"name": "privacy.sexy",
|
||||||
"version": "0.12.0",
|
"version": "0.13.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"slogan": "Now you have the choice",
|
"slogan": "Privacy is sexy",
|
||||||
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy 🍑🍆",
|
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy.",
|
||||||
"author": "undergroundwires",
|
"author": "undergroundwires",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"dev": "vite",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"test:unit": "vue-cli-service test:unit",
|
"preview": "vite preview",
|
||||||
"test:e2e": "vue-cli-service test:e2e",
|
"test:unit": "vitest run --dir tests/unit",
|
||||||
"lint": "npm run lint:md && npm run lint:md:consistency && npm run lint:md:relative-urls && npm run lint:eslint && npm run lint:yaml",
|
"test:integration": "vitest run --dir tests/integration",
|
||||||
"create-icons": "node img/logo-update.mjs",
|
"test:cy:run": "start-server-and-test \"vite build && vite preview --port 7070\" http://localhost:7070 \"cypress run --config baseUrl=http://localhost:7070\"",
|
||||||
"electron:build": "vue-cli-service electron:build",
|
"test:cy:open": "start-server-and-test \"vite --port 7070 --mode production\" http://localhost:7070 \"cypress open --config baseUrl=http://localhost:7070\"",
|
||||||
"electron:serve": "vue-cli-service electron:serve",
|
"lint": "npm run lint:md && npm run lint:md:consistency && npm run lint:md:relative-urls && npm run lint:eslint && npm run lint:yaml && npm run lint:pylint",
|
||||||
"lint:eslint": "vue-cli-service lint --no-fix --mode production",
|
"install-deps": "node scripts/npm-install.js",
|
||||||
|
"icons:build": "node scripts/logo-update.js",
|
||||||
|
"check:desktop": "vitest run --dir tests/checks/desktop-runtime-errors --environment node",
|
||||||
|
"check:external-urls": "vitest run --dir tests/checks/external-urls --environment node",
|
||||||
|
"check:verify-build-artifacts": "node scripts/verify-build-artifacts",
|
||||||
|
"electron:dev": "electron-vite dev",
|
||||||
|
"electron:preview": "electron-vite preview",
|
||||||
|
"electron:prebuild": "electron-vite build",
|
||||||
|
"electron:build": "electron-builder",
|
||||||
|
"lint:eslint": "eslint . --max-warnings=0 --ignore-path .gitignore",
|
||||||
"lint:md": "markdownlint **/*.md --ignore node_modules",
|
"lint:md": "markdownlint **/*.md --ignore node_modules",
|
||||||
"lint:md:consistency": "remark . --frail --use remark-preset-lint-consistent",
|
"lint:md:consistency": "remark . --frail --use remark-preset-lint-consistent",
|
||||||
"lint:md:relative-urls": "remark . --frail --use remark-validate-links",
|
"lint:md:relative-urls": "remark . --frail --use remark-validate-links",
|
||||||
"lint:yaml": "yamllint **/*.yaml --ignore=node_modules/**/*.yaml",
|
"lint:yaml": "yamllint **/*.yaml --ignore=node_modules/**/*.yaml",
|
||||||
|
"lint:pylint": "pylint **/*.py",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"postuninstall": "electron-builder install-app-deps",
|
"postuninstall": "electron-builder install-app-deps"
|
||||||
"test:integration": "vue-cli-service test:unit \"tests/integration/**/*.spec.ts\""
|
|
||||||
},
|
},
|
||||||
"main": "index.js",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
"@floating-ui/vue": "^1.0.6",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.4.0",
|
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
|
||||||
"@fortawesome/vue-fontawesome": "^2.0.9",
|
|
||||||
"@juggle/resize-observer": "^3.4.0",
|
"@juggle/resize-observer": "^3.4.0",
|
||||||
"ace-builds": "^1.23.4",
|
"ace-builds": "^1.33.0",
|
||||||
"core-js": "^3.32.0",
|
"electron-log": "^5.1.2",
|
||||||
"cross-fetch": "^4.0.0",
|
"electron-progressbar": "^2.2.1",
|
||||||
"electron-progressbar": "^2.1.0",
|
"electron-updater": "^6.1.9",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"install": "^0.13.0",
|
"markdown-it": "^14.1.0",
|
||||||
"liquor-tree": "^0.2.70",
|
"vue": "^3.4.27"
|
||||||
"markdown-it": "^13.0.1",
|
|
||||||
"npm": "^9.8.1",
|
|
||||||
"v-tooltip": "2.1.3",
|
|
||||||
"vue": "^2.7.14",
|
|
||||||
"vue-class-component": "^7.2.6",
|
|
||||||
"vue-js-modal": "^2.0.1",
|
|
||||||
"vue-property-decorator": "^9.1.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.3.2",
|
"@modyfi/vite-plugin-yaml": "^1.1.0",
|
||||||
"@types/ace": "^0.0.48",
|
"@rushstack/eslint-patch": "^1.10.2",
|
||||||
"@types/chai": "^4.3.5",
|
"@types/ace": "^0.0.52",
|
||||||
"@types/file-saver": "^2.0.5",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/markdown-it": "^14.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "6.21.0",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@typescript-eslint/parser": "6.21.0",
|
||||||
"@vue/cli-plugin-babel": "~5.0.8",
|
"@vitejs/plugin-legacy": "^5.3.2",
|
||||||
"@vue/cli-plugin-e2e-cypress": "~5.0.8",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"@vue/cli-plugin-eslint": "~5.0.8",
|
"@vue/eslint-config-airbnb-with-typescript": "^8.0.0",
|
||||||
"@vue/cli-plugin-typescript": "~5.0.8",
|
"@vue/eslint-config-typescript": "12.0.0",
|
||||||
"@vue/cli-plugin-unit-mocha": "~5.0.8",
|
"@vue/test-utils": "^2.4.5",
|
||||||
"@vue/cli-service": "~5.0.8",
|
"autoprefixer": "^10.4.19",
|
||||||
"@vue/eslint-config-airbnb-with-typescript": "^7.0.0",
|
"cypress": "^13.7.3",
|
||||||
"@vue/eslint-config-typescript": "^11.0.3",
|
"electron": "^29.3.0",
|
||||||
"chai": "^4.3.7",
|
"electron-builder": "^24.13.3",
|
||||||
"cypress": "^12.17.2",
|
|
||||||
"electron": "^25.3.2",
|
|
||||||
"electron-builder": "^24.6.3",
|
|
||||||
"electron-devtools-installer": "^3.2.0",
|
"electron-devtools-installer": "^3.2.0",
|
||||||
"electron-icon-builder": "^2.0.1",
|
"electron-vite": "^2.1.0",
|
||||||
"electron-log": "^4.4.8",
|
"eslint": "8.57.0",
|
||||||
"electron-updater": "^6.1.4",
|
"eslint-plugin-cypress": "^2.15.1",
|
||||||
"eslint": "^8.46.0",
|
"eslint-plugin-vue": "^9.25.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-vuejs-accessibility": "^2.2.1",
|
||||||
"eslint-plugin-vue": "^9.6.0",
|
"jsdom": "^24.0.0",
|
||||||
"eslint-plugin-vuejs-accessibility": "^1.2.0",
|
"markdownlint-cli": "^0.39.0",
|
||||||
"icon-gen": "^3.0.1",
|
"postcss": "^8.4.38",
|
||||||
"js-yaml-loader": "^1.2.2",
|
"remark-cli": "^12.0.0",
|
||||||
"markdownlint-cli": "^0.35.0",
|
|
||||||
"remark-cli": "^11.0.0",
|
|
||||||
"remark-lint-no-dead-urls": "^1.1.0",
|
"remark-lint-no-dead-urls": "^1.1.0",
|
||||||
"remark-preset-lint-consistent": "^5.1.2",
|
"remark-preset-lint-consistent": "^6.0.0",
|
||||||
"remark-validate-links": "^12.1.1",
|
"remark-validate-links": "^13.0.1",
|
||||||
"sass": "^1.64.1",
|
"sass": "^1.75.0",
|
||||||
"sass-loader": "^13.3.2",
|
"start-server-and-test": "^2.0.3",
|
||||||
"svgexport": "^0.4.2",
|
"terser": "^5.30.3",
|
||||||
"ts-loader": "^9.4.4",
|
"tslib": "^2.6.2",
|
||||||
"typescript": "~4.6.2",
|
"typescript": "^5.4.5",
|
||||||
"vue-cli-plugin-electron-builder": "^3.0.0-alpha.4",
|
"vite": "^5.2.8",
|
||||||
"yaml-lint": "^1.7.0",
|
"vitest": "^1.5.0",
|
||||||
"tslib": "~2.4.0"
|
"vue-tsc": "^2.0.13",
|
||||||
},
|
"yaml-lint": "^1.7.0"
|
||||||
"overrides": {
|
|
||||||
"vue-cli-plugin-electron-builder": {
|
|
||||||
"electron-builder": "^24.6.3"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"//devDependencies": {
|
"//devDependencies": {
|
||||||
"typescript": [
|
"terser": "Used by `@vitejs/plugin-legacy` for minification",
|
||||||
"Cannot upgrade to 5.X.X due to unmaintained @vue/cli-plugin-typescript, https://github.com/vuejs/vue-cli/issues/7401",
|
"@rushstack/eslint-patch": "Needed by `@vue/eslint-config-typescript` and `@vue/eslint-config-airbnb-with-typescript`",
|
||||||
"Cannot upgrade to > 4.6.X otherwise unit tests do not work, https://github.com/evanw/node-source-map-support/issues/252"
|
"@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",
|
||||||
"tslib": "Cannot upgrade to > 2.4.X otherwise unit tests do not work, https://github.com/evanw/node-source-map-support/issues/252",
|
"@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",
|
||||||
"@typescript-eslint/eslint-plugin": "Cannot upgrade to 6.X.X due to @vue/eslint-config-typescript, https://github.com/vuejs/eslint-config-typescript/pull/60",
|
"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"
|
||||||
"@typescript-eslint/parser": "Cannot upgrade to 6.X.X due to @vue/eslint-config-typescript, https://github.com/vuejs/eslint-config-typescript/pull/60"
|
|
||||||
},
|
},
|
||||||
"homepage": "https://privacy.sexy",
|
"homepage": "https://privacy.sexy",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/undergroundwires/privacy.sexy.git"
|
"url": "https://github.com/undergroundwires/privacy.sexy.git"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"dmg-license": "^1.0.11"
|
||||||
|
},
|
||||||
|
"//optionalDependencies": {
|
||||||
|
"dmg-license": "Required by `electron-builder` for DMG builds on macOS, https://github.com/electron-userland/electron-builder/issues/6489, https://github.com/electron-userland/electron-builder/issues/6520"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
postcss.config.cjs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const autoprefixer = require('autoprefixer');
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
return {
|
||||||
|
plugins: [
|
||||||
|
autoprefixer(),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
BIN
public/icon.png
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,34 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
||||||
<title>Privacy is sexy 🍑🍆 - Enforce privacy & security on Windows, macOS and Linux</title>
|
|
||||||
<meta name="robots" content="index,follow" />
|
|
||||||
<meta name="description" content="Web tool to generate scripts for enforcing privacy & security best-practices such as stopping data collection of Windows and different softwares on it."/>
|
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>
|
|
||||||
<style>
|
|
||||||
#javascriptDisabled {
|
|
||||||
background:#eceef1;
|
|
||||||
margin: 5rem auto;
|
|
||||||
max-width: 800px;
|
|
||||||
font-size: 7px;
|
|
||||||
padding: 3rem;
|
|
||||||
border: 1px solid#333a45;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: 150%;
|
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id="javascriptDisabled">
|
|
||||||
<h1>Problem loading page</h1>
|
|
||||||
<p>The page does not work without JavaScript enabled. Please enable it to use privacy.sexy. There's no shady stuff as 100% of the website is open source.</p>
|
|
||||||
</div>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- built files will be auto injected -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This script ensures that the '.vscode/settings.json' file exists and is configured correctly for ESLint validation on Vue and JavaScript files.
|
|
||||||
# See https://web.archive.org/web/20230801024405/https://eslint.vuejs.org/user-guide/#visual-studio-code
|
|
||||||
|
|
||||||
declare -r SETTINGS_FILE='.vscode/settings.json'
|
|
||||||
declare -ra CONFIG_KEYS=('vue' 'javascript' 'typescript')
|
|
||||||
declare -r TEMP_FILE="tmp.$$.json"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
ensure_vscode_directory_exists
|
|
||||||
create_or_update_settings
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_vscode_directory_exists() {
|
|
||||||
local dir_name
|
|
||||||
dir_name=$(dirname "${SETTINGS_FILE}")
|
|
||||||
if [[ ! -d ${dir_name} ]]; then
|
|
||||||
mkdir -p "${dir_name}"
|
|
||||||
echo "🎉 Created directory: ${dir_name}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
create_or_update_settings() {
|
|
||||||
if [[ ! -f ${SETTINGS_FILE} ]]; then
|
|
||||||
create_default_settings
|
|
||||||
else
|
|
||||||
add_or_update_eslint_validate
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
create_default_settings() {
|
|
||||||
local default_validate
|
|
||||||
default_validate=$(printf '%s' "${CONFIG_KEYS[*]}" | jq -R -s -c -M 'split(" ")')
|
|
||||||
echo "{ \"eslint.validate\": ${default_validate} }" | jq '.' > "${SETTINGS_FILE}"
|
|
||||||
echo "🎉 Created default ${SETTINGS_FILE}"
|
|
||||||
}
|
|
||||||
|
|
||||||
add_or_update_eslint_validate() {
|
|
||||||
if ! jq -e '.["eslint.validate"]' "${SETTINGS_FILE}" >/dev/null; then
|
|
||||||
add_default_eslint_validate
|
|
||||||
else
|
|
||||||
update_eslint_validate
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
add_default_eslint_validate() {
|
|
||||||
jq --argjson keys "$(printf '%s' "${CONFIG_KEYS[*]}" \
|
|
||||||
| jq -R -s -c 'split(" ")')" '. += {"eslint.validate": $keys}' "${SETTINGS_FILE}" > "${TEMP_FILE}"
|
|
||||||
replace_and_confirm
|
|
||||||
echo "🎉 Added default 'eslint.validate' to ${SETTINGS_FILE}"
|
|
||||||
}
|
|
||||||
|
|
||||||
update_eslint_validate() {
|
|
||||||
local existing_keys
|
|
||||||
existing_keys=$(jq '.["eslint.validate"]' "${SETTINGS_FILE}")
|
|
||||||
for key in "${CONFIG_KEYS[@]}"; do
|
|
||||||
if ! echo "${existing_keys}" | jq 'index("'"${key}"'")' >/dev/null; then
|
|
||||||
jq '.["eslint.validate"] += ["'"${key}"'"]' "${SETTINGS_FILE}" > "${TEMP_FILE}"
|
|
||||||
mv "${TEMP_FILE}" "${SETTINGS_FILE}"
|
|
||||||
echo "🎉 Updated 'eslint.validate' in ${SETTINGS_FILE} for ${key}"
|
|
||||||
else
|
|
||||||
echo "⏩️ No updated needed for ${key} ${SETTINGS_FILE}."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
replace_and_confirm() {
|
|
||||||
if mv "${TEMP_FILE}" "${SETTINGS_FILE}"; then
|
|
||||||
echo "🎉 Updated ${SETTINGS_FILE}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
||||||
186
scripts/configure_vscode.py
Executable file
@@ -0,0 +1,186 @@
|
|||||||
|
"""
|
||||||
|
Description:
|
||||||
|
This script configures project-level VSCode settings in '.vscode/settings.json' for
|
||||||
|
development and installs recommended extensions from '.vscode/extensions.json'.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 ./scripts/configure_vscode.py
|
||||||
|
"""
|
||||||
|
# pylint: disable=missing-function-docstring
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
from typing import Any, Optional
|
||||||
|
from shutil import which
|
||||||
|
|
||||||
|
VSCODE_SETTINGS_JSON_FILE: str = '.vscode/settings.json'
|
||||||
|
VSCODE_EXTENSIONS_JSON_FILE: str = '.vscode/extensions.json'
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
ensure_vscode_directory_exists()
|
||||||
|
ensure_setting_file_exists()
|
||||||
|
add_or_update_settings()
|
||||||
|
install_recommended_extensions()
|
||||||
|
|
||||||
|
def ensure_vscode_directory_exists() -> None:
|
||||||
|
vscode_directory_path = os.path.dirname(VSCODE_SETTINGS_JSON_FILE)
|
||||||
|
try:
|
||||||
|
os.makedirs(vscode_directory_path, exist_ok=True)
|
||||||
|
print_success(f"Created or verified directory: {vscode_directory_path}")
|
||||||
|
except OSError as error:
|
||||||
|
print_error(f"Error handling directory {vscode_directory_path}: {error}")
|
||||||
|
|
||||||
|
def ensure_setting_file_exists() -> None:
|
||||||
|
try:
|
||||||
|
if os.path.isfile(VSCODE_SETTINGS_JSON_FILE):
|
||||||
|
print_success(f"VSCode settings file exists: {VSCODE_SETTINGS_JSON_FILE}")
|
||||||
|
return
|
||||||
|
with open(VSCODE_SETTINGS_JSON_FILE, 'w', encoding='utf-8') as file:
|
||||||
|
json.dump({}, file, indent=4)
|
||||||
|
print_success(f"Created empty {VSCODE_SETTINGS_JSON_FILE}")
|
||||||
|
except IOError as error:
|
||||||
|
print_error(f"Error creating file {VSCODE_SETTINGS_JSON_FILE}: {error}")
|
||||||
|
print_success(f"Created empty {VSCODE_SETTINGS_JSON_FILE}")
|
||||||
|
|
||||||
|
def add_or_update_settings() -> None:
|
||||||
|
configure_setting_key('eslint.validate', ['vue', 'javascript', 'typescript'])
|
||||||
|
# Set ESLint validation for specific file types.
|
||||||
|
# Details: # pylint: disable-next=line-too-long
|
||||||
|
# - https://web.archive.org/web/20230801024405/https://eslint.vuejs.org/user-guide/#visual-studio-code
|
||||||
|
|
||||||
|
configure_setting_key('terminal.integrated.env.linux', {"GTK_PATH": ""})
|
||||||
|
# Unset GTK_PATH on Linux for Electron development in sandboxed environments
|
||||||
|
# like Snap or Flatpak VSCode installations, enabling script execution.
|
||||||
|
# Details: # pylint: disable-next=line-too-long
|
||||||
|
# - https://archive.ph/2024.01.06-003914/https://github.com/microsoft/vscode/issues/179274, https://web.archive.org/web/20240106003915/https://github.com/microsoft/vscode/issues/179274
|
||||||
|
|
||||||
|
def configure_setting_key(configuration_key: str, desired_value: Any) -> None:
|
||||||
|
try:
|
||||||
|
with open(VSCODE_SETTINGS_JSON_FILE, 'r+', encoding='utf-8') as file:
|
||||||
|
settings: dict = json.load(file)
|
||||||
|
if configuration_key in settings:
|
||||||
|
actual_value = settings[configuration_key]
|
||||||
|
if actual_value == desired_value:
|
||||||
|
print_skip(f"Already configured as desired: \"{configuration_key}\"")
|
||||||
|
return
|
||||||
|
settings[configuration_key] = desired_value
|
||||||
|
file.seek(0)
|
||||||
|
json.dump(settings, file, indent=4)
|
||||||
|
file.truncate()
|
||||||
|
print_success(f"Added or updated configuration: {configuration_key}")
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print_error(f"Failed to update JSON for key {configuration_key}.")
|
||||||
|
|
||||||
|
def install_recommended_extensions() -> None:
|
||||||
|
if not os.path.isfile(VSCODE_EXTENSIONS_JSON_FILE):
|
||||||
|
print_error(
|
||||||
|
f"The extensions.json file does not exist in the path: {VSCODE_EXTENSIONS_JSON_FILE}."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
with open(VSCODE_EXTENSIONS_JSON_FILE, 'r', encoding='utf-8') as file:
|
||||||
|
json_content: str = remove_json_comments(file.read())
|
||||||
|
try:
|
||||||
|
data: dict = json.loads(json_content)
|
||||||
|
extensions: list[str] = data.get("recommendations", [])
|
||||||
|
if not extensions:
|
||||||
|
print_skip(f"No recommendations found in the {VSCODE_EXTENSIONS_JSON_FILE} file.")
|
||||||
|
return
|
||||||
|
vscode_cli_path = locate_vscode_cli()
|
||||||
|
if vscode_cli_path is None:
|
||||||
|
print_error('Visual Studio Code CLI (`code`) tool not found.')
|
||||||
|
return
|
||||||
|
install_vscode_extensions(vscode_cli_path, extensions)
|
||||||
|
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 = [
|
||||||
|
# VS Code on macOS may not register 'code' command in PATH
|
||||||
|
'/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code'
|
||||||
|
]
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
def install_vscode_extensions(vscode_cli_path: str, extensions: list[str]) -> None:
|
||||||
|
successful_installations = 0
|
||||||
|
for ext in extensions:
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
[vscode_cli_path, "--install-extension", ext],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if "already installed" in result.stdout:
|
||||||
|
print_skip(f"Created or verified directory: {ext}")
|
||||||
|
else:
|
||||||
|
print_success(f"Installed extension: {ext}")
|
||||||
|
successful_installations += 1
|
||||||
|
print_subprocess_output(result)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print_subprocess_output(e)
|
||||||
|
print_error(f"Failed to install extension: {ext}")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print_error(' '.join([
|
||||||
|
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)
|
||||||
|
|
||||||
|
def print_subprocess_output(result: subprocess.CompletedProcess[str]) -> None:
|
||||||
|
output = '\n'.join([text.strip() for text in [result.stdout, result.stderr] if text])
|
||||||
|
if not output:
|
||||||
|
return
|
||||||
|
formatted_output = '\t' + output.strip().replace('\n', '\n\t')
|
||||||
|
print(formatted_output)
|
||||||
|
|
||||||
|
def print_installation_results(successful_installations: int, total_extensions: int) -> None:
|
||||||
|
if successful_installations == total_extensions:
|
||||||
|
print_success(
|
||||||
|
f"Successfully installed or verified all {total_extensions} recommended extensions."
|
||||||
|
)
|
||||||
|
elif successful_installations > 0:
|
||||||
|
print_warning(
|
||||||
|
f"Partially successful: Installed or verified {successful_installations} "
|
||||||
|
f"out of {total_extensions} recommended extensions."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print_error("Failed to install any of the recommended extensions.")
|
||||||
|
|
||||||
|
def print_error(message: str) -> None:
|
||||||
|
print(f"[ERROR] {message}", file=sys.stderr)
|
||||||
|
|
||||||
|
def print_success(message: str) -> None:
|
||||||
|
print(f"[SUCCESS] {message}")
|
||||||
|
|
||||||
|
def print_skip(message: str) -> None:
|
||||||
|
print(f"[SKIPPED] {message}")
|
||||||
|
|
||||||
|
def print_warning(message: str) -> None:
|
||||||
|
print(f"[WARNING] {message}", file=sys.stderr)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Description:
|
|
||||||
# This script ensures npm is available, removes existing node modules, optionally
|
|
||||||
# removes package-lock.json (when -n flag is used), installs dependencies and runs unit tests.
|
|
||||||
# Usage:
|
|
||||||
# ./fresh-npm-install.sh # Regular execution
|
|
||||||
# ./fresh-npm-install.sh -n # Non-deterministic mode (removes package-lock.json)
|
|
||||||
|
|
||||||
declare NON_DETERMINISTIC_FLAG=0
|
|
||||||
|
|
||||||
|
|
||||||
main() {
|
|
||||||
parse_args "$@"
|
|
||||||
ensure_npm_is_available
|
|
||||||
ensure_npm_root
|
|
||||||
remove_existing_modules
|
|
||||||
if [[ $NON_DETERMINISTIC_FLAG -eq 1 ]]; then
|
|
||||||
remove_package_lock_json
|
|
||||||
fi
|
|
||||||
install_dependencies
|
|
||||||
run_unit_tests
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_npm_is_available() {
|
|
||||||
if ! command -v npm &> /dev/null; then
|
|
||||||
log::fatal 'npm could not be found, please install it first.'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_npm_root() {
|
|
||||||
if [ ! -f package.json ]; then
|
|
||||||
log::fatal 'Current directory is not a npm root. Please run the script in a npm root directory.'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_existing_modules() {
|
|
||||||
if [ -d ./node_modules ]; then
|
|
||||||
log::info 'Removing existing node modules...'
|
|
||||||
if ! rm -rf ./node_modules; then
|
|
||||||
log::fatal 'Could not remove existing node modules.'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
install_dependencies() {
|
|
||||||
log::info 'Installing dependencies...'
|
|
||||||
if ! npm install; then
|
|
||||||
log::fatal 'Failed to install dependencies.'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_package_lock_json() {
|
|
||||||
if [ -f ./package-lock.json ]; then
|
|
||||||
log::info 'Removing package-lock.json...'
|
|
||||||
if ! rm -rf ./package-lock.json; then
|
|
||||||
log::fatal 'Could not remove package-lock.json.'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
run_unit_tests() {
|
|
||||||
log::info 'Running unit tests...'
|
|
||||||
if ! npm run test:unit; then
|
|
||||||
pwd
|
|
||||||
log::fatal 'Failed to run unit tests.'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info() {
|
|
||||||
local -r message="$1"
|
|
||||||
echo "📣 ${message}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log::fatal() {
|
|
||||||
local -r message="$1"
|
|
||||||
echo "❌ ${message}" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_args() {
|
|
||||||
while getopts "n" opt; do
|
|
||||||
case ${opt} in
|
|
||||||
n)
|
|
||||||
NON_DETERMINISTIC_FLAG=1
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
echo "Invalid option: $OPTARG" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$1"
|
|
||||||
234
scripts/logo-update.js
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* ImageMagick must be installed and accessible in the system's PATH
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { resolve, join, dirname } from 'node:path';
|
||||||
|
import { stat } from 'node:fs/promises';
|
||||||
|
import { spawn } from 'node:child_process';
|
||||||
|
import { URL, fileURLToPath } from 'node:url';
|
||||||
|
import electronBuilderConfig from '../electron-builder.cjs';
|
||||||
|
|
||||||
|
class ImageAssetPaths {
|
||||||
|
constructor(currentScriptDirectory) {
|
||||||
|
const projectRoot = resolve(currentScriptDirectory, '../');
|
||||||
|
this.sourceImage = join(projectRoot, 'img/logo.svg');
|
||||||
|
this.publicDirectory = join(projectRoot, 'src/presentation/public');
|
||||||
|
this.electronBuildResourcesDirectory = electronBuilderConfig.directories.buildResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
get electronTrayIconFile() {
|
||||||
|
return join(this.publicDirectory, 'icon.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
get webFaviconFile() {
|
||||||
|
return join(this.publicDirectory, 'favicon.ico');
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `Source image: ${this.sourceImage}`
|
||||||
|
+ `\nPublic directory: ${this.publicDirectory}`
|
||||||
|
+ `\n\t Electron tray icon file: ${this.electronTrayIconFile}`
|
||||||
|
+ `\n\t Web favicon file: ${this.webFaviconFile}`
|
||||||
|
+ `\nElectron build directory: ${this.electronBuildResourcesDirectory}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const paths = new ImageAssetPaths(getCurrentScriptDirectory());
|
||||||
|
console.log(`Paths:\n\t${paths.toString().replaceAll('\n', '\n\t')}`);
|
||||||
|
const convertCommand = await findAvailableImageMagickCommand();
|
||||||
|
await generateDesktopAndTrayIcons(
|
||||||
|
paths.sourceImage,
|
||||||
|
paths.electronTrayIconFile,
|
||||||
|
convertCommand,
|
||||||
|
);
|
||||||
|
await generateWebFavicon(
|
||||||
|
paths.sourceImage,
|
||||||
|
paths.webFaviconFile,
|
||||||
|
convertCommand,
|
||||||
|
);
|
||||||
|
await generateDesktopIcons(
|
||||||
|
paths.sourceImage,
|
||||||
|
paths.electronBuildResourcesDirectory,
|
||||||
|
convertCommand,
|
||||||
|
);
|
||||||
|
console.log('🎉 (Re)created icons successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateDesktopAndTrayIcons(sourceImage, targetFile, convertCommand) {
|
||||||
|
// Reference: https://web.archive.org/web/20240502124306/https://www.electronjs.org/docs/latest/api/tray
|
||||||
|
console.log(`Updating desktop launcher and tray icon at ${targetFile}.`);
|
||||||
|
await ensureFileExists(sourceImage);
|
||||||
|
await ensureParentFolderExists(targetFile);
|
||||||
|
await convertFromSvgToPng(
|
||||||
|
convertCommand,
|
||||||
|
sourceImage,
|
||||||
|
targetFile,
|
||||||
|
'512x512',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateWebFavicon(sourceImage, faviconFilePath, convertCommand) {
|
||||||
|
console.log(`Updating favicon at ${faviconFilePath}.`);
|
||||||
|
await ensureFileExists(sourceImage);
|
||||||
|
await ensureParentFolderExists(faviconFilePath);
|
||||||
|
await convertFromSvgToIco(
|
||||||
|
convertCommand,
|
||||||
|
sourceImage,
|
||||||
|
faviconFilePath,
|
||||||
|
[16, 24, 32, 48, 64, 128, 256],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateDesktopIcons(sourceImage, electronBuildResourcesDirectory, convertCommand) {
|
||||||
|
console.log(`Creating Electron icon files to ${electronBuildResourcesDirectory}.`);
|
||||||
|
// Reference: https://web.archive.org/web/20240501103645/https://www.electron.build/icons.html
|
||||||
|
await ensureFolderExists(electronBuildResourcesDirectory);
|
||||||
|
await ensureFileExists(sourceImage);
|
||||||
|
const electronMainIconFile = join(electronBuildResourcesDirectory, 'icon.png');
|
||||||
|
await convertFromSvgToPng(
|
||||||
|
convertCommand,
|
||||||
|
sourceImage,
|
||||||
|
electronMainIconFile,
|
||||||
|
'1024x1024', // Should be at least 512x512
|
||||||
|
);
|
||||||
|
// Relying on `electron-builder`s conversion from png to ico results in pixelated look on Windows
|
||||||
|
// 10 and 11 according to tests, see:
|
||||||
|
// - https://web.archive.org/web/20240502114650/https://github.com/electron-userland/electron-builder/issues/7328
|
||||||
|
// - https://web.archive.org/web/20240502115448/https://github.com/electron-userland/electron-builder/issues/3867
|
||||||
|
const electronWindowsIconFile = join(electronBuildResourcesDirectory, 'icon.ico');
|
||||||
|
await convertFromSvgToIco(
|
||||||
|
convertCommand,
|
||||||
|
sourceImage,
|
||||||
|
electronWindowsIconFile,
|
||||||
|
[16, 24, 32, 48, 64, 128, 256],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureFileExists(filePath) {
|
||||||
|
const path = await stat(filePath);
|
||||||
|
if (!path.isFile()) {
|
||||||
|
throw new Error(`Not a file: ${filePath}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureFolderExists(folderPath) {
|
||||||
|
if (!folderPath) {
|
||||||
|
throw new Error('Path is missing');
|
||||||
|
}
|
||||||
|
const path = await stat(folderPath);
|
||||||
|
if (!path.isDirectory()) {
|
||||||
|
throw new Error(`Not a directory: ${folderPath}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureParentFolderExists(filePath) {
|
||||||
|
return ensureFolderExists(dirname(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
const BaseImageMagickConvertArguments = Object.freeze([
|
||||||
|
'-background none', // Transparent, so they do not get filled with white.
|
||||||
|
'-strip', // Strip metadata.
|
||||||
|
'-gravity Center', // Center the image when there's empty space
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function convertFromSvgToIco(
|
||||||
|
convertCommand,
|
||||||
|
inputFile,
|
||||||
|
outputFile,
|
||||||
|
sizes,
|
||||||
|
) {
|
||||||
|
await runCommand(
|
||||||
|
convertCommand,
|
||||||
|
...BaseImageMagickConvertArguments,
|
||||||
|
`-density ${Math.max(...sizes).toString()}`, // High enough for sharpness
|
||||||
|
`-define icon:auto-resize=${sizes.map((s) => s.toString()).join(',')}`, // Automatically store multiple sizes in an ico image
|
||||||
|
'-compress None',
|
||||||
|
inputFile,
|
||||||
|
outputFile,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function convertFromSvgToPng(
|
||||||
|
convertCommand,
|
||||||
|
inputFile,
|
||||||
|
outputFile,
|
||||||
|
size = undefined,
|
||||||
|
) {
|
||||||
|
await runCommand(
|
||||||
|
convertCommand,
|
||||||
|
...BaseImageMagickConvertArguments,
|
||||||
|
...(size === undefined ? [] : [
|
||||||
|
`-resize ${size}`,
|
||||||
|
`-density ${size}`, // High enough for sharpness
|
||||||
|
]),
|
||||||
|
inputFile,
|
||||||
|
outputFile,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runCommand(...args) {
|
||||||
|
const command = args.join(' ');
|
||||||
|
console.log(`Running command: ${command}`);
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const process = spawn(command, { shell: true });
|
||||||
|
process.stdout.on('data', (stdout) => {
|
||||||
|
console.log(stdout.toString());
|
||||||
|
});
|
||||||
|
process.stderr.on('data', (stderr) => {
|
||||||
|
console.error(stderr.toString());
|
||||||
|
});
|
||||||
|
process.on('error', (err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
process.on('close', (exitCode) => {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
reject(new Error(`Process exited with non-zero exit code: ${exitCode}`));
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
process.stdin.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentScriptDirectory() {
|
||||||
|
return fileURLToPath(new URL('.', import.meta.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findAvailableImageMagickCommand() {
|
||||||
|
// Reference: https://web.archive.org/web/20240502120041/https://imagemagick.org/script/convert.php
|
||||||
|
const potentialBaseCommands = [
|
||||||
|
'convert', // Legacy command, usually available on Linux/macOS installations
|
||||||
|
'magick convert', // Newer command, available on Windows installations
|
||||||
|
];
|
||||||
|
for (const baseCommand of potentialBaseCommands) {
|
||||||
|
const testCommand = `${baseCommand} -version`;
|
||||||
|
try {
|
||||||
|
await runCommand(testCommand); // eslint-disable-line no-await-in-loop
|
||||||
|
console.log(`Confirmed: ImageMagick command '${baseCommand}' is available and operational.`);
|
||||||
|
return baseCommand;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`Error: The command '${baseCommand}' is not found or failed to execute. Detailed error: ${err.message}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error([
|
||||||
|
'Unable to locate any operational ImageMagick command.',
|
||||||
|
`Attempted commands were: ${potentialBaseCommands.join(', ')}.`,
|
||||||
|
'Please ensure ImageMagick is correctly installed and accessible.',
|
||||||
|
].join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
await main();
|
||||||
199
scripts/npm-install.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
Description:
|
||||||
|
This script manages NPM dependencies for a project.
|
||||||
|
It offers capabilities like doing a fresh install, retries on network errors, and other features.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
npm run install-deps [-- <options>]
|
||||||
|
node scripts/npm-install.js [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--root-directory <path>
|
||||||
|
Specifies the root directory where package.json resides
|
||||||
|
Defaults to the current working directory.
|
||||||
|
Example: npm run install-deps -- --root-directory /your/path/here
|
||||||
|
|
||||||
|
--no-errors
|
||||||
|
Ignores errors and continues the execution.
|
||||||
|
Example: npm run install-deps -- --no-errors
|
||||||
|
|
||||||
|
--ci
|
||||||
|
Uses 'npm ci' for dependency installation instead of 'npm install'.
|
||||||
|
Example: npm run install-deps -- --ci
|
||||||
|
|
||||||
|
--fresh
|
||||||
|
Removes the existing node_modules directory before installing dependencies.
|
||||||
|
Example: npm run install-deps -- --fresh
|
||||||
|
|
||||||
|
--non-deterministic
|
||||||
|
Removes package-lock.json for a non-deterministic installation.
|
||||||
|
Example: npm run install-deps -- --non-deterministic
|
||||||
|
|
||||||
|
Note:
|
||||||
|
|
||||||
|
Flags can be combined as needed.
|
||||||
|
Example: npm run install-deps -- --fresh --non-deterministic
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { exec } from 'node:child_process';
|
||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { access, rm, unlink } from 'node:fs/promises';
|
||||||
|
import { constants } from 'node:fs';
|
||||||
|
|
||||||
|
const MAX_RETRIES = 5;
|
||||||
|
const RETRY_DELAY_IN_MS = 5 /* seconds */ * 1000;
|
||||||
|
const ARG_NAMES = {
|
||||||
|
rootDirectory: '--root-directory',
|
||||||
|
ignoreErrors: '--no-errors',
|
||||||
|
ci: '--ci',
|
||||||
|
fresh: '--fresh',
|
||||||
|
nonDeterministic: '--non-deterministic',
|
||||||
|
};
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const options = getOptions();
|
||||||
|
console.log('Options:', options);
|
||||||
|
await ensureNpmRootDirectory(options.rootDirectory);
|
||||||
|
await ensureNpmIsAvailable();
|
||||||
|
if (options.fresh) {
|
||||||
|
await removeNodeModules(options.rootDirectory);
|
||||||
|
}
|
||||||
|
if (options.nonDeterministic) {
|
||||||
|
await removePackageLockJson(options.rootDirectory);
|
||||||
|
}
|
||||||
|
const command = buildCommand(options.ci, options.outputErrors);
|
||||||
|
console.log('Starting dependency installation...');
|
||||||
|
const exitCode = await executeWithRetry(
|
||||||
|
command,
|
||||||
|
options.workingDirectory,
|
||||||
|
MAX_RETRIES,
|
||||||
|
RETRY_DELAY_IN_MS,
|
||||||
|
);
|
||||||
|
if (exitCode === 0) {
|
||||||
|
console.log('🎊 Installed dependencies...');
|
||||||
|
} else {
|
||||||
|
console.error(`💀 Failed to install dependencies, exit code: ${exitCode}`);
|
||||||
|
}
|
||||||
|
process.exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeNodeModules(workingDirectory) {
|
||||||
|
const nodeModulesDirectory = resolve(workingDirectory, 'node_modules');
|
||||||
|
if (await exists('./node_modules')) {
|
||||||
|
console.log('Removing node_modules...');
|
||||||
|
await rm(nodeModulesDirectory, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removePackageLockJson(workingDirectory) {
|
||||||
|
const packageLockJsonFile = resolve(workingDirectory, 'package-lock.json');
|
||||||
|
if (await exists(packageLockJsonFile)) {
|
||||||
|
console.log('Removing package-lock.json...');
|
||||||
|
await unlink(packageLockJsonFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureNpmIsAvailable() {
|
||||||
|
const exitCode = await executeCommand('npm --version');
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
throw new Error('`npm` in not available!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureNpmRootDirectory(workingDirectory) {
|
||||||
|
const packageJsonPath = resolve(workingDirectory, 'package.json');
|
||||||
|
if (!await exists(packageJsonPath)) {
|
||||||
|
throw new Error(`Not an NPM project root: ${workingDirectory}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCommand(ci, outputErrors) {
|
||||||
|
const baseCommand = ci ? 'npm ci' : 'npm install';
|
||||||
|
if (!outputErrors) {
|
||||||
|
return `${baseCommand} --loglevel=error`;
|
||||||
|
}
|
||||||
|
return baseCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOptions() {
|
||||||
|
const processArgs = process.argv.slice(2); // Slice off the node and script name
|
||||||
|
return {
|
||||||
|
rootDirectory: processArgs.includes('--root-directory') ? processArgs[processArgs.indexOf('--root-directory') + 1] : process.cwd(),
|
||||||
|
outputErrors: !processArgs.includes(ARG_NAMES.ignoreErrors),
|
||||||
|
ci: processArgs.includes(ARG_NAMES.ci),
|
||||||
|
fresh: processArgs.includes(ARG_NAMES.fresh),
|
||||||
|
nonDeterministic: processArgs.includes(ARG_NAMES.nonDeterministic),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function executeWithRetry(
|
||||||
|
command,
|
||||||
|
workingDirectory,
|
||||||
|
maxRetries,
|
||||||
|
retryDelayInMs,
|
||||||
|
currentAttempt = 1,
|
||||||
|
) {
|
||||||
|
const statusCode = await executeCommand(command, workingDirectory, true, true);
|
||||||
|
if (statusCode === 0 || currentAttempt >= maxRetries) {
|
||||||
|
return statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`⚠️🔄 Attempt ${currentAttempt} failed. Retrying in ${retryDelayInMs / 1000} seconds...`);
|
||||||
|
await sleep(retryDelayInMs);
|
||||||
|
|
||||||
|
const retryResult = await executeWithRetry(
|
||||||
|
command,
|
||||||
|
workingDirectory,
|
||||||
|
maxRetries,
|
||||||
|
retryDelayInMs,
|
||||||
|
currentAttempt + 1,
|
||||||
|
);
|
||||||
|
return retryResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function executeCommand(
|
||||||
|
command,
|
||||||
|
workingDirectory = process.cwd(),
|
||||||
|
logStdout = false,
|
||||||
|
logCommand = false,
|
||||||
|
) {
|
||||||
|
if (logCommand) {
|
||||||
|
console.log(`▶️ Executing command "${command}" at "${workingDirectory}"`);
|
||||||
|
}
|
||||||
|
const process = exec(
|
||||||
|
command,
|
||||||
|
{
|
||||||
|
cwd: workingDirectory,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (logStdout) {
|
||||||
|
process.stdout.on('data', (data) => {
|
||||||
|
console.log(data.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
process.stderr.on('data', (data) => {
|
||||||
|
console.error(data.toString());
|
||||||
|
});
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
process.on('exit', (code) => {
|
||||||
|
resolve(code);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(milliseconds) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, milliseconds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function exists(path) {
|
||||||
|
try {
|
||||||
|
await access(path, constants.F_OK);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await main();
|
||||||
58
scripts/print-dist-dir.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Description:
|
||||||
|
* This script determines the absolute path of a distribution directory based on CLI arguments
|
||||||
|
* and outputs its absolute path. It is designed to be run programmatically by other scripts.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node scripts/print-dist-dir.js [options]
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* --electron-unbundled Path for the unbundled Electron application
|
||||||
|
* --electron-bundled Path for the bundled Electron application
|
||||||
|
* --web Path for the web application
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
|
||||||
|
const DIST_DIRS_JSON_FILE_PATH = resolve(process.cwd(), 'dist-dirs.json'); // cannot statically import because ESLint does not support it https://github.com/eslint/eslint/discussions/15305
|
||||||
|
const CLI_ARGUMENTS = process.argv.slice(2);
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const distDirs = await readDistDirsJsonFile(DIST_DIRS_JSON_FILE_PATH);
|
||||||
|
const relativeDistDir = determineRelativeDistDir(distDirs, CLI_ARGUMENTS);
|
||||||
|
const absoluteDistDir = resolve(process.cwd(), relativeDistDir);
|
||||||
|
console.log(absoluteDistDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapCliFlagsToDistDirs(distDirs) {
|
||||||
|
return {
|
||||||
|
'--electron-unbundled': distDirs.electronUnbundled,
|
||||||
|
'--electron-bundled': distDirs.electronBundled,
|
||||||
|
'--web': distDirs.web,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function determineRelativeDistDir(distDirsJsonObject, cliArguments) {
|
||||||
|
const cliFlagDistDirMap = mapCliFlagsToDistDirs(distDirsJsonObject);
|
||||||
|
const availableCliFlags = Object.keys(cliFlagDistDirMap);
|
||||||
|
const requestedCliFlags = cliArguments.filter((arg) => {
|
||||||
|
return availableCliFlags.includes(arg);
|
||||||
|
});
|
||||||
|
if (!requestedCliFlags.length) {
|
||||||
|
throw new Error(`No distribution directory was requested. Please use one of these flags: ${availableCliFlags.join(', ')}`);
|
||||||
|
}
|
||||||
|
if (requestedCliFlags.length > 1) {
|
||||||
|
throw new Error(`Multiple distribution directories were requested, but this script only supports one: ${requestedCliFlags.join(', ')}`);
|
||||||
|
}
|
||||||
|
const selectedCliFlag = requestedCliFlags[0];
|
||||||
|
return cliFlagDistDirMap[selectedCliFlag];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readDistDirsJsonFile(absoluteConfigJsonFilePath) {
|
||||||
|
const fileContentAsText = await readFile(absoluteConfigJsonFilePath, 'utf8');
|
||||||
|
const parsedJsonData = JSON.parse(fileContentAsText);
|
||||||
|
return parsedJsonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
await main();
|
||||||
133
scripts/verify-build-artifacts.js
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* Description:
|
||||||
|
* This script verifies the existence and content of build artifacts based on the
|
||||||
|
* provided CLI flags. It exists with exit code `0` if all verifications pass, otherwise
|
||||||
|
* with exit code `1`.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node scripts/verify-build-artifacts.js [options]
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* --electron-unbundled Verify artifacts for the unbundled Electron application.
|
||||||
|
* --electron-bundled Verify artifacts for the bundled Electron application.
|
||||||
|
* --web Verify artifacts for the web application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { access, readdir } from 'node:fs/promises';
|
||||||
|
import { exec } from 'node:child_process';
|
||||||
|
import { resolve } from 'node:path';
|
||||||
|
|
||||||
|
const PROCESS_ARGUMENTS = process.argv.slice(2);
|
||||||
|
const PRINT_DIST_DIR_SCRIPT_BASE_COMMAND = 'node scripts/print-dist-dir';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const buildConfigs = getBuildVerificationConfigs();
|
||||||
|
if (!anyCommandsFound(Object.keys(buildConfigs))) {
|
||||||
|
die(`No valid command found in process arguments. Expected one of: ${Object.keys(buildConfigs).join(', ')}`);
|
||||||
|
}
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
for (const [command, config] of Object.entries(buildConfigs)) {
|
||||||
|
if (PROCESS_ARGUMENTS.includes(command)) {
|
||||||
|
const distDir = await executePrintDistDirScript(config.printDistDirScriptArgument);
|
||||||
|
await verifyDirectoryExists(distDir);
|
||||||
|
await verifyNonEmptyDirectory(distDir);
|
||||||
|
await verifyFilesExist(distDir, config.filePatterns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* eslint-enable no-await-in-loop */
|
||||||
|
console.log('✅ Build completed successfully and all expected artifacts are in place.');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBuildVerificationConfigs() {
|
||||||
|
return {
|
||||||
|
'--electron-unbundled': {
|
||||||
|
printDistDirScriptArgument: '--electron-unbundled',
|
||||||
|
filePatterns: [
|
||||||
|
/main[/\\]index\.(cjs|mjs|js)/,
|
||||||
|
/preload[/\\]index\.(cjs|mjs|js)/,
|
||||||
|
/renderer[/\\]index\.htm(l)?/,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'--electron-bundled': {
|
||||||
|
printDistDirScriptArgument: '--electron-bundled',
|
||||||
|
filePatterns: [
|
||||||
|
/latest.*\.yml/, // generates latest.yml for auto-updates
|
||||||
|
/.*-\d+\.\d+\.\d+\..*/, // a file with extension and semantic version (packaged application)
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'--web': {
|
||||||
|
printDistDirScriptArgument: '--web',
|
||||||
|
filePatterns: [
|
||||||
|
/index\.htm(l)?/,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function anyCommandsFound(commands) {
|
||||||
|
return PROCESS_ARGUMENTS.some((arg) => commands.includes(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function verifyDirectoryExists(directoryPath) {
|
||||||
|
try {
|
||||||
|
await access(directoryPath);
|
||||||
|
} catch (error) {
|
||||||
|
die(`Directory does not exist at \`${directoryPath}\`:\n\t${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function verifyNonEmptyDirectory(directoryPath) {
|
||||||
|
const files = await readdir(directoryPath);
|
||||||
|
if (files.length === 0) {
|
||||||
|
die(`Directory is empty at \`${directoryPath}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function verifyFilesExist(directoryPath, filePatterns) {
|
||||||
|
const files = await listAllFilesRecursively(directoryPath);
|
||||||
|
for (const pattern of filePatterns) {
|
||||||
|
const match = files.some((file) => pattern.test(file));
|
||||||
|
if (!match) {
|
||||||
|
die(
|
||||||
|
`No file matches the pattern ${pattern.source} in directory \`${directoryPath}\``,
|
||||||
|
`\nFiles in directory:\n${files.map((file) => `\t- ${file}`).join('\n')}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listAllFilesRecursively(directoryPath) {
|
||||||
|
const dir = await readdir(directoryPath, { withFileTypes: true });
|
||||||
|
const files = await Promise.all(dir.map(async (dirent) => {
|
||||||
|
const absolutePath = resolve(directoryPath, dirent.name);
|
||||||
|
if (dirent.isDirectory()) {
|
||||||
|
return listAllFilesRecursively(absolutePath);
|
||||||
|
}
|
||||||
|
return absolutePath;
|
||||||
|
}));
|
||||||
|
return files.flat();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function executePrintDistDirScript(flag) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const commandToRun = `${PRINT_DIST_DIR_SCRIPT_BASE_COMMAND} ${flag}`;
|
||||||
|
|
||||||
|
exec(commandToRun, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
reject(new Error(`Execution failed with error: ${error}`));
|
||||||
|
} else if (stderr) {
|
||||||
|
reject(new Error(`Execution failed with stderr: ${stderr}`));
|
||||||
|
} else {
|
||||||
|
resolve(stdout.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function die(...message) {
|
||||||
|
console.error(...message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await main();
|
||||||
87
scripts/verify-web-server-status.js
Normal file
@@ -0,0 +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.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node ./scripts/verify-web-server-status.js --url [URL] [--max-retries NUMBER]
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* --url URL of the server to check
|
||||||
|
* --max-retries Maximum number of retry attempts (default: 30)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DEFAULT_MAX_RETRIES = 30;
|
||||||
|
const RETRY_DELAY_IN_SECONDS = 3;
|
||||||
|
const PARAMETER_NAME_URL = '--url';
|
||||||
|
const PARAMETER_NAME_MAX_RETRIES = '--max-retries';
|
||||||
|
|
||||||
|
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 {
|
||||||
|
exitWithError(`Server returned unexpected HTTP status code ${response.statusCode}.`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error making the request:', error);
|
||||||
|
scheduleNextRetry(maxRetries, currentRetryCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleNextRetry(maxRetries, currentRetryCount) {
|
||||||
|
console.log(`Attempt ${currentRetryCount}/${maxRetries}:`);
|
||||||
|
console.log(`Retrying in ${RETRY_DELAY_IN_SECONDS} seconds.`);
|
||||||
|
|
||||||
|
const remainingTime = (maxRetries - currentRetryCount) * RETRY_DELAY_IN_SECONDS;
|
||||||
|
console.log(`Time remaining before timeout: ${remainingTime}s`);
|
||||||
|
|
||||||
|
if (currentRetryCount < maxRetries) {
|
||||||
|
setTimeout(() => checkServer(currentRetryCount + 1), RETRY_DELAY_IN_SECONDS * 1000);
|
||||||
|
} else {
|
||||||
|
exitWithError('The server at did not return HTTP 200 within the allocated time.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readRequiredParameterValue(parameterName) {
|
||||||
|
const parameterValue = readOptionalParameterValue(parameterName);
|
||||||
|
if (parameterValue === undefined) {
|
||||||
|
exitWithError(`Parameter "${parameterName}" is required but not provided.`);
|
||||||
|
}
|
||||||
|
return parameterValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
48
src/TypeHelpers.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
export type Constructible<T, TArgs extends unknown[] = never> = {
|
||||||
|
prototype: T;
|
||||||
|
apply: (this: unknown, args: TArgs) => void;
|
||||||
|
readonly name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PropertyKeys<T> = {
|
||||||
|
[K in keyof T]: T[K] extends (...args: unknown[]) => unknown ? never : K;
|
||||||
|
}[keyof T];
|
||||||
|
|
||||||
|
export type ConstructorArguments<T> =
|
||||||
|
T extends new (...args: infer U) => unknown ? U : never;
|
||||||
|
|
||||||
|
export type FunctionKeys<T> = {
|
||||||
|
[K in keyof T]: T[K] extends (...args: unknown[]) => unknown ? K : never;
|
||||||
|
}[keyof T];
|
||||||
|
|
||||||
|
export function isString(value: unknown): value is string {
|
||||||
|
return typeof value === 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isNumber(value: unknown): value is number {
|
||||||
|
return typeof value === 'number';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBoolean(value: unknown): value is boolean {
|
||||||
|
return typeof value === 'boolean';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isFunction(value: unknown): value is (...args: unknown[]) => unknown {
|
||||||
|
return typeof value === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isArray(value: unknown): value is Array<unknown> {
|
||||||
|
return Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPlainObject(
|
||||||
|
variable: unknown,
|
||||||
|
): variable is object & Record<string, unknown> {
|
||||||
|
return Boolean(variable) // the data type of null is an object
|
||||||
|
&& typeof variable === 'object'
|
||||||
|
&& !Array.isArray(variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isNullOrUndefined(value: unknown): value is (null | undefined) {
|
||||||
|
return typeof value === 'undefined' || value === null;
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { IApplication } from '@/domain/IApplication';
|
import type { IApplication } from '@/domain/IApplication';
|
||||||
import { AsyncLazy } from '@/infrastructure/Threading/AsyncLazy';
|
import { AsyncLazy } from '@/infrastructure/Threading/AsyncLazy';
|
||||||
import { IApplicationFactory } from './IApplicationFactory';
|
|
||||||
import { parseApplication } from './Parser/ApplicationParser';
|
import { parseApplication } from './Parser/ApplicationParser';
|
||||||
|
import type { IApplicationFactory } from './IApplicationFactory';
|
||||||
|
|
||||||
export type ApplicationGetterType = () => IApplication;
|
export type ApplicationGetterType = () => IApplication;
|
||||||
const ApplicationGetter: ApplicationGetterType = parseApplication;
|
const ApplicationGetter: ApplicationGetterType = parseApplication;
|
||||||
@@ -12,9 +12,6 @@ export class ApplicationFactory implements IApplicationFactory {
|
|||||||
private readonly getter: AsyncLazy<IApplication>;
|
private readonly getter: AsyncLazy<IApplication>;
|
||||||
|
|
||||||
protected constructor(costlyGetter: ApplicationGetterType) {
|
protected constructor(costlyGetter: ApplicationGetterType) {
|
||||||
if (!costlyGetter) {
|
|
||||||
throw new Error('missing getter');
|
|
||||||
}
|
|
||||||
this.getter = new AsyncLazy<IApplication>(() => Promise.resolve(costlyGetter()));
|
this.getter = new AsyncLazy<IApplication>(() => Promise.resolve(costlyGetter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
src/application/CodeRunner/CodeRunner.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
export interface CodeRunner {
|
||||||
|
runCode(
|
||||||
|
code: string,
|
||||||
|
fileExtension: string,
|
||||||
|
): Promise<CodeRunOutcome>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CodeRunOutcome = SuccessfulCodeRun | FailedCodeRun;
|
||||||
|
|
||||||
|
export type CodeRunErrorType =
|
||||||
|
| 'FileWriteError'
|
||||||
|
| 'FileReadbackVerificationError'
|
||||||
|
| 'FilePathGenerationError'
|
||||||
|
| 'UnsupportedPlatform'
|
||||||
|
| 'DirectoryCreationError'
|
||||||
|
| 'FilePermissionChangeError'
|
||||||
|
| 'FileExecutionError'
|
||||||
|
| 'ExternalProcessTermination';
|
||||||
|
|
||||||
|
interface CodeRunStatus {
|
||||||
|
readonly success: boolean;
|
||||||
|
readonly error?: CodeRunError;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SuccessfulCodeRun extends CodeRunStatus {
|
||||||
|
readonly success: true;
|
||||||
|
readonly error?: undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FailedCodeRun extends CodeRunStatus {
|
||||||
|
readonly success: false;
|
||||||
|
readonly error: CodeRunError;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CodeRunError {
|
||||||
|
readonly type: CodeRunErrorType;
|
||||||
|
readonly message: string;
|
||||||
|
}
|
||||||
1
src/application/CodeRunner/ScriptFilename.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const ScriptFilename = 'privacy-script' as const;
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
// Compares to Array<T> objects for equality, ignoring order
|
// Compares to Array<T> objects for equality, ignoring order
|
||||||
export function scrambledEqual<T>(array1: readonly T[], array2: readonly T[]) {
|
export function scrambledEqual<T>(array1: readonly T[], array2: readonly T[]) {
|
||||||
if (!array1) { throw new Error('missing first array'); }
|
|
||||||
if (!array2) { throw new Error('missing second array'); }
|
|
||||||
const sortedArray1 = sort(array1);
|
const sortedArray1 = sort(array1);
|
||||||
const sortedArray2 = sort(array2);
|
const sortedArray2 = sort(array2);
|
||||||
return sequenceEqual(sortedArray1, sortedArray2);
|
return sequenceEqual(sortedArray1, sortedArray2);
|
||||||
@@ -12,8 +10,6 @@ export function scrambledEqual<T>(array1: readonly T[], array2: readonly T[]) {
|
|||||||
|
|
||||||
// Compares to Array<T> objects for equality in same order
|
// Compares to Array<T> objects for equality in same order
|
||||||
export function sequenceEqual<T>(array1: readonly T[], array2: readonly T[]) {
|
export function sequenceEqual<T>(array1: readonly T[], array2: readonly T[]) {
|
||||||
if (!array1) { throw new Error('missing first array'); }
|
|
||||||
if (!array2) { throw new Error('missing second array'); }
|
|
||||||
if (array1.length !== array2.length) {
|
if (array1.length !== array2.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/application/Common/CustomError.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { isFunction, type ConstructorArguments } from '@/TypeHelpers';
|
||||||
|
|
||||||
|
/*
|
||||||
|
Provides a unified and resilient way to extend errors across platforms.
|
||||||
|
|
||||||
|
Rationale:
|
||||||
|
- Babel:
|
||||||
|
> "Built-in classes cannot be properly subclassed due to limitations in ES5"
|
||||||
|
> https://web.archive.org/web/20230810014108/https://babeljs.io/docs/caveats#classes
|
||||||
|
- TypeScript:
|
||||||
|
> "Extending built-ins like Error, Array, and Map may no longer work"
|
||||||
|
> https://web.archive.org/web/20230810014143/https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
||||||
|
*/
|
||||||
|
export abstract class CustomError extends Error {
|
||||||
|
constructor(...args: ConstructorArguments<typeof Error>) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
fixPrototype(this, new.target.prototype);
|
||||||
|
ensureStackTrace(this);
|
||||||
|
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrorPrototypeManipulation {
|
||||||
|
getSetPrototypeOf: () => (typeof Object.setPrototypeOf | undefined);
|
||||||
|
getCaptureStackTrace: () => (typeof Error.captureStackTrace | undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlatformErrorPrototypeManipulation: ErrorPrototypeManipulation = {
|
||||||
|
getSetPrototypeOf: () => Object.setPrototypeOf,
|
||||||
|
getCaptureStackTrace: () => Error.captureStackTrace,
|
||||||
|
};
|
||||||
|
|
||||||
|
function fixPrototype(target: Error, prototype: CustomError) {
|
||||||
|
// This is recommended by TypeScript guidelines.
|
||||||
|
// Source: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
|
||||||
|
// Snapshots: https://web.archive.org/web/20231111234849/https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget, https://archive.ph/tr7cX#support-for-newtarget
|
||||||
|
const setPrototypeOf = PlatformErrorPrototypeManipulation.getSetPrototypeOf();
|
||||||
|
if (!isFunction(setPrototypeOf)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setPrototypeOf(target, prototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureStackTrace(target: Error) {
|
||||||
|
const captureStackTrace = PlatformErrorPrototypeManipulation.getCaptureStackTrace();
|
||||||
|
if (!isFunction(captureStackTrace)) {
|
||||||
|
// captureStackTrace is only available on V8, if it's not available
|
||||||
|
// modern JS engines will usually generate a stack trace on error objects when they're thrown.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
captureStackTrace(target, target.constructor);
|
||||||
|
}
|
||||||