diff --git a/.eslintignore b/.eslintignore
index 65c73659b3b..dbdaf0fe8cd 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,3 @@
/dist
-/vite-dist
+/out
/ts-dist
\ No newline at end of file
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 62ce0b3685d..5fcf2825921 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -12,7 +12,7 @@ module.exports = {
overrides: [
{
- files: ['./src/**/*.{js,cjs,mjs,jsx,ts,tsx,mts}'],
+ files: ['./src/renderer/**/*.{js,cjs,mjs,jsx,ts,tsx,mts}'],
env: {
node: false,
browser: true,
@@ -22,7 +22,13 @@ module.exports = {
},
},
{
- files: ['./script/**/*.{js,cjs,mjs,jsx,ts,tsx,mts}', 'vite.config.js'],
+ files: ['./src/preload/**/*.{js,cjs,jsx,ts,tsx}'],
+ env: {
+ browser: true,
+ },
+ },
+ {
+ files: ['./script/**/*.{js,cjs,mjs,jsx,ts,tsx,mts}', 'electron.vite.config.js'],
rules: {
'import/no-extraneous-dependencies': ['error', {
devDependencies: true,
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5b6a2b7dd8e..64733259359 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -98,7 +98,7 @@ jobs:
- name: (MacOS) Upload to Mac App Store
if: startsWith(matrix.os, 'macos') && env.is_tag == 'true'
run: |
- node script/xcrun-wrapper.mjs dist/mas-universal/LosslessCut-mac-universal.pkg ${{ secrets.api_key_id }} ${{ secrets.api_key_issuer_id }} 1505323402 no.mifi.losslesscut-mac
+ npx tsx script/xcrun-wrapper.mts dist/mas-universal/LosslessCut-mac-universal.pkg ${{ secrets.api_key_id }} ${{ secrets.api_key_issuer_id }} 1505323402 no.mifi.losslesscut-mac
- name: (MacOS) Upload artifacts
uses: actions/upload-artifact@v3
diff --git a/.gitignore b/.gitignore
index ccfeb8f620f..e6588184493 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,7 +11,7 @@ node_modules
!.yarn/versions
/dist
-/vite-dist
+/out
/icon-build
/build-resources
/doc
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5f3300c2346..37b0157b5e4 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,5 @@
{
"search.exclude": {
- "/public/locales/**": true,
+ "/src/main/locales/**": true,
}
}
\ No newline at end of file
diff --git a/README.md b/README.md
index 5d93b153521..1f3f5011c7f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-

+

LosslessCut
The swiss army knife of lossless video/audio editing
diff --git a/cli.md b/cli.md
index 42fe4d3bb1a..67ce519c861 100644
--- a/cli.md
+++ b/cli.md
@@ -26,7 +26,7 @@ LosslessCut file1.mp4 file2.mkv
```
## Override settings (experimental)
-See [available settings](https://github.com/mifi/lossless-cut/blob/master/public/configStore.js). Note that this is subject to change in newer versions. ⚠️ If you specify incorrect values it could corrupt your configuration file. You may use JSON or JSON5. Example:
+See [available settings](https://github.com/mifi/lossless-cut/blob/master/src/main/configStore.js). Note that this is subject to change in newer versions. ⚠️ If you specify incorrect values it could corrupt your configuration file. You may use JSON or JSON5. Example:
```bash
LosslessCut --settings-json '{captureFormat:"jpeg", "keyframeCut":true}'
```
diff --git a/developer-notes.md b/developer-notes.md
index 43fee72c683..1345e05258f 100644
--- a/developer-notes.md
+++ b/developer-notes.md
@@ -5,10 +5,6 @@
This app is built using Electron.
Make sure you have at least Node v16. The app uses ffmpeg from PATH when developing.
-```bash
-npm install -g yarn
-```
-
```bash
git clone https://github.com/mifi/lossless-cut.git
cd lossless-cut
diff --git a/electron.vite.config.js b/electron.vite.config.js
new file mode 100644
index 00000000000..a198c3c2f88
--- /dev/null
+++ b/electron.vite.config.js
@@ -0,0 +1,28 @@
+import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
+import react from '@vitejs/plugin-react';
+
+
+export default defineConfig({
+ main: {
+ // https://electron-vite.org/guide/dev#dependencies-vs-devdependencies
+ // For the main process and preload, the best practice is to externalize dependencies and only bundle our own code.
+ // However, until we use ESM for electron main, we need to include ESM-only deps in the bundle: (exclude from externalize)
+ plugins: [externalizeDepsPlugin({ exclude: ['p-map', 'execa', 'nanoid'] })],
+ },
+ preload: {
+ // https://electron-vite.org/guide/dev#dependencies-vs-devdependencies
+ plugins: [externalizeDepsPlugin({ exclude: [] })],
+ },
+ renderer: {
+ plugins: [react()],
+ build: {
+ chunkSizeWarningLimit: 3e6,
+ sourcemap: true,
+ },
+ server: {
+ port: 3001,
+ host: '127.0.0.1',
+ https: false,
+ },
+ },
+});
diff --git a/i18next-parser.config.mjs b/i18next-parser.config.mjs
index 4bb1dc26a87..0fb603a8477 100644
--- a/i18next-parser.config.mjs
+++ b/i18next-parser.config.mjs
@@ -1,8 +1,8 @@
// eslint-disable-line unicorn/filename-case
export default {
- input: ['src/**/*.{js,jsx,ts,tsx}', 'public/*.{js,ts}'],
+ input: ['src/renderer/**/*.{js,jsx,ts,tsx}', 'src/main/*.{js,ts}'],
- output: 'public/locales/$LOCALE/$NAMESPACE.json',
+ output: 'src/main/locales/$LOCALE/$NAMESPACE.json',
indentation: 4,
sort: true,
@@ -16,7 +16,7 @@ export default {
defaultValue: (lng, ns, key) => key,
- // Keep in sync between i18next-parser.config.js and i18n-common.js:
+ // Keep in sync between i18next-parser.config.js and i18nCommon.js:
keySeparator: false,
namespaceSeparator: false,
};
diff --git a/public/locales/cs/translation.json b/locales/cs/translation.json
similarity index 100%
rename from public/locales/cs/translation.json
rename to locales/cs/translation.json
diff --git a/public/locales/de/translation.json b/locales/de/translation.json
similarity index 100%
rename from public/locales/de/translation.json
rename to locales/de/translation.json
diff --git a/public/locales/en/translation.json b/locales/en/translation.json
similarity index 100%
rename from public/locales/en/translation.json
rename to locales/en/translation.json
diff --git a/public/locales/es/translation.json b/locales/es/translation.json
similarity index 100%
rename from public/locales/es/translation.json
rename to locales/es/translation.json
diff --git a/public/locales/et/translation.json b/locales/et/translation.json
similarity index 100%
rename from public/locales/et/translation.json
rename to locales/et/translation.json
diff --git a/public/locales/fa/translation.json b/locales/fa/translation.json
similarity index 100%
rename from public/locales/fa/translation.json
rename to locales/fa/translation.json
diff --git a/public/locales/fi/translation.json b/locales/fi/translation.json
similarity index 100%
rename from public/locales/fi/translation.json
rename to locales/fi/translation.json
diff --git a/public/locales/fr/translation.json b/locales/fr/translation.json
similarity index 100%
rename from public/locales/fr/translation.json
rename to locales/fr/translation.json
diff --git a/public/locales/he/translation.json b/locales/he/translation.json
similarity index 100%
rename from public/locales/he/translation.json
rename to locales/he/translation.json
diff --git a/public/locales/hu/translation.json b/locales/hu/translation.json
similarity index 100%
rename from public/locales/hu/translation.json
rename to locales/hu/translation.json
diff --git a/public/locales/id/translation.json b/locales/id/translation.json
similarity index 100%
rename from public/locales/id/translation.json
rename to locales/id/translation.json
diff --git a/public/locales/it/translation.json b/locales/it/translation.json
similarity index 100%
rename from public/locales/it/translation.json
rename to locales/it/translation.json
diff --git a/public/locales/ja/translation.json b/locales/ja/translation.json
similarity index 100%
rename from public/locales/ja/translation.json
rename to locales/ja/translation.json
diff --git a/public/locales/ko/translation.json b/locales/ko/translation.json
similarity index 100%
rename from public/locales/ko/translation.json
rename to locales/ko/translation.json
diff --git a/public/locales/lt/translation.json b/locales/lt/translation.json
similarity index 100%
rename from public/locales/lt/translation.json
rename to locales/lt/translation.json
diff --git a/public/locales/nb_NO/translation.json b/locales/nb_NO/translation.json
similarity index 100%
rename from public/locales/nb_NO/translation.json
rename to locales/nb_NO/translation.json
diff --git a/public/locales/nl/translation.json b/locales/nl/translation.json
similarity index 100%
rename from public/locales/nl/translation.json
rename to locales/nl/translation.json
diff --git a/public/locales/nn/translation.json b/locales/nn/translation.json
similarity index 100%
rename from public/locales/nn/translation.json
rename to locales/nn/translation.json
diff --git a/public/locales/pl/translation.json b/locales/pl/translation.json
similarity index 100%
rename from public/locales/pl/translation.json
rename to locales/pl/translation.json
diff --git a/public/locales/pt/translation.json b/locales/pt/translation.json
similarity index 100%
rename from public/locales/pt/translation.json
rename to locales/pt/translation.json
diff --git a/public/locales/pt_BR/translation.json b/locales/pt_BR/translation.json
similarity index 100%
rename from public/locales/pt_BR/translation.json
rename to locales/pt_BR/translation.json
diff --git a/public/locales/ro/translation.json b/locales/ro/translation.json
similarity index 100%
rename from public/locales/ro/translation.json
rename to locales/ro/translation.json
diff --git a/public/locales/ru/translation.json b/locales/ru/translation.json
similarity index 100%
rename from public/locales/ru/translation.json
rename to locales/ru/translation.json
diff --git a/public/locales/si/translation.json b/locales/si/translation.json
similarity index 100%
rename from public/locales/si/translation.json
rename to locales/si/translation.json
diff --git a/public/locales/sl/translation.json b/locales/sl/translation.json
similarity index 100%
rename from public/locales/sl/translation.json
rename to locales/sl/translation.json
diff --git a/public/locales/sr/translation.json b/locales/sr/translation.json
similarity index 100%
rename from public/locales/sr/translation.json
rename to locales/sr/translation.json
diff --git a/public/locales/sv/translation.json b/locales/sv/translation.json
similarity index 100%
rename from public/locales/sv/translation.json
rename to locales/sv/translation.json
diff --git a/public/locales/tr/translation.json b/locales/tr/translation.json
similarity index 100%
rename from public/locales/tr/translation.json
rename to locales/tr/translation.json
diff --git a/public/locales/uk/translation.json b/locales/uk/translation.json
similarity index 100%
rename from public/locales/uk/translation.json
rename to locales/uk/translation.json
diff --git a/public/locales/vi/translation.json b/locales/vi/translation.json
similarity index 100%
rename from public/locales/vi/translation.json
rename to locales/vi/translation.json
diff --git a/public/locales/zh_Hans/translation.json b/locales/zh_Hans/translation.json
similarity index 100%
rename from public/locales/zh_Hans/translation.json
rename to locales/zh_Hans/translation.json
diff --git a/public/locales/zh_Hant/translation.json b/locales/zh_Hant/translation.json
similarity index 100%
rename from public/locales/zh_Hant/translation.json
rename to locales/zh_Hant/translation.json
diff --git a/package.json b/package.json
index 321280d0439..de479eb5b99 100644
--- a/package.json
+++ b/package.json
@@ -4,31 +4,27 @@
"description": "The swiss army knife of lossless video/audio editing",
"copyright": "Copyright © 2021 ${author}",
"version": "3.60.0",
- "main": "public/electron.js",
+ "main": "./out/main/index.js",
"homepage": "./",
"scripts": {
- "dev": "concurrently -k \"npm run dev:frontend\" \"npm run dev:electron\"",
- "dev:frontend": "cross-env vite --port 3001",
- "dev:electron": "wait-on tcp:3001 && electron .",
- "icon-gen": "mkdirp icon-build build-resources/appx && node script/icon-gen.mjs",
+ "clean": "rimraf dist out ts-dist build-resources icon-build",
+ "start": "electron-vite preview",
+ "dev": "electron-vite dev -w",
+ "icon-gen": "mkdirp icon-build build-resources/appx && tsx script/icon-gen.mts",
"download-ffmpeg-darwin-x64": "mkdirp ffmpeg/darwin-x64 && cd ffmpeg/darwin-x64 && wget https://github.com/mifi/ffmpeg-build-script/releases/download/6.0-1/ffmpeg-macos-X64 -O ffmpeg && wget https://github.com/mifi/ffmpeg-build-script/releases/download/6.0-1/ffprobe-macos-X64 -O ffprobe && chmod +x ffmpeg && chmod +x ffprobe",
"download-ffmpeg-darwin-arm64": "mkdirp ffmpeg/darwin-arm64 && cd ffmpeg/darwin-arm64 && wget https://github.com/mifi/ffmpeg-build-script/releases/download/6.0-1/ffmpeg-macos-ARM64 -O ffmpeg && wget https://github.com/mifi/ffmpeg-build-script/releases/download/6.0-1/ffprobe-macos-ARM64 -O ffprobe && chmod +x ffmpeg && chmod +x ffprobe",
"download-ffmpeg-linux-x64": "mkdirp ffmpeg/linux-x64 && cd ffmpeg/linux-x64 && wget https://github.com/mifi/ffmpeg-builds/releases/download/6.0/ffmpeg-n6.0-12-ga6dc92968a-linux64-gpl-shared-6.0.tar.xz -O ffmpeg-ffprobe.xz && tar -xv -f ffmpeg-ffprobe.xz && mv ffmpeg-n6.0-12-ga6dc92968a-linux64-gpl-shared-6.0 extracted && mkdirp lib && mv extracted/bin/ffmpeg extracted/bin/ffprobe extracted/lib/lib*.so* lib",
"download-ffmpeg-win32-x64": "mkdirp ffmpeg/win32-x64 && cd ffmpeg/win32-x64 && npx download-cli https://github.com/mifi/ffmpeg-builds/releases/download/6.0/ffmpeg-n6.0-12-ga6dc92968a-win64-gpl-shared-6.0.zip --out . --filename ffmpeg-ffprobe.zip && 7z x ffmpeg-ffprobe.zip && mkdirp lib && cd ffmpeg-n6.0-12-ga6dc92968a-win64-gpl-shared-6.0/bin && npx shx mv ffmpeg.exe ffprobe.exe *.dll ../../lib",
- "build": "yarn icon-gen && vite build --outDir vite-dist",
+ "build": "yarn icon-gen && electron-vite build",
"tsc": "tsc --build",
"test": "vitest",
- "lint": "eslint --ext .js,.ts,.jsx,.tsx,.mjs .",
- "pack-mac": "electron-builder --mac -m dmg",
- "prepack-mac": "yarn build",
- "pack-mas-dev": "electron-builder --mac -m mas-dev -c.mas.provisioningProfile=LosslessCut_Dev.provisionprofile -c.mas.identity='Apple Development: Mikael Finstad (JH4PH8B3C8)'",
- "prepack-mas-dev": "yarn build",
- "pack-win": "electron-builder --win",
- "prepack-win": "yarn build",
+ "lint": "eslint --ext .js,.ts,.jsx,.tsx,.mjs,.mts .",
+ "pack-mac": "yarn build && electron-builder --mac -m dmg",
+ "pack-mas-dev": "yarn build && electron-builder --mac -m mas-dev -c.mas.provisioningProfile=LosslessCut_Dev.provisionprofile -c.mas.identity='Apple Development: Mikael Finstad (JH4PH8B3C8)'",
+ "pack-win": "yarn build && electron-builder --win",
"postinstall": "electron-builder install-app-deps",
- "version": "node script/postversion.mjs && git add no.mifi.losslesscut.appdata.xml",
- "pack-linux": "electron-builder --linux",
- "prepack-linux": "yarn build",
+ "version": "tsx script/postversion.mts && git add no.mifi.losslesscut.appdata.xml",
+ "pack-linux": "yarn build && electron-builder --linux",
"scan-i18n": "i18next --config i18next-parser.config.mjs",
"generate-licenses": "yarn licenses generate-disclaimer > licenses.txt && echo '\n\nffmpeg is licensed under GPL v2+:\n\nhttp://www.gnu.org/licenses/old-licenses/gpl-2.0.html' >> licenses.txt"
},
@@ -44,29 +40,36 @@
"license": "GPL-2.0-only",
"devDependencies": {
"@fontsource/open-sans": "^4.5.14",
+ "@radix-ui/colors": "^0.1.8",
"@radix-ui/react-switch": "^1.0.1",
+ "@tsconfig/node18": "^18.2.2",
"@tsconfig/strictest": "^2.0.2",
"@tsconfig/vite-react": "^3.0.0",
"@types/color": "^3.0.6",
"@types/css-modules": "^1.0.5",
"@types/eslint": "^8",
+ "@types/express": "^4.17.21",
"@types/lodash": "^4.14.202",
+ "@types/luxon": "^3.4.2",
+ "@types/morgan": "^1.9.9",
"@types/node": "18",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@types/sortablejs": "^1.15.0",
+ "@types/yargs-parser": "^21.0.3",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"@uidotdev/usehooks": "^2.4.1",
"@vitejs/plugin-react": "^3.1.0",
"color": "^3.1.0",
"concurrently": "^6.0.0",
- "cross-env": "^7.0.3",
"csv-parse": "^4.15.3",
"csv-stringify": "^5.6.2",
+ "data-uri-to-buffer": "^4.0.0",
"electron": "^27.0.0",
"electron-builder": "^24.6.4",
"electron-devtools-installer": "^3.2.0",
+ "electron-vite": "^2.1.0",
"eslint": "^8.2.0",
"eslint-config-mifi": "^0.0.3",
"eslint-plugin-import": "^2.25.3",
@@ -78,7 +81,7 @@
"fast-xml-parser": "^4.2.5",
"framer-motion": "^9.0.3",
"i18next-parser": "^7.6.0",
- "icon-gen": "^3.0.0",
+ "icon-gen": "^4.0.0",
"immer": "^10.0.2",
"ky": "^0.33.1",
"luxon": "^3.3.0",
@@ -97,6 +100,7 @@
"react-sortablejs": "^6.1.4",
"react-syntax-highlighter": "^15.4.3",
"react-use": "^17.4.0",
+ "rimraf": "^5.0.5",
"screenfull": "^6.0.2",
"scroll-into-view-if-needed": "^2.2.28",
"sharp": "^0.32.6",
@@ -105,28 +109,25 @@
"sweetalert2": "^11.0.0",
"sweetalert2-react-content": "^5.0.7",
"tiny-invariant": "^1.3.3",
+ "tsx": "^4.7.1",
"typescript": "~5.2.0",
"use-debounce": "^5.1.0",
"use-trace-update": "^1.3.0",
"vite": "^4.5.2",
- "vitest": "^1.2.2",
- "wait-on": "^7.0.1"
+ "vitest": "^1.2.2"
},
"dependencies": {
"@electron/remote": "^2.0.10",
- "@radix-ui/colors": "^0.1.8",
+ "@octokit/core": "5",
"cue-parser": "^0.3.0",
- "data-uri-to-buffer": "^4.0.0",
- "electron-is-dev": "^2.0.0",
"electron-store": "5.1.1",
"electron-unhandled": "^4.0.1",
- "execa": "5",
+ "execa": "^8.0.1",
"express": "^4.18.2",
"express-async-handler": "^1.2.0",
"file-type": "16",
"file-url": "^3.0.0",
"fs-extra": "^8.1.0",
- "github-api": "^3.2.2",
"i18next": "^22.4.10",
"i18next-fs-backend": "^2.1.1",
"json5": "^2.2.2",
@@ -134,25 +135,28 @@
"mime-types": "^2.1.14",
"morgan": "^1.10.0",
"semver": "^7.5.2",
- "string-to-stream": "^1.1.1",
+ "string-to-stream": "^3.0.1",
"winston": "^3.8.1",
- "yargs-parser": "^21.0.0"
+ "yargs-parser": "^21.1.1"
},
"build": {
"directories": {
"buildResources": "build-resources"
},
- "extraMetadata": {
- "main": "vite-dist/electron.js"
- },
"files": [
- "vite-dist/**/*"
+ "out/**/*"
],
"asar": {
"smartUnpack": false
},
"appId": "no.mifi.losslesscut",
"artifactName": "${productName}-${os}-${arch}.${ext}",
+ "extraResources": [
+ {
+ "from": "locales",
+ "to": "locales"
+ }
+ ],
"mac": {
"hardenedRuntime": true,
"appId": "no.mifi.losslesscut-mac",
diff --git a/public/constants.js b/public/constants.js
deleted file mode 100644
index 2d6dd7bb833..00000000000
--- a/public/constants.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const homepage = 'https://mifi.no/losslesscut/';
-const githubLink = 'https://github.com/mifi/lossless-cut/';
-const getReleaseUrl = (version) => `https://github.com/mifi/lossless-cut/releases/tag/v${version}`;
-const licensesPage = 'https://losslesscut.mifi.no/licenses.txt';
-
-module.exports = {
- homepage,
- getReleaseUrl,
- githubLink,
- licensesPage,
-};
diff --git a/public/util.js b/public/util.js
deleted file mode 100644
index eb11f816a34..00000000000
--- a/public/util.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const os = require('os');
-
-const frontendBuildDir = 'vite-dist';
-
-const platform = os.platform();
-const arch = os.arch();
-
-// todo dedupe between renderer and main
-const isWindows = platform === 'win32';
-const isMac = platform === 'darwin';
-const isLinux = platform === 'linux';
-
-module.exports = {
- frontendBuildDir,
- isWindows,
- isMac,
- isLinux,
- platform,
- arch,
-};
diff --git a/script/icon-gen.mjs b/script/icon-gen.mjs
deleted file mode 100644
index ba1b0d7c6a7..00000000000
--- a/script/icon-gen.mjs
+++ /dev/null
@@ -1,29 +0,0 @@
-// eslint-disable-line unicorn/filename-case
-import sharp from 'sharp';
-import icongen from 'icon-gen';
-
-const svg2png = (from, to, width, height) => sharp(from)
- .png()
- .resize(width, height, {
- fit: sharp.fit.contain,
- background: { r: 0, g: 0, b: 0, alpha: 0 },
- })
- .toFile(to);
-
-// Linux:
-await svg2png('src/icon.svg', './icon-build/app-512.png', 512, 512);
-
-// Windows Store
-await svg2png('src/icon.svg', './build-resources/appx/StoreLogo.png', 50, 50);
-await svg2png('src/icon.svg', './build-resources/appx/Square150x150Logo.png', 300, 300);
-await svg2png('src/icon.svg', './build-resources/appx/Square44x44Logo.png', 44, 44);
-await svg2png('src/icon.svg', './build-resources/appx/Wide310x150Logo.png', 620, 300);
-
-// MacOS:
-// https://github.com/mifi/lossless-cut/issues/1820
-await icongen('./src/icon-mac.svg', './icon-build', { icns: { sizes: [512, 1024] } });
-
-// Windows ICO:
-// https://github.com/mifi/lossless-cut/issues/778
-// https://stackoverflow.com/questions/3236115/which-icon-sizes-should-my-windows-applications-icon-include
-await icongen('./src/icon.svg', './icon-build', { ico: { sizes: [16, 24, 32, 40, 48, 64, 96, 128, 256, 512] } });
diff --git a/script/icon-gen.mts b/script/icon-gen.mts
new file mode 100644
index 00000000000..6064b79c28e
--- /dev/null
+++ b/script/icon-gen.mts
@@ -0,0 +1,32 @@
+// eslint-disable-line unicorn/filename-case
+import sharp from 'sharp';
+import icongenRaw from 'icon-gen';
+
+const icongen = icongenRaw as unknown as typeof icongenRaw['default'];
+
+const svg2png = (from: string, to: string, width: number, height: number) => sharp(from)
+ .png()
+ .resize(width, height, {
+ fit: sharp.fit.contain,
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
+ })
+ .toFile(to);
+
+const srcIcon = 'src/renderer/src/icon.svg';
+// Linux:
+await svg2png(srcIcon, './icon-build/app-512.png', 512, 512);
+
+// Windows Store
+await svg2png(srcIcon, './build-resources/appx/StoreLogo.png', 50, 50);
+await svg2png(srcIcon, './build-resources/appx/Square150x150Logo.png', 300, 300);
+await svg2png(srcIcon, './build-resources/appx/Square44x44Logo.png', 44, 44);
+await svg2png(srcIcon, './build-resources/appx/Wide310x150Logo.png', 620, 300);
+
+// MacOS:
+// https://github.com/mifi/lossless-cut/issues/1820
+await icongen('./src/renderer/src/icon-mac.svg', './icon-build', { icns: { sizes: [512, 1024] }, report: false });
+
+// Windows ICO:
+// https://github.com/mifi/lossless-cut/issues/778
+// https://stackoverflow.com/questions/3236115/which-icon-sizes-should-my-windows-applications-icon-include
+await icongen(srcIcon, './icon-build', { ico: { sizes: [16, 24, 32, 40, 48, 64, 96, 128, 256, 512] }, report: false });
diff --git a/script/postversion.mjs b/script/postversion.mts
similarity index 91%
rename from script/postversion.mjs
rename to script/postversion.mts
index 6d0d0b3a8fc..5c0fd4eb192 100644
--- a/script/postversion.mjs
+++ b/script/postversion.mts
@@ -1,12 +1,11 @@
import { readFile, writeFile } from 'fs/promises';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
-// eslint-disable-next-line import/no-unresolved
import { DateTime } from 'luxon';
const xmlUrl = new URL('../no.mifi.losslesscut.appdata.xml', import.meta.url);
const xmlData = await readFile(xmlUrl);
-const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)));
+const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)) as unknown as string);
const parser = new XMLParser({ alwaysCreateTextNode: true, ignoreAttributes: false, ignoreDeclaration: false });
const xml = parser.parse(xmlData);
diff --git a/script/xcrun-wrapper.mjs b/script/xcrun-wrapper.mts
similarity index 87%
rename from script/xcrun-wrapper.mjs
rename to script/xcrun-wrapper.mts
index 1c3c6e54919..0a28d7c49f8 100644
--- a/script/xcrun-wrapper.mjs
+++ b/script/xcrun-wrapper.mts
@@ -1,5 +1,5 @@
// eslint-disable-line unicorn/filename-case
-import execa from 'execa';
+import { execa } from 'execa';
import { readFile } from 'fs/promises';
// we need a wrapper script because altool tends to error out very often
@@ -17,7 +17,7 @@ const bundleId = args[4];
// seems to be the same
const ascPublicId = apiIssuer;
-const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)));
+const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)) as unknown as string);
console.log('Using version', packageJson.version);
@@ -74,8 +74,11 @@ async function runAttempt() {
console.log('stdout', stdout);
return false;
} catch (err) {
- if (err.exitCode === 1 && err.stdout) {
- const errorJson = JSON.parse(err.stdout);
+ if (err instanceof Error && 'exitCode' in err && err.exitCode === 1 && 'stdout' in err && err.stdout && typeof err.stdout === 'string') {
+ const errorJson = JSON.parse(err.stdout) as unknown;
+ if (!(errorJson != null && typeof errorJson === 'object' && 'product-errors' in errorJson && Array.isArray(errorJson['product-errors']))) {
+ throw new TypeError('Invalid JSON');
+ }
const productErrors = errorJson['product-errors'];
// Unable to authenticate
if (productErrors.some((error) => error.code === -19209)) {
diff --git a/src/isDev.ts b/src/isDev.ts
deleted file mode 100644
index b62ee03586c..00000000000
--- a/src/isDev.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-const { isDev }: { isDev: boolean } = window.require('@electron/remote').require('./electron');
-
-export default isDev;
diff --git a/public/compatPlayer.js b/src/main/compatPlayer.ts
similarity index 54%
rename from public/compatPlayer.js
rename to src/main/compatPlayer.ts
index 016d9289b13..38832651fab 100644
--- a/public/compatPlayer.js
+++ b/src/main/compatPlayer.ts
@@ -1,8 +1,12 @@
-const logger = require('./logger');
-const { createMediaSourceProcess, readOneJpegFrame } = require('./ffmpeg');
+import assert from 'assert';
+import logger from './logger.js';
+import { createMediaSourceProcess, readOneJpegFrame as readOneJpegFrameRaw } from './ffmpeg.js';
-function createMediaSourceStream({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps }) {
+
+export function createMediaSourceStream({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps }: {
+ path: string, videoStreamIndex?: number | undefined, audioStreamIndex?: number | undefined, seekTo: number, size?: number | undefined, fps?: number | undefined,
+}) {
const abortController = new AbortController();
logger.info('Starting preview process', { videoStreamIndex, audioStreamIndex, seekTo });
const process = createMediaSourceProcess({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps });
@@ -13,38 +17,39 @@ function createMediaSourceStream({ path, videoStreamIndex, audioStreamIndex, see
process.kill('SIGKILL');
};
- process.stdout.pause();
-
- async function readChunk() {
- return new Promise((resolve, reject) => {
- let cleanup;
-
- const onClose = () => {
- cleanup();
- resolve(null);
- };
- const onData = (chunk) => {
- process.stdout.pause();
- cleanup();
- resolve(chunk);
- };
- const onError = (err) => {
- cleanup();
- reject(err);
- };
- cleanup = () => {
- process.stdout.off('data', onData);
- process.stdout.off('error', onError);
- process.stdout.off('close', onClose);
- };
-
- process.stdout.once('data', onData);
- process.stdout.once('error', onError);
- process.stdout.once('close', onClose);
-
- process.stdout.resume();
- });
- }
+ const { stdout } = process;
+ assert(stdout != null);
+
+ stdout.pause();
+
+ const readChunk = async () => new Promise((resolve, reject) => {
+ let cleanup: () => void;
+
+ const onClose = () => {
+ cleanup();
+ resolve(null);
+ };
+ const onData = (chunk: Buffer) => {
+ stdout.pause();
+ cleanup();
+ resolve(chunk);
+ };
+ const onError = (err: Error) => {
+ cleanup();
+ reject(err);
+ };
+ cleanup = () => {
+ stdout.off('data', onData);
+ stdout.off('error', onError);
+ stdout.off('close', onClose);
+ };
+
+ stdout.once('data', onData);
+ stdout.once('error', onError);
+ stdout.once('close', onClose);
+
+ stdout.resume();
+ });
function abort() {
abortController.abort();
@@ -75,9 +80,9 @@ function createMediaSourceStream({ path, videoStreamIndex, audioStreamIndex, see
return { abort, readChunk };
}
-function readOneJpegFrameWrapper({ path, seekTo, videoStreamIndex }) {
+export function readOneJpegFrame({ path, seekTo, videoStreamIndex }: { path: string, seekTo: number, videoStreamIndex: number }) {
const abortController = new AbortController();
- const process = readOneJpegFrame({ path, seekTo, videoStreamIndex });
+ const process = readOneJpegFrameRaw({ path, seekTo, videoStreamIndex });
// eslint-disable-next-line unicorn/prefer-add-event-listener
abortController.signal.onabort = () => process.kill('SIGKILL');
@@ -99,9 +104,3 @@ function readOneJpegFrameWrapper({ path, seekTo, videoStreamIndex }) {
return { promise, abort };
}
-
-
-module.exports = {
- createMediaSourceStream,
- readOneJpegFrame: readOneJpegFrameWrapper,
-};
diff --git a/public/configStore.js b/src/main/configStore.ts
similarity index 89%
rename from public/configStore.js
rename to src/main/configStore.ts
index 6e77d67adb1..76e24a53083 100644
--- a/public/configStore.js
+++ b/src/main/configStore.ts
@@ -1,17 +1,17 @@
-const Store = require('electron-store');
+import Store from 'electron-store';
// eslint-disable-next-line import/no-extraneous-dependencies
-const electron = require('electron');
-const os = require('os');
-const { join, dirname } = require('path');
-const { pathExists } = require('fs-extra');
+import electron from 'electron';
+import { join, dirname } from 'path';
+import { pathExists } from 'fs-extra';
-const logger = require('./logger');
+import { KeyBinding, Config } from '../../types.js';
+import logger from './logger.js';
+import { isWindows } from './util.js';
const { app } = electron;
-/** @type {import('../types').KeyBinding[]} */
-const defaultKeyBindings = [
+const defaultKeyBindings: KeyBinding[] = [
{ keys: 'plus', action: 'addSegment' },
{ keys: 'space', action: 'togglePlayResetSpeed' },
{ keys: 'k', action: 'togglePlayNoResetSpeed' },
@@ -83,8 +83,7 @@ const defaultKeyBindings = [
{ keys: 'alt+down', action: 'decreaseVolume' },
];
-/** @type {import('../types').Config} */
-const defaults = {
+const defaults: Config = {
captureFormat: 'jpeg',
customOutDir: undefined,
keyframeCut: true,
@@ -145,7 +144,6 @@ const defaults = {
// For portable app: https://github.com/mifi/lossless-cut/issues/645
async function getCustomStoragePath() {
try {
- const isWindows = os.platform() === 'win32';
if (!isWindows || process.windowsStore) return undefined;
// https://github.com/mifi/lossless-cut/issues/645#issuecomment-1001363314
@@ -161,28 +159,28 @@ async function getCustomStoragePath() {
}
}
-let store;
+let store: Store;
-/** @type {import('../types').StoreGetConfig} */
-function get(key) {
+export function get
(key: T): Config[T] {
return store.get(key);
}
-/** @type {import('../types').StoreSetConfig} */
-function set(key, val) {
+export function set(key: T, val: Config[T]) {
if (val === undefined) store.delete(key);
else store.set(key, val);
}
-/** @type {import('../types').StoreResetConfig} */
-function reset(key) {
+export function reset(key: T) {
set(key, defaults[key]);
}
-async function tryCreateStore({ customStoragePath }) {
+async function tryCreateStore({ customStoragePath }: { customStoragePath: string | undefined }) {
for (let i = 0; i < 5; i += 1) {
try {
- store = new Store({ defaults, cwd: customStoragePath });
+ store = new Store({
+ defaults,
+ ...(customStoragePath != null ? { cwd: customStoragePath } : {}),
+ });
return;
} catch (err) {
// eslint-disable-next-line no-await-in-loop
@@ -194,7 +192,7 @@ async function tryCreateStore({ customStoragePath }) {
throw new Error('Timed out while creating config store');
}
-async function init() {
+export async function init() {
const customStoragePath = await getCustomStoragePath();
if (customStoragePath) logger.info('customStoragePath', customStoragePath);
@@ -214,10 +212,3 @@ async function init() {
set('cleanupChoices', { ...cleanupChoices, closeFile: true });
}
}
-
-module.exports = {
- init,
- get,
- set,
- reset,
-};
diff --git a/src/main/constants.ts b/src/main/constants.ts
new file mode 100644
index 00000000000..23c2c9f6696
--- /dev/null
+++ b/src/main/constants.ts
@@ -0,0 +1,4 @@
+export const homepage = 'https://mifi.no/losslesscut/';
+export const githubLink = 'https://github.com/mifi/lossless-cut/';
+export const getReleaseUrl = (version: string) => `https://github.com/mifi/lossless-cut/releases/tag/v${version}`;
+export const licensesPage = 'https://losslesscut.mifi.no/licenses.txt';
diff --git a/public/contextMenu.js b/src/main/contextMenu.ts
similarity index 81%
rename from public/contextMenu.js
rename to src/main/contextMenu.ts
index 6aadef5d3cf..d757085c0f5 100644
--- a/public/contextMenu.js
+++ b/src/main/contextMenu.ts
@@ -1,8 +1,8 @@
// eslint-disable-next-line import/no-extraneous-dependencies
-const { Menu } = require('electron');
+import { BrowserWindow, Menu } from 'electron';
// https://github.com/electron/electron/issues/4068#issuecomment-274159726
-module.exports = (window) => {
+export default (window: BrowserWindow) => {
const selectionMenu = Menu.buildFromTemplate([
{ role: 'copy' },
{ type: 'separator' },
@@ -23,9 +23,9 @@ module.exports = (window) => {
window.webContents.on('context-menu', (_e, props) => {
const { selectionText, isEditable } = props;
if (isEditable) {
- inputMenu.popup(window);
+ inputMenu.popup({ window });
} else if (selectionText && selectionText.trim() !== '') {
- selectionMenu.popup(window);
+ selectionMenu.popup({ window });
}
});
};
diff --git a/public/ffmpeg.js b/src/main/ffmpeg.ts
similarity index 57%
rename from public/ffmpeg.js
rename to src/main/ffmpeg.ts
index 5115681af69..3d68d7c019c 100644
--- a/public/ffmpeg.js
+++ b/src/main/ffmpeg.ts
@@ -1,53 +1,60 @@
-const { join } = require('path');
-const isDev = require('electron-is-dev');
-const readline = require('readline');
-const stringToStream = require('string-to-stream');
-const execa = require('execa');
+import { join } from 'path';
+import readline from 'readline';
+import stringToStream from 'string-to-stream';
+import { BufferEncodingOption, execa, ExecaChildProcess, Options as ExecaOptions } from 'execa';
+import assert from 'assert';
+import { Readable } from 'stream';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { app } from 'electron';
-const { platform, arch, isWindows, isMac, isLinux } = require('./util');
+import { platform, arch, isWindows, isMac, isLinux } from './util.js';
+import { CaptureFormat, Html5ifyMode, Waveform } from '../../types.js';
+import isDev from './isDev.js';
-const runningFfmpegs = new Set();
+const runningFfmpegs = new Set>();
// setInterval(() => console.log(runningFfmpegs.size), 1000);
-let customFfPath;
+let customFfPath: string | undefined;
// Note that this does not work on MAS because of sandbox restrictions
-function setCustomFfPath(path) {
+export function setCustomFfPath(path: string | undefined) {
customFfPath = path;
}
-function getFfCommandLine(cmd, args) {
+export function getFfCommandLine(cmd: string, args: readonly string[]) {
return `${cmd} ${args.map((arg) => (/[^\w-]/.test(arg) ? `'${arg}'` : arg)).join(' ')}`;
}
-function getFfPath(cmd) {
+function getFfPath(cmd: string) {
const exeName = isWindows ? `${cmd}.exe` : cmd;
if (customFfPath) return join(customFfPath, exeName);
- if (isDev) {
- const components = ['ffmpeg', `${platform}-${arch}`];
- if (isWindows || isLinux) components.push('lib');
- components.push(exeName);
- return join(...components);
+ if (app.isPackaged) {
+ return join(process.resourcesPath, exeName);
}
- return join(process.resourcesPath, exeName);
+ // local dev
+ const components = ['ffmpeg', `${platform}-${arch}`];
+ if (isWindows || isLinux) components.push('lib');
+ components.push(exeName);
+ return join(...components);
}
const getFfprobePath = () => getFfPath('ffprobe');
-const getFfmpegPath = () => getFfPath('ffmpeg');
+export const getFfmpegPath = () => getFfPath('ffmpeg');
-function abortFfmpegs() {
+export function abortFfmpegs() {
console.log('Aborting', runningFfmpegs.size, 'ffmpeg process(es)');
runningFfmpegs.forEach((process) => {
process.kill('SIGTERM', { forceKillAfterTimeout: 10000 });
});
}
-function handleProgress(process, durationIn, onProgress, customMatcher = () => undefined) {
+function handleProgress(process: { stderr: Readable | null }, durationIn: number | undefined, onProgress: (a: number) => void, customMatcher: (a: string) => void = () => undefined) {
if (!onProgress) return;
+ if (process.stderr == null) return;
onProgress(0);
const rl = readline.createInterface({ input: process.stderr });
@@ -61,20 +68,19 @@ function handleProgress(process, durationIn, onProgress, customMatcher = () => u
// eslint-disable-next-line unicorn/better-regex
if (!match) match = line.match(/(?:size|Lsize)=\s*[^\s]+\s+time=\s*([^\s]+)\s+/);
if (!match) {
- // @ts-expect-error todo
customMatcher(line);
return;
}
const timeStr = match[1];
// console.log(timeStr);
- const match2 = timeStr.match(/^(\d+):(\d+):(\d+)\.(\d+)$/);
+ const match2 = timeStr!.match(/^(\d+):(\d+):(\d+)\.(\d+)$/);
if (!match2) throw new Error(`Invalid time from ffmpeg progress ${timeStr}`);
- const h = parseInt(match2[1], 10);
- const m = parseInt(match2[2], 10);
- const s = parseInt(match2[3], 10);
- const cs = parseInt(match2[4], 10);
+ const h = parseInt(match2[1]!, 10);
+ const m = parseInt(match2[2]!, 10);
+ const s = parseInt(match2[3]!, 10);
+ const cs = parseInt(match2[4]!, 10);
const time = (((h * 60) + m) * 60 + s) + cs / 100;
// console.log(time);
@@ -93,18 +99,22 @@ function handleProgress(process, durationIn, onProgress, customMatcher = () => u
});
}
-// @ts-expect-error todo
-function getExecaOptions({ env, ...customExecaOptions } = {}) {
- const execaOptions = { ...customExecaOptions, env: { ...env } };
+function getExecaOptions({ env, ...customExecaOptions }: Omit, 'buffer'> = {}) {
+ const execaOptions: Omit, 'buffer'> = { ...customExecaOptions, encoding: 'buffer' };
// https://github.com/mifi/lossless-cut/issues/1143#issuecomment-1500883489
- if (isLinux && !isDev && !customFfPath) execaOptions.env.LD_LIBRARY_PATH = process.resourcesPath;
+ if (isLinux && !isDev && !customFfPath) {
+ return {
+ ...execaOptions,
+ env: { ...env, LD_LIBRARY_PATH: process.resourcesPath },
+ };
+ }
return execaOptions;
}
// todo collect warnings from ffmpeg output and show them after export? example: https://github.com/mifi/lossless-cut/issues/1469
-function runFfmpegProcess(args, customExecaOptions, { logCli = true } = {}) {
+function runFfmpegProcess(args: readonly string[], customExecaOptions?: Omit, 'encoding'>, additionalOptions?: { logCli?: boolean }) {
const ffmpegPath = getFfmpegPath();
- if (logCli) console.log(getFfCommandLine('ffmpeg', args));
+ if (additionalOptions?.logCli) console.log(getFfCommandLine('ffmpeg', args));
const process = execa(ffmpegPath, args, getExecaOptions(customExecaOptions));
@@ -121,23 +131,29 @@ function runFfmpegProcess(args, customExecaOptions, { logCli = true } = {}) {
return process;
}
-async function runFfmpegConcat({ ffmpegArgs, concatTxt, totalDuration, onProgress }) {
+export async function runFfmpegConcat({ ffmpegArgs, concatTxt, totalDuration, onProgress }: {
+ ffmpegArgs: string[], concatTxt: string, totalDuration: number, onProgress: (a: number) => void
+}) {
const process = runFfmpegProcess(ffmpegArgs);
handleProgress(process, totalDuration, onProgress);
+ assert(process.stdin != null);
stringToStream(concatTxt).pipe(process.stdin);
return process;
}
-async function runFfmpegWithProgress({ ffmpegArgs, duration, onProgress }) {
+export async function runFfmpegWithProgress({ ffmpegArgs, duration, onProgress }: {
+ ffmpegArgs: string[], duration: number | undefined, onProgress: (a: number) => void,
+}) {
const process = runFfmpegProcess(ffmpegArgs);
+ assert(process.stderr != null);
handleProgress(process, duration, onProgress);
return process;
}
-async function runFfprobe(args, { timeout = isDev ? 10000 : 30000 } = {}) {
+export async function runFfprobe(args: readonly string[], { timeout = isDev ? 10000 : 30000 } = {}) {
const ffprobePath = getFfprobePath();
console.log(getFfCommandLine('ffprobe', args));
const ps = execa(ffprobePath, args, getExecaOptions());
@@ -152,13 +168,14 @@ async function runFfprobe(args, { timeout = isDev ? 10000 : 30000 } = {}) {
}
}
-/** @type {(a: any) => Promise} */
-async function renderWaveformPng({ filePath, start, duration, color, streamIndex }) {
+export async function renderWaveformPng({ filePath, start, duration, color, streamIndex }: {
+ filePath: string, start: number, duration: number, color: string, streamIndex: number,
+}): Promise {
const args1 = [
'-hide_banner',
'-i', filePath,
- '-ss', start,
- '-t', duration,
+ '-ss', String(start),
+ '-t', String(duration),
'-c', 'copy',
'-vn',
'-map', `0:${streamIndex}`,
@@ -179,16 +196,18 @@ async function renderWaveformPng({ filePath, start, duration, color, streamIndex
console.log(getFfCommandLine('ffmpeg1', args1));
console.log('|', getFfCommandLine('ffmpeg2', args2));
- let ps1;
- let ps2;
+ let ps1: ExecaChildProcess | undefined;
+ let ps2: ExecaChildProcess | undefined;
try {
- ps1 = runFfmpegProcess(args1, { encoding: null, buffer: false }, { logCli: false });
- ps2 = runFfmpegProcess(args2, { encoding: null }, { logCli: false });
+ ps1 = runFfmpegProcess(args1, { buffer: false }, { logCli: false });
+ ps2 = runFfmpegProcess(args2, undefined, { logCli: false });
+ assert(ps1.stdout != null);
+ assert(ps2.stdin != null);
ps1.stdout.pipe(ps2.stdin);
const timer = setTimeout(() => {
- ps1.kill();
- ps2.kill();
+ ps1?.kill();
+ ps2?.kill();
console.warn('ffmpeg timed out');
}, 10000);
@@ -209,14 +228,14 @@ async function renderWaveformPng({ filePath, start, duration, color, streamIndex
}
}
-const getInputSeekArgs = ({ filePath, from, to }) => [
+const getInputSeekArgs = ({ filePath, from, to }: { filePath: string, from?: number | undefined, to?: number | undefined }) => [
...(from != null ? ['-ss', from.toFixed(5)] : []),
'-i', filePath,
- ...(to != null ? ['-t', (to - from).toFixed(5)] : []),
+ ...(from != null && to != null ? ['-t', (to - from).toFixed(5)] : []),
];
-function mapTimesToSegments(times) {
- const segments = [];
+export function mapTimesToSegments(times: number[]) {
+ const segments: { start: number, end: number | undefined }[] = [];
for (let i = 0; i < times.length; i += 1) {
const start = times[i];
const end = times[i + 1];
@@ -225,32 +244,35 @@ function mapTimesToSegments(times) {
return segments;
}
-const getSegmentOffset = (from) => (from != null ? from : 0);
+const getSegmentOffset = (from?: number) => (from != null ? from : 0);
-function adjustSegmentsWithOffset({ segments, from }) {
+function adjustSegmentsWithOffset({ segments, from }: { segments: { start: number, end: number | undefined }[], from?: number | undefined }) {
const offset = getSegmentOffset(from);
return segments.map(({ start, end }) => ({ start: start + offset, end: end != null ? end + offset : end }));
}
// https://stackoverflow.com/questions/35675529/using-ffmpeg-how-to-do-a-scene-change-detection-with-timecode
-async function detectSceneChanges({ filePath, minChange, onProgress, from, to }) {
+export async function detectSceneChanges({ filePath, minChange, onProgress, from, to }: {
+ filePath: string, minChange: number | string, onProgress: (p: number) => void, from: number, to: number,
+}) {
const args = [
'-hide_banner',
...getInputSeekArgs({ filePath, from, to }),
'-filter_complex', `select='gt(scene,${minChange})',metadata=print:file=-`,
'-f', 'null', '-',
];
- const process = runFfmpegProcess(args, { encoding: null, buffer: false });
+ const process = runFfmpegProcess(args, { buffer: false });
const times = [0];
handleProgress(process, to - from, onProgress);
+ assert(process.stdout != null);
const rl = readline.createInterface({ input: process.stdout });
rl.on('line', (line) => {
// eslint-disable-next-line unicorn/better-regex
const match = line.match(/^frame:\d+\s+pts:\d+\s+pts_time:([\d.]+)/);
if (!match) return;
- const time = parseFloat(match[1]);
+ const time = parseFloat(match[1]!);
// @ts-expect-error todo
if (Number.isNaN(time) || time <= times.at(-1)) return;
times.push(time);
@@ -263,89 +285,134 @@ async function detectSceneChanges({ filePath, minChange, onProgress, from, to })
return adjustSegmentsWithOffset({ segments, from });
}
-async function detectIntervals({ filePath, customArgs, onProgress, from, to, matchLineTokens }) {
+async function detectIntervals({ filePath, customArgs, onProgress, from, to, matchLineTokens }: {
+ filePath: string, customArgs: string[], onProgress: (p: number) => void, from: number, to: number, matchLineTokens: (line: string) => { start?: string | number | undefined, end?: string | number | undefined },
+}) {
const args = [
'-hide_banner',
...getInputSeekArgs({ filePath, from, to }),
...customArgs,
'-f', 'null', '-',
];
- const process = runFfmpegProcess(args, { encoding: null, buffer: false });
-
- const segments = [];
-
- function customMatcher(line) {
- const { start: startStr, end: endStr } = matchLineTokens(line);
- const start = parseFloat(startStr);
- const end = parseFloat(endStr);
- if (start == null || end == null || Number.isNaN(start) || Number.isNaN(end)) return;
- segments.push({ start, end });
+ const process = runFfmpegProcess(args, { buffer: false });
+
+ const segments: { start: number, end: number }[] = [];
+
+ function customMatcher(line: string) {
+ const { start: startRaw, end: endRaw } = matchLineTokens(line);
+ if (typeof startRaw === 'number' && typeof endRaw === 'number') {
+ if (startRaw == null || endRaw == null) return;
+ if (Number.isNaN(startRaw) || Number.isNaN(endRaw)) return;
+ segments.push({ start: startRaw, end: endRaw });
+ } else if (typeof startRaw === 'string' && typeof endRaw === 'string') {
+ if (startRaw == null || endRaw == null) return;
+ const start = parseFloat(startRaw);
+ const end = parseFloat(endRaw);
+ if (Number.isNaN(start) || Number.isNaN(end)) return;
+ segments.push({ start, end });
+ } else {
+ throw new TypeError('Invalid line match');
+ }
}
- // @ts-expect-error todo
handleProgress(process, to - from, onProgress, customMatcher);
await process;
return adjustSegmentsWithOffset({ segments, from });
}
-const mapFilterOptions = (options) => Object.entries(options).map(([key, value]) => `${key}=${value}`).join(':');
+const mapFilterOptions = (options: Record) => Object.entries(options).map(([key, value]) => `${key}=${value}`).join(':');
-async function blackDetect({ filePath, filterOptions, onProgress, from, to }) {
- function matchLineTokens(line) {
- // eslint-disable-next-line unicorn/better-regex
- const match = line.match(/^[blackdetect\s*@\s*0x[0-9a-f]+] black_start:([\d\\.]+) black_end:([\d\\.]+) black_duration:[\d\\.]+/);
- if (!match) return {};
- return {
- start: parseFloat(match[1]),
- end: parseFloat(match[2]),
- };
- }
+export async function blackDetect({ filePath, filterOptions, onProgress, from, to }: { filePath: string, filterOptions: Record, onProgress: (p: number) => void, from: number, to: number }) {
const customArgs = ['-vf', `blackdetect=${mapFilterOptions(filterOptions)}`, '-an'];
- return detectIntervals({ filePath, onProgress, from, to, matchLineTokens, customArgs });
+ return detectIntervals({
+ filePath,
+ onProgress,
+ from,
+ to,
+ matchLineTokens: (line) => {
+ // eslint-disable-next-line unicorn/better-regex
+ const match = line.match(/^[blackdetect\s*@\s*0x[0-9a-f]+] black_start:([\d\\.]+) black_end:([\d\\.]+) black_duration:[\d\\.]+/);
+ if (!match) {
+ return {
+ start: undefined,
+ end: undefined,
+ };
+ }
+ return {
+ start: match[1],
+ end: match[2],
+ };
+ },
+ customArgs,
+ });
}
-async function silenceDetect({ filePath, filterOptions, onProgress, from, to }) {
- function matchLineTokens(line) {
- // eslint-disable-next-line unicorn/better-regex
- const match = line.match(/^[silencedetect\s*@\s*0x[0-9a-f]+] silence_end: ([\d\\.]+)[|\s]+silence_duration: ([\d\\.]+)/);
- if (!match) return {};
- const end = parseFloat(match[1]);
- const silenceDuration = parseFloat(match[2]);
- if (Number.isNaN(end) || Number.isNaN(silenceDuration)) return {};
- const start = end - silenceDuration;
- if (start < 0 || end <= 0 || start >= end) return {};
- return {
- start,
- end,
- };
- }
- const customArgs = ['-af', `silencedetect=${mapFilterOptions(filterOptions)}`, '-vn'];
- return detectIntervals({ filePath, onProgress, from, to, matchLineTokens, customArgs });
+export async function silenceDetect({ filePath, filterOptions, onProgress, from, to }: {
+ filePath: string, filterOptions: Record, onProgress: (p: number) => void, from: number, to: number,
+}) {
+ return detectIntervals({
+ filePath,
+ onProgress,
+ from,
+ to,
+ matchLineTokens: (line) => {
+ // eslint-disable-next-line unicorn/better-regex
+ const match = line.match(/^[silencedetect\s*@\s*0x[0-9a-f]+] silence_end: ([\d\\.]+)[|\s]+silence_duration: ([\d\\.]+)/);
+ if (!match) {
+ return {
+ start: undefined,
+ end: undefined,
+ };
+ }
+ const end = parseFloat(match[1]!);
+ const silenceDuration = parseFloat(match[2]!);
+ if (Number.isNaN(end) || Number.isNaN(silenceDuration)) {
+ return {
+ start: undefined,
+ end: undefined,
+ };
+ }
+ const start = end - silenceDuration;
+ if (start < 0 || end <= 0 || start >= end) {
+ return {
+ start: undefined,
+ end: undefined,
+ };
+ }
+ return {
+ start,
+ end,
+ };
+ },
+ customArgs: ['-af', `silencedetect=${mapFilterOptions(filterOptions)}`, '-vn'],
+ });
}
-function getFffmpegJpegQuality(quality) {
+function getFffmpegJpegQuality(quality: number) {
// Normal range for JPEG is 2-31 with 31 being the worst quality.
const qMin = 2;
const qMax = 31;
return Math.min(Math.max(qMin, quality, Math.round((1 - quality) * (qMax - qMin) + qMin)), qMax);
}
-function getQualityOpts({ captureFormat, quality }) {
- if (captureFormat === 'jpeg') return ['-q:v', getFffmpegJpegQuality(quality)];
- if (captureFormat === 'webp') return ['-q:v', Math.max(0, Math.min(100, Math.round(quality * 100)))];
+function getQualityOpts({ captureFormat, quality }: { captureFormat: CaptureFormat, quality: number }) {
+ if (captureFormat === 'jpeg') return ['-q:v', String(getFffmpegJpegQuality(quality))];
+ if (captureFormat === 'webp') return ['-q:v', String(Math.max(0, Math.min(100, Math.round(quality * 100))))];
return [];
}
-function getCodecOpts(captureFormat) {
+function getCodecOpts(captureFormat: CaptureFormat) {
if (captureFormat === 'webp') return ['-c:v', 'libwebp']; // else we get only a single file for webp https://github.com/mifi/lossless-cut/issues/1693
return [];
}
-async function captureFrames({ from, to, videoPath, outPathTemplate, quality, filter, framePts, onProgress, captureFormat }) {
+export async function captureFrames({ from, to, videoPath, outPathTemplate, quality, filter, framePts, onProgress, captureFormat }: {
+ from: number, to: number, videoPath: string, outPathTemplate: string, quality: number, filter?: string | undefined, framePts?: boolean | undefined, onProgress: (p: number) => void, captureFormat: CaptureFormat,
+}) {
const args = [
- '-ss', from,
+ '-ss', String(from),
'-i', videoPath,
- '-t', Math.max(0, to - from),
+ '-t', String(Math.max(0, to - from)),
...getQualityOpts({ captureFormat, quality }),
...(filter != null ? ['-vf', filter] : []),
// https://superuser.com/questions/1336285/use-ffmpeg-for-thumbnail-selections
@@ -356,39 +423,43 @@ async function captureFrames({ from, to, videoPath, outPathTemplate, quality, fi
'-y', outPathTemplate,
];
- const process = runFfmpegProcess(args, { encoding: null, buffer: false });
+ const process = runFfmpegProcess(args, { buffer: false });
handleProgress(process, to - from, onProgress);
await process;
}
-async function captureFrame({ timestamp, videoPath, outPath, quality }) {
+export async function captureFrame({ timestamp, videoPath, outPath, quality }: {
+ timestamp: number, videoPath: string, outPath: string, quality: number,
+}) {
const ffmpegQuality = getFffmpegJpegQuality(quality);
await runFfmpegProcess([
- '-ss', timestamp,
+ '-ss', String(timestamp),
'-i', videoPath,
'-vframes', '1',
- '-q:v', ffmpegQuality,
+ '-q:v', String(ffmpegQuality),
'-y', outPath,
]);
}
-async function readFormatData(filePath) {
+async function readFormatData(filePath: string) {
console.log('readFormatData', filePath);
const { stdout } = await runFfprobe([
'-of', 'json', '-show_format', '-i', filePath, '-hide_banner',
]);
- return JSON.parse(stdout).format;
+ return JSON.parse(stdout as unknown as string).format;
}
-async function getDuration(filePath) {
+export async function getDuration(filePath: string) {
return parseFloat((await readFormatData(filePath)).duration);
}
-async function html5ify({ outPath, filePath: filePathArg, speed, hasAudio, hasVideo, onProgress }) {
+export async function html5ify({ outPath, filePath: filePathArg, speed, hasAudio, hasVideo, onProgress }: {
+ outPath: string, filePath: string, speed: Html5ifyMode, hasAudio: boolean, hasVideo: boolean, onProgress: (p: number) => void,
+}) {
let audio;
if (hasAudio) {
if (speed === 'slowest') audio = 'hq';
@@ -492,14 +563,14 @@ async function html5ify({ outPath, filePath: filePathArg, speed, hasAudio, hasVi
if (duration) handleProgress(process, duration, onProgress);
const { stdout } = await process;
- console.log(stdout);
+ console.log(stdout.toString('utf8'));
}
-function readOneJpegFrame({ path, seekTo, videoStreamIndex }) {
+export function readOneJpegFrame({ path, seekTo, videoStreamIndex }: { path: string, seekTo: number, videoStreamIndex: number }) {
const args = [
'-hide_banner', '-loglevel', 'error',
- '-ss', seekTo,
+ '-ss', String(seekTo),
'-noautorotate',
@@ -516,17 +587,19 @@ function readOneJpegFrame({ path, seekTo, videoStreamIndex }) {
// console.log(args);
- return runFfmpegProcess(args, { encoding: 'buffer' }, { logCli: true });
+ return runFfmpegProcess(args, undefined, { logCli: true });
}
const enableLog = false;
const encode = true;
-function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps }) {
+export function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps }: {
+ path: string, videoStreamIndex?: number | undefined, audioStreamIndex?: number | undefined, seekTo: number, size?: number | undefined, fps?: number | undefined,
+}) {
function getVideoFilters() {
if (videoStreamIndex == null) return [];
- const filters = [];
+ const filters: string[] = [];
if (fps != null) filters.push(`fps=${fps}`);
if (size != null) filters.push(`scale=${size}:${size}:flags=lanczos:force_original_aspect_ratio=decrease`);
if (filters.length === 0) return [];
@@ -547,7 +620,7 @@ function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIndex, se
'-vsync', 'passthrough',
- '-ss', seekTo,
+ '-ss', String(seekTo),
'-noautorotate',
@@ -582,27 +655,5 @@ function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIndex, se
return execa(getFfmpegPath(), args, { encoding: null, buffer: false, stderr: enableLog ? 'inherit' : 'pipe' });
}
-// Don't pass complex objects over the bridge
-const runFfmpeg = async (...args) => runFfmpegProcess(...args);
-
-module.exports = {
- setCustomFfPath,
- abortFfmpegs,
- getFfmpegPath,
- runFfprobe,
- runFfmpeg,
- runFfmpegConcat,
- runFfmpegWithProgress,
- renderWaveformPng,
- mapTimesToSegments,
- detectSceneChanges,
- captureFrames,
- captureFrame,
- getFfCommandLine,
- html5ify,
- getDuration,
- readOneJpegFrame,
- blackDetect,
- silenceDetect,
- createMediaSourceProcess,
-};
+// Don't pass complex objects over the bridge (process)
+export const runFfmpeg = async (...args: Parameters) => runFfmpegProcess(...args);
diff --git a/public/httpServer.js b/src/main/httpServer.ts
similarity index 68%
rename from public/httpServer.js
rename to src/main/httpServer.ts
index dcb8bd94f77..2ce4a5ea6a9 100644
--- a/public/httpServer.js
+++ b/src/main/httpServer.ts
@@ -1,14 +1,16 @@
-const express = require('express');
-const morgan = require('morgan');
-const http = require('http');
-const asyncHandler = require('express-async-handler');
-const { homepage } = require('./constants');
+import express from 'express';
+import morgan from 'morgan';
+import http from 'http';
+import asyncHandler from 'express-async-handler';
+import assert from 'assert';
+import { homepage } from './constants.js';
+import logger from './logger.js';
-const logger = require('./logger');
-
-module.exports = ({ port, onKeyboardAction }) => {
+export default ({ port, onKeyboardAction }: {
+ port: number, onKeyboardAction: (a: string) => Promise,
+}) => {
const app = express();
// https://expressjs.com/en/resources/middleware/morgan.html
@@ -25,7 +27,10 @@ module.exports = ({ port, onKeyboardAction }) => {
app.use('/api', apiRouter);
apiRouter.post('/shortcuts/:action', express.json(), asyncHandler(async (req, res) => {
- await onKeyboardAction(req.params.action);
+ // eslint-disable-next-line prefer-destructuring
+ const action = req.params['action'];
+ assert(action != null);
+ await onKeyboardAction(action);
res.end();
}));
diff --git a/public/i18n.js b/src/main/i18n.ts
similarity index 75%
rename from public/i18n.js
rename to src/main/i18n.ts
index b13c8d9170e..12417aabbe2 100644
--- a/public/i18n.js
+++ b/src/main/i18n.ts
@@ -1,12 +1,12 @@
-const i18n = require('i18next');
-const Backend = require('i18next-fs-backend');
+import i18n from 'i18next';
+import Backend from 'i18next-fs-backend';
-const { commonI18nOptions, loadPath, addPath } = require('./i18n-common');
+import { commonI18nOptions, loadPath, addPath } from './i18nCommon.js';
// See also renderer
// https://github.com/i18next/i18next/issues/869
-i18n
+export default i18n
.use(Backend)
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
@@ -23,5 +23,3 @@ i18n
addPath,
},
});
-
-module.exports = i18n;
diff --git a/public/i18n-common.js b/src/main/i18nCommon.ts
similarity index 59%
rename from public/i18n-common.js
rename to src/main/i18nCommon.ts
index ef091ce39db..3738ab1271e 100644
--- a/public/i18n-common.js
+++ b/src/main/i18nCommon.ts
@@ -1,28 +1,26 @@
-// eslint-disable-line unicorn/filename-case
// intentionally disabled because I don't know the quality of the languages, so better to default to english
// const LanguageDetector = window.require('i18next-electron-language-detector');
-const isDev = require('electron-is-dev');
// eslint-disable-next-line import/no-extraneous-dependencies
-const { app } = require('electron');
-const { join } = require('path');
+import { app } from 'electron';
+import { join } from 'path';
+import { InitOptions } from 'i18next';
-const { frontendBuildDir } = require('./util');
-let customLocalesPath;
-function setCustomLocalesPath(p) {
+let customLocalesPath: string | undefined;
+export function setCustomLocalesPath(p: string) {
customLocalesPath = p;
}
-function getLangPath(subPath) {
+function getLangPath(subPath: string) {
if (customLocalesPath != null) return join(customLocalesPath, subPath);
- if (isDev) return join('public', subPath);
- return join(app.getAppPath(), frontendBuildDir, subPath);
+ if (app.isPackaged) return join(process.resourcesPath, 'locales', subPath);
+ return join('locales', subPath);
}
// Weblate hardcodes different lang codes than electron
// https://www.electronjs.org/docs/api/app#appgetlocale
// https://source.chromium.org/chromium/chromium/src/+/master:ui/base/l10n/l10n_util.cc
-const mapLang = (lng) => ({
+const mapLang = (lng: string) => ({
nb: 'nb_NO',
no: 'nb_NO',
zh: 'zh_Hans',
@@ -39,29 +37,21 @@ const mapLang = (lng) => ({
'ru-RU': 'ru',
}[lng] || lng);
-const fallbackLng = 'en';
+export const fallbackLng = 'en';
-const commonI18nOptions = {
+export const commonI18nOptions: InitOptions = {
fallbackLng,
// debug: isDev,
// saveMissing: isDev,
// updateMissing: isDev,
// saveMissingTo: 'all',
- // Keep in sync between i18next-parser.config.js and i18n-common.js:
+ // Keep in sync between i18next-parser.config.js and i18nCommon.js:
// TODO improve keys?
// Maybe do something like this: https://stackoverflow.com/a/19405314/6519037
keySeparator: false,
nsSeparator: false,
};
-const loadPath = (lng, ns) => getLangPath(`locales/${mapLang(lng)}/${ns}.json`);
-const addPath = (lng, ns) => getLangPath(`locales/${mapLang(lng)}/${ns}.missing.json`);
-
-module.exports = {
- fallbackLng,
- loadPath,
- addPath,
- commonI18nOptions,
- setCustomLocalesPath,
-};
+export const loadPath = (lng: string, ns: string) => getLangPath(`${mapLang(lng)}/${ns}.json`);
+export const addPath = (lng: string, ns: string) => getLangPath(`${mapLang(lng)}/${ns}.missing.json`);
diff --git a/public/electron.js b/src/main/index.ts
similarity index 75%
rename from public/electron.js
rename to src/main/index.ts
index a6444b93dea..2b406cc510b 100644
--- a/public/electron.js
+++ b/src/main/index.ts
@@ -1,31 +1,55 @@
+///
process.traceDeprecation = true;
process.traceProcessWarnings = true;
+/* eslint-disable import/first */
// eslint-disable-next-line import/no-extraneous-dependencies
-const electron = require('electron');
-const isDev = require('electron-is-dev');
-const unhandled = require('electron-unhandled');
-const i18n = require('i18next');
-const debounce = require('lodash/debounce');
-const yargsParser = require('yargs-parser');
-const JSON5 = require('json5');
-const remote = require('@electron/remote/main');
-const { stat } = require('fs/promises');
+import electron, { AboutPanelOptionsOptions, BrowserWindow, BrowserWindowConstructorOptions, nativeTheme, shell, app, ipcMain } from 'electron';
+import unhandled from 'electron-unhandled';
+import i18n from 'i18next';
+import debounce from 'lodash/debounce';
+import yargsParser from 'yargs-parser';
+import JSON5 from 'json5';
+import remote from '@electron/remote/main';
+import { stat } from 'fs/promises';
+import assert from 'assert';
-const logger = require('./logger');
-const menu = require('./menu');
-const configStore = require('./configStore');
-const { frontendBuildDir, isLinux } = require('./util');
-const attachContextMenu = require('./contextMenu');
-const HttpServer = require('./httpServer');
+import logger from './logger.js';
+import menu from './menu.js';
+import * as configStore from './configStore.js';
+import { isLinux } from './util.js';
+import attachContextMenu from './contextMenu.js';
+import HttpServer from './httpServer.js';
+import isDev from './isDev.js';
-const { checkNewVersion } = require('./update-checker');
+import { checkNewVersion } from './updateChecker.js';
-const i18nCommon = require('./i18n-common');
+import * as i18nCommon from './i18nCommon.js';
-require('./i18n');
+import './i18n.js';
+import { ApiKeyboardActionRequest } from '../../types.js';
-const { app, ipcMain, shell, BrowserWindow, nativeTheme } = electron;
+export * as ffmpeg from './ffmpeg.js';
+
+export * as i18n from './i18nCommon.js';
+
+export * as compatPlayer from './compatPlayer.js';
+
+export * as configStore from './configStore.js';
+
+export { isLinux, isWindows, isMac, platform } from './util.js';
+
+
+// https://www.i18next.com/overview/typescript#argument-of-type-defaulttfuncreturn-is-not-assignable-to-parameter-of-type-xyz
+// todo This should not be necessary anymore since v23.0.0
+declare module 'i18next' {
+ interface CustomTypeOptions {
+ returnNull: false;
+ }
+}
+
+// eslint-disable-next-line unicorn/prefer-export-from
+export { isDev };
// https://chromestatus.com/feature/5748496434987008
// https://peter.sh/experiments/chromium-command-line-switches/
@@ -49,8 +73,7 @@ const isStoreBuild = process.windowsStore || process.mas;
const showVersion = !isStoreBuild;
-/** @type import('electron').AboutPanelOptionsOptions */
-const aboutPanelOptions = {
+const aboutPanelOptions: AboutPanelOptionsOptions = {
applicationName: appName,
copyright: `Copyright © ${copyrightYear} Mikael Finstad ❤️ 🇳🇴`,
version: '', // not very useful (MacOS only, and same as applicationVersion)
@@ -69,28 +92,28 @@ if (!showVersion) {
// https://www.electronjs.org/docs/latest/api/app#appsetaboutpaneloptionsoptions
app.setAboutPanelOptions(aboutPanelOptions);
-let filesToOpen = [];
+let filesToOpen: string[] = [];
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
-let mainWindow;
+let mainWindow: BrowserWindow | null;
let askBeforeClose = false;
let rendererReady = false;
-let newVersion;
-let disableNetworking;
+let newVersion: string | undefined;
+let disableNetworking: boolean;
-const openFiles = (paths) => mainWindow.webContents.send('openFiles', paths);
+const openFiles = (paths: string[]) => mainWindow!.webContents.send('openFiles', paths);
let apiKeyboardActionRequestsId = 0;
-const apiKeyboardActionRequests = new Map();
+const apiKeyboardActionRequests = new Map void>();
-async function sendApiKeyboardAction(action) {
+async function sendApiKeyboardAction(action: string) {
try {
const id = apiKeyboardActionRequestsId;
apiKeyboardActionRequestsId += 1;
- mainWindow.webContents.send('apiKeyboardAction', { id, action });
- await new Promise((resolve) => {
+ mainWindow!.webContents.send('apiKeyboardAction', { id, action } satisfies ApiKeyboardActionRequest);
+ await new Promise((resolve) => {
apiKeyboardActionRequests.set(id, resolve);
});
} catch (err) {
@@ -101,7 +124,7 @@ async function sendApiKeyboardAction(action) {
// https://github.com/electron/electron/issues/526#issuecomment-563010533
function getSizeOptions() {
const bounds = configStore.get('windowBounds');
- const options = {};
+ const options: BrowserWindowConstructorOptions = {};
if (bounds) {
const area = electron.screen.getDisplayMatching(bounds).workArea;
// If the saved position still valid (the window is entirely inside the display area), use it.
@@ -147,7 +170,7 @@ function createWindow() {
if (isDev) mainWindow.loadURL('http://localhost:3001');
// Need to useloadFile for special characters https://github.com/mifi/lossless-cut/issues/40
- else mainWindow.loadFile(`${frontendBuildDir}/index.html`);
+ else mainWindow.loadFile('out/renderer/index.html');
// Open the DevTools.
// mainWindow.webContents.openDevTools()
@@ -164,6 +187,7 @@ function createWindow() {
mainWindow.on('close', (e) => {
if (!askBeforeClose) return;
+ assert(mainWindow);
const choice = electron.dialog.showMessageBoxSync(mainWindow, {
type: 'question',
buttons: ['Yes', 'No'],
@@ -186,10 +210,11 @@ function createWindow() {
}
function updateMenu() {
+ assert(mainWindow);
menu({ app, mainWindow, newVersion, isStoreBuild });
}
-function openFilesEventually(paths) {
+function openFilesEventually(paths: string[]) {
if (rendererReady) openFiles(paths);
else filesToOpen = paths;
}
@@ -201,18 +226,18 @@ function openFilesEventually(paths) {
function parseCliArgs(rawArgv = process.argv) {
const ignoreFirstArgs = process.defaultApp ? 2 : 1;
// production: First arg is the LosslessCut executable
- // dev: First 2 args are electron and the electron.js
+ // dev: First 2 args are electron and the index.js
const argsWithoutAppName = rawArgv.length > ignoreFirstArgs ? rawArgv.slice(ignoreFirstArgs) : [];
- return yargsParser(argsWithoutAppName, { boolean: ['allow-multiple-instances', 'disable-networking'] });
+ return yargsParser(argsWithoutAppName, { boolean: ['allow-multiple-instances', 'disable-networking'], string: ['settings-json'] });
}
const argv = parseCliArgs();
-if (argv.localesPath != null) i18nCommon.setCustomLocalesPath(argv.localesPath);
+if (argv['localesPath'] != null) i18nCommon.setCustomLocalesPath(argv['localesPath']);
-function safeRequestSingleInstanceLock(additionalData) {
+function safeRequestSingleInstanceLock(additionalData: Record) {
if (process.mas) return true; // todo remove when fixed https://github.com/electron/electron/issues/35540
// using additionalData because the built in "argv" passing is a bit broken:
@@ -232,16 +257,14 @@ function initApp() {
mainWindow.focus();
}
- // @ts-expect-error todo
- if (!Array.isArray(additionalData?.argv)) return;
+ if (!(additionalData != null && typeof additionalData === 'object' && 'argv' in additionalData) || !Array.isArray(additionalData.argv)) return;
- // @ts-expect-error todo
const argv2 = parseCliArgs(additionalData.argv);
logger.info('second-instance', argv2);
- if (argv2._ && argv2._.length > 0) openFilesEventually(argv2._);
- else if (argv2.keyboardAction) sendApiKeyboardAction(argv2.keyboardAction);
+ if (argv2._ && argv2._.length > 0) openFilesEventually(argv2._.map(String));
+ else if (argv2['keyboardAction']) sendApiKeyboardAction(argv2['keyboardAction']);
});
// Quit when all windows are closed.
@@ -322,7 +345,7 @@ const readyPromise = app.whenReady();
logger.info('CLI arguments', argv);
// Only if no files to open already (open-file might have already added some files)
- if (filesToOpen.length === 0) filesToOpen = argv._;
+ if (filesToOpen.length === 0) filesToOpen = argv._.map(String);
const { settingsJson } = argv;
({ disableNetworking } = argv);
@@ -330,6 +353,7 @@ const readyPromise = app.whenReady();
if (settingsJson != null) {
logger.info('initializing settings', settingsJson);
Object.entries(JSON5.parse(settingsJson)).forEach(([key, value]) => {
+ // @ts-expect-error todo use zod?
configStore.set(key, value);
});
}
@@ -340,6 +364,7 @@ const readyPromise = app.whenReady();
const port = typeof httpApi === 'number' ? httpApi : 8080;
const { startHttpServer } = HttpServer({ port, onKeyboardAction: sendApiKeyboardAction });
await startHttpServer();
+ logger.info('HTTP API listening on port', port);
}
@@ -347,8 +372,8 @@ const readyPromise = app.whenReady();
const { default: installExtension, REACT_DEVELOPER_TOOLS } = require('electron-devtools-installer'); // eslint-disable-line global-require,import/no-extraneous-dependencies
installExtension(REACT_DEVELOPER_TOOLS)
- .then((name) => logger.info('Added Extension', name))
- .catch((err) => logger.error('Failed to add extension', err));
+ .then((name: string) => logger.info('Added Extension', name))
+ .catch((err: unknown) => logger.error('Failed to add extension', err));
}
createWindow();
@@ -366,7 +391,7 @@ const readyPromise = app.whenReady();
}
})();
-function focusWindow() {
+export function focusWindow() {
try {
app.focus({ steal: true });
} catch (err) {
@@ -374,10 +399,8 @@ function focusWindow() {
}
}
-function quitApp() {
+export function quitApp() {
electron.app.quit();
}
-const hasDisabledNetworking = () => !!disableNetworking;
-
-module.exports = { focusWindow, isDev, hasDisabledNetworking, quitApp };
+export const hasDisabledNetworking = () => !!disableNetworking;
diff --git a/src/main/isDev.ts b/src/main/isDev.ts
new file mode 100644
index 00000000000..bd7448bdbb8
--- /dev/null
+++ b/src/main/isDev.ts
@@ -0,0 +1,2 @@
+const isDev = import.meta.env.MODE === 'development';
+export default isDev;
diff --git a/public/logger.js b/src/main/logger.ts
similarity index 56%
rename from public/logger.js
rename to src/main/logger.ts
index a436abfae64..fafeab2d313 100644
--- a/public/logger.js
+++ b/src/main/logger.ts
@@ -1,15 +1,18 @@
-const winston = require('winston');
-const util = require('util');
-const isDev = require('electron-is-dev');
+import winston from 'winston';
+import util from 'util';
// eslint-disable-next-line import/no-extraneous-dependencies
-const { app } = require('electron');
-const { join } = require('path');
+import { app } from 'electron';
+import { join } from 'path';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import type { TransformableInfo } from 'logform';
+
// https://mifi.no/blog/winston-electron-logger/
// https://github.com/winstonjs/winston/issues/1427
const combineMessageAndSplat = () => ({
- transform(info) {
+ transform(info: TransformableInfo) {
+ // @ts-expect-error todo
const { [Symbol.for('splat')]: args = [], message } = info;
// eslint-disable-next-line no-param-reassign
info.message = util.format(message, ...args);
@@ -21,14 +24,14 @@ const createLogger = () => winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
combineMessageAndSplat(),
- winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`),
+ winston.format.printf((info) => `${info['timestamp']} ${info.level}: ${info.message}`),
),
});
-const logDirPath = isDev ? '.' : app.getPath('userData');
+const logDirPath = app.isPackaged ? app.getPath('userData') : '.';
const logger = createLogger();
logger.add(new winston.transports.File({ level: 'debug', filename: join(logDirPath, 'app.log'), options: { flags: 'a' } }));
-if (isDev) logger.add(new winston.transports.Console());
+if (!app.isPackaged) logger.add(new winston.transports.Console());
-module.exports = logger;
+export default logger;
diff --git a/public/menu.js b/src/main/menu.ts
similarity index 97%
rename from public/menu.js
rename to src/main/menu.ts
index 2cd15ac7c68..7dbdda7ac56 100644
--- a/public/menu.js
+++ b/src/main/menu.ts
@@ -1,16 +1,19 @@
// eslint-disable-next-line import/no-extraneous-dependencies
-const electron = require('electron');
-const { t } = require('i18next');
+import electron, { BrowserWindow } from 'electron';
+import { t } from 'i18next';
+
+import { homepage, getReleaseUrl, licensesPage } from './constants.js';
+
// menu-safe i18n.t:
// https://github.com/mifi/lossless-cut/issues/1456
-const esc = (val) => val.replaceAll('&', '&&');
+const esc = (val: string) => val.replaceAll('&', '&&');
const { Menu } = electron;
-const { homepage, getReleaseUrl, licensesPage } = require('./constants');
-
-module.exports = ({ app, mainWindow, newVersion, isStoreBuild }) => {
+export default ({ app, mainWindow, newVersion, isStoreBuild }: {
+ app: Electron.App, mainWindow: BrowserWindow, newVersion?: string | undefined, isStoreBuild: boolean,
+}) => {
const menu = [
...(process.platform === 'darwin' ? [{ role: 'appMenu' }] : []),
diff --git a/public/update-checker.js b/src/main/updateChecker.ts
similarity index 55%
rename from public/update-checker.js
rename to src/main/updateChecker.ts
index 95fe75feaf8..a761e73486e 100644
--- a/public/update-checker.js
+++ b/src/main/updateChecker.ts
@@ -1,24 +1,33 @@
-// eslint-disable-line unicorn/filename-case
-const GitHub = require('github-api');
// eslint-disable-next-line import/no-extraneous-dependencies
-const electron = require('electron');
-const semver = require('semver');
+import electron from 'electron';
+import semver from 'semver';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { Octokit } from '@octokit/core';
-const logger = require('./logger');
+import logger from './logger.js';
const { app } = electron;
-const gh = new GitHub();
-const repo = gh.getRepo('mifi', 'lossless-cut');
+const octokit = new Octokit();
+
-async function checkNewVersion() {
+// eslint-disable-next-line import/prefer-default-export
+export async function checkNewVersion() {
try {
// From API: https://developer.github.com/v3/repos/releases/#get-the-latest-release
// View the latest published full release for the repository.
// Draft releases and prereleases are not returned by this endpoint.
- const res = (await repo.getRelease('latest')).data;
- const newestVersion = res.tag_name.replace(/^v?/, '');
+
+ const { data } = await octokit.request('GET /repos/{owner}/{repo}/releases/latest', {
+ owner: 'mifi',
+ repo: 'lossless-cut',
+ headers: {
+ 'X-GitHub-Api-Version': '2022-11-28',
+ },
+ });
+
+ const newestVersion = data.tag_name.replace(/^v?/, '');
const currentVersion = app.getVersion();
// const currentVersion = '3.17.2';
@@ -34,5 +43,3 @@ async function checkNewVersion() {
return undefined;
}
}
-
-module.exports = { checkNewVersion };
diff --git a/src/main/util.ts b/src/main/util.ts
new file mode 100644
index 00000000000..75724c9560d
--- /dev/null
+++ b/src/main/util.ts
@@ -0,0 +1,8 @@
+import os from 'os';
+
+export const platform = os.platform();
+export const arch = os.arch();
+
+export const isWindows = platform === 'win32';
+export const isMac = platform === 'darwin';
+export const isLinux = platform === 'linux';
diff --git a/src/preload/index.ts b/src/preload/index.ts
new file mode 100644
index 00000000000..07d67e5ea6d
--- /dev/null
+++ b/src/preload/index.ts
@@ -0,0 +1,2 @@
+// todo
+console.log('preload');
diff --git a/index.html b/src/renderer/index.html
similarity index 100%
rename from index.html
rename to src/renderer/index.html
diff --git a/src/7077-magic-flow.json b/src/renderer/src/7077-magic-flow.json
similarity index 100%
rename from src/7077-magic-flow.json
rename to src/renderer/src/7077-magic-flow.json
diff --git a/src/App.tsx b/src/renderer/src/App.tsx
similarity index 99%
rename from src/App.tsx
rename to src/renderer/src/App.tsx
index d2eb2b89285..9b323ca7c46 100644
--- a/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -86,9 +86,9 @@ import { rightBarWidth, leftBarWidth, ffmpegExtractWindow, zoomMax } from './uti
import BigWaveform from './components/BigWaveform';
import isDev from './isDev';
-import { ChromiumHTMLVideoElement, EdlFileType, FfmpegCommandLog, FormatTimecode, Html5ifyMode, PlaybackMode, SegmentColorIndex, SegmentTags, SegmentToExport, StateSegment, Thumbnail, TunerType } from './types';
-import { CaptureFormat, KeyboardAction } from '../types';
-import { FFprobeChapter, FFprobeFormat, FFprobeStream } from '../ffprobe';
+import { ChromiumHTMLVideoElement, EdlFileType, FfmpegCommandLog, FormatTimecode, PlaybackMode, SegmentColorIndex, SegmentTags, SegmentToExport, StateSegment, Thumbnail, TunerType } from './types';
+import { CaptureFormat, KeyboardAction, Html5ifyMode } from '../../../types';
+import { FFprobeChapter, FFprobeFormat, FFprobeStream } from '../../../ffprobe';
const electron = window.require('electron');
const { exists } = window.require('fs-extra');
@@ -96,8 +96,7 @@ const { lstat } = window.require('fs/promises');
const filePathToUrl = window.require('file-url');
const { parse: parsePath, join: pathJoin, basename, dirname } = window.require('path');
-const remote = window.require('@electron/remote');
-const { focusWindow, hasDisabledNetworking, quitApp } = remote.require('./electron');
+const { focusWindow, hasDisabledNetworking, quitApp } = window.require('@electron/remote').require('./index.js');
const videoStyle: CSSProperties = { width: '100%', height: '100%', objectFit: 'contain' };
@@ -1338,8 +1337,10 @@ function App() {
return;
}
- if ('stdout' in err) console.error('stdout:', err.stdout);
- if ('stderr' in err) console.error('stderr:', err.stderr);
+ // @ts-expect-error todo
+ if ('stdout' in err && err.stdout != null) console.error('stdout:', err.stdout.toString('utf8'));
+ // @ts-expect-error todo
+ if ('stderr' in err && err.stderr != null) console.error('stderr:', err.stderr.toString('utf8'));
if (isExecaFailure(err)) {
if (isOutOfSpaceError(err)) {
diff --git a/src/BetweenSegments.tsx b/src/renderer/src/BetweenSegments.tsx
similarity index 100%
rename from src/BetweenSegments.tsx
rename to src/renderer/src/BetweenSegments.tsx
diff --git a/src/BottomBar.jsx b/src/renderer/src/BottomBar.jsx
similarity index 100%
rename from src/BottomBar.jsx
rename to src/renderer/src/BottomBar.jsx
diff --git a/src/ErrorBoundary.jsx b/src/renderer/src/ErrorBoundary.jsx
similarity index 100%
rename from src/ErrorBoundary.jsx
rename to src/renderer/src/ErrorBoundary.jsx
diff --git a/src/LastCommandsSheet.tsx b/src/renderer/src/LastCommandsSheet.tsx
similarity index 100%
rename from src/LastCommandsSheet.tsx
rename to src/renderer/src/LastCommandsSheet.tsx
diff --git a/src/MediaSourcePlayer.tsx b/src/renderer/src/MediaSourcePlayer.tsx
similarity index 97%
rename from src/MediaSourcePlayer.tsx
rename to src/renderer/src/MediaSourcePlayer.tsx
index 8f8ac3ecc82..e25402110f5 100644
--- a/src/MediaSourcePlayer.tsx
+++ b/src/renderer/src/MediaSourcePlayer.tsx
@@ -4,10 +4,9 @@ import { useDebounce } from 'use-debounce';
import isDev from './isDev';
import { ChromiumHTMLVideoElement } from './types';
-import { FFprobeStream } from '../ffprobe';
+import { FFprobeStream } from '../../../ffprobe';
-const remote = window.require('@electron/remote');
-const { createMediaSourceStream, readOneJpegFrame } = remote.require('./compatPlayer');
+const { compatPlayer: { createMediaSourceStream, readOneJpegFrame } } = window.require('@electron/remote').require('./index.js');
async function startPlayback({ path, video, videoStreamIndex, audioStreamIndex, seekTo, signal, playSafe, onCanPlay, getTargetTime, size, fps }: {
@@ -231,7 +230,7 @@ async function startPlayback({ path, video, videoStreamIndex, audioStreamIndex,
processChunk();
}
-function drawJpegFrame(canvas: HTMLCanvasElement, jpegImage: Buffer) {
+function drawJpegFrame(canvas: HTMLCanvasElement | null, jpegImage: Buffer) {
if (!canvas) return;
const ctx = canvas.getContext('2d');
@@ -248,7 +247,9 @@ function drawJpegFrame(canvas: HTMLCanvasElement, jpegImage: Buffer) {
img.src = `data:image/jpeg;base64,${jpegImage.toString('base64')}`;
}
-async function createPauseImage({ path, seekTo, videoStreamIndex, canvas, signal }) {
+async function createPauseImage({ path, seekTo, videoStreamIndex, canvas, signal }: {
+ path: string, seekTo: number, videoStreamIndex: number, canvas: HTMLCanvasElement | null, signal: AbortSignal,
+}) {
const { promise, abort } = readOneJpegFrame({ path, seekTo, videoStreamIndex });
signal.addEventListener('abort', () => abort());
const jpegImage = await promise;
diff --git a/src/NoFileLoaded.tsx b/src/renderer/src/NoFileLoaded.tsx
similarity index 100%
rename from src/NoFileLoaded.tsx
rename to src/renderer/src/NoFileLoaded.tsx
diff --git a/src/SegmentList.tsx b/src/renderer/src/SegmentList.tsx
similarity index 100%
rename from src/SegmentList.tsx
rename to src/renderer/src/SegmentList.tsx
diff --git a/src/StreamsSelector.jsx b/src/renderer/src/StreamsSelector.jsx
similarity index 100%
rename from src/StreamsSelector.jsx
rename to src/renderer/src/StreamsSelector.jsx
diff --git a/src/Timeline.tsx b/src/renderer/src/Timeline.tsx
similarity index 100%
rename from src/Timeline.tsx
rename to src/renderer/src/Timeline.tsx
diff --git a/src/TimelineSeg.tsx b/src/renderer/src/TimelineSeg.tsx
similarity index 100%
rename from src/TimelineSeg.tsx
rename to src/renderer/src/TimelineSeg.tsx
diff --git a/src/TopMenu.tsx b/src/renderer/src/TopMenu.tsx
similarity index 100%
rename from src/TopMenu.tsx
rename to src/renderer/src/TopMenu.tsx
diff --git a/src/__snapshots__/edlFormats.test.ts.snap b/src/renderer/src/__snapshots__/edlFormats.test.ts.snap
similarity index 100%
rename from src/__snapshots__/edlFormats.test.ts.snap
rename to src/renderer/src/__snapshots__/edlFormats.test.ts.snap
diff --git a/src/__snapshots__/segments.test.ts.snap b/src/renderer/src/__snapshots__/segments.test.ts.snap
similarity index 100%
rename from src/__snapshots__/segments.test.ts.snap
rename to src/renderer/src/__snapshots__/segments.test.ts.snap
diff --git a/src/animations.js b/src/renderer/src/animations.js
similarity index 100%
rename from src/animations.js
rename to src/renderer/src/animations.js
diff --git a/src/colors.js b/src/renderer/src/colors.js
similarity index 100%
rename from src/colors.js
rename to src/renderer/src/colors.js
diff --git a/src/components/AutoExportToggler.tsx b/src/renderer/src/components/AutoExportToggler.tsx
similarity index 100%
rename from src/components/AutoExportToggler.tsx
rename to src/renderer/src/components/AutoExportToggler.tsx
diff --git a/src/components/BatchFile.tsx b/src/renderer/src/components/BatchFile.tsx
similarity index 100%
rename from src/components/BatchFile.tsx
rename to src/renderer/src/components/BatchFile.tsx
diff --git a/src/components/BatchFilesList.jsx b/src/renderer/src/components/BatchFilesList.jsx
similarity index 100%
rename from src/components/BatchFilesList.jsx
rename to src/renderer/src/components/BatchFilesList.jsx
diff --git a/src/components/BigWaveform.tsx b/src/renderer/src/components/BigWaveform.tsx
similarity index 100%
rename from src/components/BigWaveform.tsx
rename to src/renderer/src/components/BigWaveform.tsx
diff --git a/src/components/Button.module.css b/src/renderer/src/components/Button.module.css
similarity index 100%
rename from src/components/Button.module.css
rename to src/renderer/src/components/Button.module.css
diff --git a/src/components/Button.tsx b/src/renderer/src/components/Button.tsx
similarity index 100%
rename from src/components/Button.tsx
rename to src/renderer/src/components/Button.tsx
diff --git a/src/components/CaptureFormatButton.tsx b/src/renderer/src/components/CaptureFormatButton.tsx
similarity index 100%
rename from src/components/CaptureFormatButton.tsx
rename to src/renderer/src/components/CaptureFormatButton.tsx
diff --git a/src/components/ConcatDialog.tsx b/src/renderer/src/components/ConcatDialog.tsx
similarity index 99%
rename from src/components/ConcatDialog.tsx
rename to src/renderer/src/components/ConcatDialog.tsx
index 06e437b550b..2f0e3bcd52a 100644
--- a/src/components/ConcatDialog.tsx
+++ b/src/renderer/src/components/ConcatDialog.tsx
@@ -14,7 +14,7 @@ import OutputFormatSelect from './OutputFormatSelect';
import useUserSettings from '../hooks/useUserSettings';
import { isMov } from '../util/streams';
import { getOutFileExtension, getSuffixedFileName } from '../util';
-import { FFprobeChapter, FFprobeFormat, FFprobeStream } from '../../ffprobe';
+import { FFprobeChapter, FFprobeFormat, FFprobeStream } from '../../../../ffprobe';
const { basename } = window.require('path');
diff --git a/src/components/CopyClipboardButton.tsx b/src/renderer/src/components/CopyClipboardButton.tsx
similarity index 100%
rename from src/components/CopyClipboardButton.tsx
rename to src/renderer/src/components/CopyClipboardButton.tsx
diff --git a/src/components/ExportButton.tsx b/src/renderer/src/components/ExportButton.tsx
similarity index 100%
rename from src/components/ExportButton.tsx
rename to src/renderer/src/components/ExportButton.tsx
diff --git a/src/components/ExportConfirm.module.css b/src/renderer/src/components/ExportConfirm.module.css
similarity index 100%
rename from src/components/ExportConfirm.module.css
rename to src/renderer/src/components/ExportConfirm.module.css
diff --git a/src/components/ExportConfirm.tsx b/src/renderer/src/components/ExportConfirm.tsx
similarity index 99%
rename from src/components/ExportConfirm.tsx
rename to src/renderer/src/components/ExportConfirm.tsx
index 991492d4293..56ef360a185 100644
--- a/src/components/ExportConfirm.tsx
+++ b/src/renderer/src/components/ExportConfirm.tsx
@@ -26,8 +26,8 @@ import useUserSettings from '../hooks/useUserSettings';
import styles from './ExportConfirm.module.css';
import { InverseCutSegment, SegmentToExport } from '../types';
import { GenerateOutSegFileNames } from '../util/outputNameTemplate';
-import { FFprobeStream } from '../../ffprobe';
-import { AvoidNegativeTs } from '../../types';
+import { FFprobeStream } from '../../../../ffprobe';
+import { AvoidNegativeTs } from '../../../../types';
const boxStyle: CSSProperties = { margin: '15px 15px 50px 15px', borderRadius: 10, padding: '10px 20px', minHeight: 500, position: 'relative' };
diff --git a/src/components/ExportModeButton.tsx b/src/renderer/src/components/ExportModeButton.tsx
similarity index 100%
rename from src/components/ExportModeButton.tsx
rename to src/renderer/src/components/ExportModeButton.tsx
diff --git a/src/components/HighlightedText.tsx b/src/renderer/src/components/HighlightedText.tsx
similarity index 100%
rename from src/components/HighlightedText.tsx
rename to src/renderer/src/components/HighlightedText.tsx
diff --git a/src/components/KeyboardShortcuts.tsx b/src/renderer/src/components/KeyboardShortcuts.tsx
similarity index 99%
rename from src/components/KeyboardShortcuts.tsx
rename to src/renderer/src/components/KeyboardShortcuts.tsx
index 34a65f24665..0071f9d5b89 100644
--- a/src/components/KeyboardShortcuts.tsx
+++ b/src/renderer/src/components/KeyboardShortcuts.tsx
@@ -12,7 +12,7 @@ import Swal from '../swal';
import SetCutpointButton from './SetCutpointButton';
import SegmentCutpointButton from './SegmentCutpointButton';
import { getModifier } from '../hooks/useTimelineScroll';
-import { KeyBinding, KeyboardAction } from '../../types';
+import { KeyBinding, KeyboardAction } from '../../../../types';
import { StateSegment } from '../types';
diff --git a/src/components/MergedOutFileName.tsx b/src/renderer/src/components/MergedOutFileName.tsx
similarity index 100%
rename from src/components/MergedOutFileName.tsx
rename to src/renderer/src/components/MergedOutFileName.tsx
diff --git a/src/components/MovFastStartButton.jsx b/src/renderer/src/components/MovFastStartButton.jsx
similarity index 100%
rename from src/components/MovFastStartButton.jsx
rename to src/renderer/src/components/MovFastStartButton.jsx
diff --git a/src/components/OutSegTemplateEditor.tsx b/src/renderer/src/components/OutSegTemplateEditor.tsx
similarity index 100%
rename from src/components/OutSegTemplateEditor.tsx
rename to src/renderer/src/components/OutSegTemplateEditor.tsx
diff --git a/src/components/OutputFormatSelect.tsx b/src/renderer/src/components/OutputFormatSelect.tsx
similarity index 100%
rename from src/components/OutputFormatSelect.tsx
rename to src/renderer/src/components/OutputFormatSelect.tsx
diff --git a/src/components/PlaybackStreamSelector.tsx b/src/renderer/src/components/PlaybackStreamSelector.tsx
similarity index 100%
rename from src/components/PlaybackStreamSelector.tsx
rename to src/renderer/src/components/PlaybackStreamSelector.tsx
diff --git a/src/components/PreserveMovDataButton.jsx b/src/renderer/src/components/PreserveMovDataButton.jsx
similarity index 100%
rename from src/components/PreserveMovDataButton.jsx
rename to src/renderer/src/components/PreserveMovDataButton.jsx
diff --git a/src/components/SegmentCutpointButton.tsx b/src/renderer/src/components/SegmentCutpointButton.tsx
similarity index 100%
rename from src/components/SegmentCutpointButton.tsx
rename to src/renderer/src/components/SegmentCutpointButton.tsx
diff --git a/src/components/Select.module.css b/src/renderer/src/components/Select.module.css
similarity index 100%
rename from src/components/Select.module.css
rename to src/renderer/src/components/Select.module.css
diff --git a/src/components/Select.tsx b/src/renderer/src/components/Select.tsx
similarity index 100%
rename from src/components/Select.tsx
rename to src/renderer/src/components/Select.tsx
diff --git a/src/components/SetCutpointButton.tsx b/src/renderer/src/components/SetCutpointButton.tsx
similarity index 100%
rename from src/components/SetCutpointButton.tsx
rename to src/renderer/src/components/SetCutpointButton.tsx
diff --git a/src/components/Settings.module.css b/src/renderer/src/components/Settings.module.css
similarity index 100%
rename from src/components/Settings.module.css
rename to src/renderer/src/components/Settings.module.css
diff --git a/src/components/Settings.tsx b/src/renderer/src/components/Settings.tsx
similarity index 99%
rename from src/components/Settings.tsx
rename to src/renderer/src/components/Settings.tsx
index eee0cbbf425..e79fd93afc9 100644
--- a/src/components/Settings.tsx
+++ b/src/renderer/src/components/Settings.tsx
@@ -11,7 +11,7 @@ import Switch from './Switch';
import useUserSettings from '../hooks/useUserSettings';
import { askForFfPath } from '../dialogs';
import { isMasBuild, isStoreBuild } from '../util';
-import { LanguageKey, TimecodeFormat, langNames } from '../../types';
+import { LanguageKey, TimecodeFormat, langNames } from '../../../../types';
import styles from './Settings.module.css';
import Select from './Select';
diff --git a/src/components/Sheet.module.css b/src/renderer/src/components/Sheet.module.css
similarity index 100%
rename from src/components/Sheet.module.css
rename to src/renderer/src/components/Sheet.module.css
diff --git a/src/components/Sheet.tsx b/src/renderer/src/components/Sheet.tsx
similarity index 100%
rename from src/components/Sheet.tsx
rename to src/renderer/src/components/Sheet.tsx
diff --git a/src/components/SimpleModeButton.tsx b/src/renderer/src/components/SimpleModeButton.tsx
similarity index 100%
rename from src/components/SimpleModeButton.tsx
rename to src/renderer/src/components/SimpleModeButton.tsx
diff --git a/src/components/Switch.module.css b/src/renderer/src/components/Switch.module.css
similarity index 100%
rename from src/components/Switch.module.css
rename to src/renderer/src/components/Switch.module.css
diff --git a/src/components/Switch.tsx b/src/renderer/src/components/Switch.tsx
similarity index 100%
rename from src/components/Switch.tsx
rename to src/renderer/src/components/Switch.tsx
diff --git a/src/components/TagEditor.jsx b/src/renderer/src/components/TagEditor.jsx
similarity index 100%
rename from src/components/TagEditor.jsx
rename to src/renderer/src/components/TagEditor.jsx
diff --git a/src/components/TextInput.tsx b/src/renderer/src/components/TextInput.tsx
similarity index 100%
rename from src/components/TextInput.tsx
rename to src/renderer/src/components/TextInput.tsx
diff --git a/src/components/ToggleExportConfirm.tsx b/src/renderer/src/components/ToggleExportConfirm.tsx
similarity index 100%
rename from src/components/ToggleExportConfirm.tsx
rename to src/renderer/src/components/ToggleExportConfirm.tsx
diff --git a/src/components/ValueTuner.tsx b/src/renderer/src/components/ValueTuner.tsx
similarity index 100%
rename from src/components/ValueTuner.tsx
rename to src/renderer/src/components/ValueTuner.tsx
diff --git a/src/components/ValueTuners.tsx b/src/renderer/src/components/ValueTuners.tsx
similarity index 95%
rename from src/components/ValueTuners.tsx
rename to src/renderer/src/components/ValueTuners.tsx
index 3e9a1e3fe78..36065597500 100644
--- a/src/components/ValueTuners.tsx
+++ b/src/renderer/src/components/ValueTuners.tsx
@@ -9,7 +9,7 @@ const ValueTuners = memo(({ type, onFinished }: { type: TunerType, onFinished: (
const { t } = useTranslation();
const { wheelSensitivity, setWheelSensitivity, keyboardNormalSeekSpeed, setKeyboardNormalSeekSpeed, keyboardSeekAccFactor, setKeyboardSeekAccFactor } = useUserSettings();
- // NOTE default values are duplicated in public/configStore.js
+ // NOTE default values are duplicated in src/main/configStore.js
const types = {
wheelSensitivity: {
title: t('Timeline trackpad/wheel sensitivity'),
diff --git a/src/components/VolumeControl.tsx b/src/renderer/src/components/VolumeControl.tsx
similarity index 100%
rename from src/components/VolumeControl.tsx
rename to src/renderer/src/components/VolumeControl.tsx
diff --git a/src/components/Working.tsx b/src/renderer/src/components/Working.tsx
similarity index 100%
rename from src/components/Working.tsx
rename to src/renderer/src/components/Working.tsx
diff --git a/src/contexts.ts b/src/renderer/src/contexts.ts
similarity index 100%
rename from src/contexts.ts
rename to src/renderer/src/contexts.ts
diff --git a/src/dialogs/extractFrames.jsx b/src/renderer/src/dialogs/extractFrames.jsx
similarity index 100%
rename from src/dialogs/extractFrames.jsx
rename to src/renderer/src/dialogs/extractFrames.jsx
diff --git a/src/dialogs/html5ify.tsx b/src/renderer/src/dialogs/html5ify.tsx
similarity index 98%
rename from src/dialogs/html5ify.tsx
rename to src/renderer/src/dialogs/html5ify.tsx
index a94243f1454..9b577c505cc 100644
--- a/src/dialogs/html5ify.tsx
+++ b/src/renderer/src/dialogs/html5ify.tsx
@@ -4,7 +4,7 @@ import i18n from 'i18next';
import withReactContent from 'sweetalert2-react-content';
import Swal from '../swal';
-import { Html5ifyMode } from '../types';
+import { Html5ifyMode } from '../../../../types';
const ReactSwal = withReactContent(Swal);
diff --git a/src/dialogs/index.tsx b/src/renderer/src/dialogs/index.tsx
similarity index 100%
rename from src/dialogs/index.tsx
rename to src/renderer/src/dialogs/index.tsx
diff --git a/src/dialogs/parameters.tsx b/src/renderer/src/dialogs/parameters.tsx
similarity index 96%
rename from src/dialogs/parameters.tsx
rename to src/renderer/src/dialogs/parameters.tsx
index 36459ba8ce5..3854dec0605 100644
--- a/src/dialogs/parameters.tsx
+++ b/src/renderer/src/dialogs/parameters.tsx
@@ -53,12 +53,11 @@ const ParametersInput = ({ description, parameters: parametersIn, onChange, onSu
);
};
-// eslint-disable-next-line import/prefer-default-export
export async function showParametersDialog({ title, description, parameters: parametersIn, docUrl }: { title?: string, description?: string, parameters: ParameterDialogParameters, docUrl?: string }) {
let parameters = parametersIn;
- let resolve1;
+ let resolve1: (value: boolean) => void;
- const promise1 = new Promise((resolve) => {
+ const promise1 = new Promise((resolve) => {
resolve1 = resolve;
});
const handleSubmit = () => {
diff --git a/src/edlFormats.test.ts b/src/renderer/src/edlFormats.test.ts
similarity index 100%
rename from src/edlFormats.test.ts
rename to src/renderer/src/edlFormats.test.ts
diff --git a/src/edlFormats.ts b/src/renderer/src/edlFormats.ts
similarity index 100%
rename from src/edlFormats.ts
rename to src/renderer/src/edlFormats.ts
diff --git a/src/edlStore.ts b/src/renderer/src/edlStore.ts
similarity index 100%
rename from src/edlStore.ts
rename to src/renderer/src/edlStore.ts
diff --git a/src/ffmpeg-parameters.js b/src/renderer/src/ffmpeg-parameters.js
similarity index 100%
rename from src/ffmpeg-parameters.js
rename to src/renderer/src/ffmpeg-parameters.js
diff --git a/src/ffmpeg.ts b/src/renderer/src/ffmpeg.ts
similarity index 95%
rename from src/ffmpeg.ts
rename to src/renderer/src/ffmpeg.ts
index 5d4bd11663e..02342205cad 100644
--- a/src/ffmpeg.ts
+++ b/src/renderer/src/ffmpeg.ts
@@ -8,16 +8,12 @@ import invariant from 'tiny-invariant';
import { pcmAudioCodecs, getMapStreamsArgs, isMov, LiteFFprobeStream } from './util/streams';
import { getSuffixedOutPath, isExecaFailure } from './util';
import { isDurationValid } from './segments';
-import { Waveform } from '../types';
-import { FFprobeChapter, FFprobeFormat, FFprobeProbeResult, FFprobeStream } from '../ffprobe';
+import { FFprobeChapter, FFprobeFormat, FFprobeProbeResult, FFprobeStream } from '../../../ffprobe';
const FileType = window.require('file-type');
const { pathExists } = window.require('fs-extra');
-const remote = window.require('@electron/remote');
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const ffmpeg: { renderWaveformPng: (a: any) => Promise, mapTimesToSegments, detectSceneChanges, captureFrames, captureFrame, getFfCommandLine, runFfmpegConcat, runFfmpegWithProgress, html5ify, getDuration, abortFfmpegs, runFfmpeg, runFfprobe, getFfmpegPath, setCustomFfPath } = remote.require('./ffmpeg');
+const { ffmpeg } = window.require('@electron/remote').require('./index.js');
const { renderWaveformPng, mapTimesToSegments, detectSceneChanges, captureFrames, captureFrame, getFfCommandLine, runFfmpegConcat, runFfmpegWithProgress, html5ify, getDuration, abortFfmpegs, runFfmpeg, runFfprobe, getFfmpegPath, setCustomFfPath } = ffmpeg;
@@ -32,14 +28,14 @@ export class RefuseOverwriteError extends Error {
}
}
-export function logStdoutStderr({ stdout, stderr }) {
+export function logStdoutStderr({ stdout, stderr }: { stdout: Buffer, stderr: Buffer }) {
if (stdout.length > 0) {
console.log('%cSTDOUT:', 'color: green; font-weight: bold');
- console.log(stdout);
+ console.log(stdout.toString('utf8'));
}
if (stderr.length > 0) {
console.log('%cSTDERR:', 'color: blue; font-weight: bold');
- console.log(stderr);
+ console.log(stderr.toString('utf8'));
}
}
@@ -72,10 +68,8 @@ export async function readFrames({ filePath, from, to, streamIndex }: {
filePath: string, from?: number | undefined, to?: number | undefined, streamIndex: number,
}) {
const intervalsArgs = from != null && to != null ? ['-read_intervals', `${from}%${to}`] : [];
- const { stdout } = await runFfprobe(['-v', 'error', ...intervalsArgs, '-show_packets', '-select_streams', streamIndex, '-show_entries', 'packet=pts_time,flags', '-of', 'json', filePath]);
- // todo types
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const packetsFiltered: Frame[] = (JSON.parse(stdout).packets as any[])
+ const { stdout } = await runFfprobe(['-v', 'error', ...intervalsArgs, '-show_packets', '-select_streams', String(streamIndex), '-show_entries', 'packet=pts_time,flags', '-of', 'json', filePath]);
+ const packetsFiltered: Frame[] = (JSON.parse(stdout as unknown as string).packets as { flags: string, pts_time: string }[])
.map((p) => ({
keyframe: p.flags[0] === 'K',
time: parseFloat(p.pts_time),
@@ -337,7 +331,7 @@ export async function readFileMeta(filePath: string) {
let parsedJson: FFprobeProbeResult;
try {
// https://github.com/mifi/lossless-cut/issues/1342
- parsedJson = JSON.parse(stdout);
+ parsedJson = JSON.parse(stdout.toString('utf8'));
} catch {
console.log('ffprobe stdout', stdout);
throw new Error('ffprobe returned malformed data');
@@ -423,7 +417,7 @@ async function extractNonAttachmentStreams({ customOutDir, filePath, streams, en
];
const { stdout } = await runFfmpeg(ffmpegArgs);
- console.log(stdout);
+ console.log(stdout.toString('utf8'));
return outPaths;
}
@@ -459,7 +453,7 @@ async function extractAttachmentStreams({ customOutDir, filePath, streams, enabl
try {
const { stdout } = await runFfmpeg(ffmpegArgs);
- console.log(stdout);
+ console.log(stdout.toString('utf8'));
} catch (err) {
// Unfortunately ffmpeg will exit with code 1 even though it's a success
// Note: This is kind of hacky:
@@ -487,7 +481,7 @@ export async function extractStreams({ filePath, customOutDir, streams, enableOv
async function renderThumbnail(filePath: string, timestamp: number) {
const args = [
- '-ss', timestamp,
+ '-ss', String(timestamp),
'-i', filePath,
'-vf', 'scale=-2:200',
'-f', 'image2',
@@ -496,7 +490,7 @@ async function renderThumbnail(filePath: string, timestamp: number) {
'-',
];
- const { stdout } = await runFfmpeg(args, { encoding: null });
+ const { stdout } = await runFfmpeg(args);
const blob = new Blob([stdout], { type: 'image/jpeg' });
return URL.createObjectURL(blob);
@@ -511,7 +505,7 @@ export async function extractSubtitleTrack(filePath: string, streamId: number) {
'-',
];
- const { stdout } = await runFfmpeg(args, { encoding: null });
+ const { stdout } = await runFfmpeg(args);
const blob = new Blob([stdout], { type: 'text/vtt' });
return URL.createObjectURL(blob);
diff --git a/src/ffprobe.js b/src/renderer/src/ffprobe.js
similarity index 100%
rename from src/ffprobe.js
rename to src/renderer/src/ffprobe.js
diff --git a/src/fixtures/DV Analyzer Summary.txt b/src/renderer/src/fixtures/DV Analyzer Summary.txt
similarity index 100%
rename from src/fixtures/DV Analyzer Summary.txt
rename to src/renderer/src/fixtures/DV Analyzer Summary.txt
diff --git a/src/fixtures/FCPXML_1_9.fcpxml b/src/renderer/src/fixtures/FCPXML_1_9.fcpxml
similarity index 100%
rename from src/fixtures/FCPXML_1_9.fcpxml
rename to src/renderer/src/fixtures/FCPXML_1_9.fcpxml
diff --git a/src/fixtures/Final Cut Pro XMEML 2.xml b/src/renderer/src/fixtures/Final Cut Pro XMEML 2.xml
similarity index 100%
rename from src/fixtures/Final Cut Pro XMEML 2.xml
rename to src/renderer/src/fixtures/Final Cut Pro XMEML 2.xml
diff --git a/src/fixtures/Final Cut Pro XMEML 3.xml b/src/renderer/src/fixtures/Final Cut Pro XMEML 3.xml
similarity index 100%
rename from src/fixtures/Final Cut Pro XMEML 3.xml
rename to src/renderer/src/fixtures/Final Cut Pro XMEML 3.xml
diff --git a/src/fixtures/Final Cut Pro XMEML.xml b/src/renderer/src/fixtures/Final Cut Pro XMEML.xml
similarity index 100%
rename from src/fixtures/Final Cut Pro XMEML.xml
rename to src/renderer/src/fixtures/Final Cut Pro XMEML.xml
diff --git a/src/fixtures/mplayer.edl b/src/renderer/src/fixtures/mplayer.edl
similarity index 100%
rename from src/fixtures/mplayer.edl
rename to src/renderer/src/fixtures/mplayer.edl
diff --git a/src/fixtures/potplayer bookmark format utf16le issue 867.pbf b/src/renderer/src/fixtures/potplayer bookmark format utf16le issue 867.pbf
similarity index 100%
rename from src/fixtures/potplayer bookmark format utf16le issue 867.pbf
rename to src/renderer/src/fixtures/potplayer bookmark format utf16le issue 867.pbf
diff --git a/src/fixtures/sample.srt b/src/renderer/src/fixtures/sample.srt
similarity index 100%
rename from src/fixtures/sample.srt
rename to src/renderer/src/fixtures/sample.srt
diff --git a/src/fixtures/test1.csv b/src/renderer/src/fixtures/test1.csv
similarity index 100%
rename from src/fixtures/test1.csv
rename to src/renderer/src/fixtures/test1.csv
diff --git a/src/fixtures/test1.pbf b/src/renderer/src/fixtures/test1.pbf
similarity index 100%
rename from src/fixtures/test1.pbf
rename to src/renderer/src/fixtures/test1.pbf
diff --git a/src/fixtures/test2.csv b/src/renderer/src/fixtures/test2.csv
similarity index 100%
rename from src/fixtures/test2.csv
rename to src/renderer/src/fixtures/test2.csv
diff --git a/src/fixtures/test2.pbf b/src/renderer/src/fixtures/test2.pbf
similarity index 100%
rename from src/fixtures/test2.pbf
rename to src/renderer/src/fixtures/test2.pbf
diff --git a/src/fixtures/test3.csv b/src/renderer/src/fixtures/test3.csv
similarity index 100%
rename from src/fixtures/test3.csv
rename to src/renderer/src/fixtures/test3.csv
diff --git a/src/fixtures/test3.pbf b/src/renderer/src/fixtures/test3.pbf
similarity index 100%
rename from src/fixtures/test3.pbf
rename to src/renderer/src/fixtures/test3.pbf
diff --git a/src/hooks/normalizeWheel.ts b/src/renderer/src/hooks/normalizeWheel.ts
similarity index 100%
rename from src/hooks/normalizeWheel.ts
rename to src/renderer/src/hooks/normalizeWheel.ts
diff --git a/src/hooks/useContextMenu.ts b/src/renderer/src/hooks/useContextMenu.ts
similarity index 100%
rename from src/hooks/useContextMenu.ts
rename to src/renderer/src/hooks/useContextMenu.ts
diff --git a/src/hooks/useDirectoryAccess.js b/src/renderer/src/hooks/useDirectoryAccess.ts
similarity index 91%
rename from src/hooks/useDirectoryAccess.js
rename to src/renderer/src/hooks/useDirectoryAccess.ts
index bb43ac5ba5a..754b293fa34 100644
--- a/src/hooks/useDirectoryAccess.js
+++ b/src/renderer/src/hooks/useDirectoryAccess.ts
@@ -1,11 +1,11 @@
import { useCallback } from 'react';
import i18n from 'i18next';
+import invariant from 'tiny-invariant';
import { getOutDir, getFileDir, checkDirWriteAccess, dirExists, isMasBuild } from '../util';
import { askForOutDir, askForInputDir } from '../dialogs';
import { errorToast } from '../swal';
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import isDev from '../isDev';
+// import isDev from '../isDev';
export class DirectoryAccessDeclinedError extends Error {
constructor() {
@@ -26,10 +26,11 @@ const simulateMasBuild = false;
const masMode = isMasBuild || simulateMasBuild;
-export default ({ setCustomOutDir }) => {
- const ensureAccessToSourceDir = useCallback(async (inputPath) => {
+export default ({ setCustomOutDir }: { setCustomOutDir: (a: string | undefined) => void }) => {
+ const ensureAccessToSourceDir = useCallback(async (inputPath: string) => {
// Called if we need to read/write to the source file's directory (probably to read/write the project file)
const inputFileDir = getFileDir(inputPath);
+ invariant(inputFileDir != null);
let simulateMasPermissionError = simulateMasBuild;
@@ -55,7 +56,7 @@ export default ({ setCustomOutDir }) => {
}
}, []);
- const ensureWritableOutDir = useCallback(async ({ inputPath, outDir }) => {
+ const ensureWritableOutDir = useCallback(async ({ inputPath, outDir }: { inputPath: string | undefined, outDir: string | undefined }) => {
// we might need to change the output directory if the user chooses to give us a different one.
let newCustomOutDir = outDir;
diff --git a/src/hooks/useFfmpegOperations.ts b/src/renderer/src/hooks/useFfmpegOperations.ts
similarity index 98%
rename from src/hooks/useFfmpegOperations.ts
rename to src/renderer/src/hooks/useFfmpegOperations.ts
index cbabc25a374..9f92de4e34d 100644
--- a/src/hooks/useFfmpegOperations.ts
+++ b/src/renderer/src/hooks/useFfmpegOperations.ts
@@ -9,7 +9,8 @@ import { isCuttingStart, isCuttingEnd, runFfmpegWithProgress, getFfCommandLine,
import { getMapStreamsArgs, getStreamIdsToCopy } from '../util/streams';
import { getSmartCutParams } from '../smartcut';
import { isDurationValid } from '../segments';
-import { FFprobeStream } from '../../ffprobe';
+import { FFprobeStream } from '../../../../ffprobe';
+import { Html5ifyMode } from '../../../../types';
const { join, resolve, dirname } = window.require('path');
const { pathExists } = window.require('fs-extra');
@@ -470,8 +471,11 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
if (autoDeleteMergedSegments) await tryDeleteFiles(segmentPaths);
}, [concatFiles, filePath, shouldSkipExistingFile]);
- const html5ify = useCallback(async ({ customOutDir, filePath: filePathArg, speed, hasAudio, hasVideo, onProgress }) => {
+ const html5ify = useCallback(async ({ customOutDir, filePath: filePathArg, speed, hasAudio, hasVideo, onProgress }: {
+ customOutDir: string | undefined, filePath: string, speed: Html5ifyMode, hasAudio: boolean, hasVideo: boolean, onProgress: (p: number) => void,
+ }) => {
const outPath = getHtml5ifiedPath(customOutDir, filePathArg, speed);
+ invariant(outPath != null);
await ffmpegHtml5ify({ filePath: filePathArg, outPath, speed, hasAudio, hasVideo, onProgress });
invariant(outPath != null);
await transferTimestamps({ inPath: filePathArg, outPath, treatOutputFileModifiedTimeAsStart });
diff --git a/src/hooks/useFileFormatState.ts b/src/renderer/src/hooks/useFileFormatState.ts
similarity index 100%
rename from src/hooks/useFileFormatState.ts
rename to src/renderer/src/hooks/useFileFormatState.ts
diff --git a/src/hooks/useFrameCapture.ts b/src/renderer/src/hooks/useFrameCapture.ts
similarity index 96%
rename from src/hooks/useFrameCapture.ts
rename to src/renderer/src/hooks/useFrameCapture.ts
index 10a49187b00..9823b58c036 100644
--- a/src/hooks/useFrameCapture.ts
+++ b/src/renderer/src/hooks/useFrameCapture.ts
@@ -8,7 +8,7 @@ import { getNumDigits } from '../segments';
import { captureFrame as ffmpegCaptureFrame, captureFrames as ffmpegCaptureFrames } from '../ffmpeg';
import { FormatTimecode } from '../types';
-import { CaptureFormat } from '../../types';
+import { CaptureFormat } from '../../../../types';
const mime = window.require('mime-types');
const { rename, readdir, writeFile }: typeof FsPromises = window.require('fs/promises');
@@ -28,7 +28,7 @@ function getFrameFromVideo(video: HTMLVideoElement, format: CaptureFormat, quali
export default ({ formatTimecode, treatOutputFileModifiedTimeAsStart }: { formatTimecode: FormatTimecode, treatOutputFileModifiedTimeAsStart?: boolean | undefined | null }) => {
const captureFramesRange = useCallback(async ({ customOutDir, filePath, fps, fromTime, toTime, estimatedMaxNumFiles, captureFormat, quality, filter, onProgress, outputTimestamps }: {
- customOutDir, filePath: string, fps: number, fromTime: number, toTime: number, estimatedMaxNumFiles: number, captureFormat: string, quality: number, filter?: string | undefined, onProgress: (a: number) => void, outputTimestamps: boolean
+ customOutDir, filePath: string, fps: number, fromTime: number, toTime: number, estimatedMaxNumFiles: number, captureFormat: CaptureFormat, quality: number, filter?: string | undefined, onProgress: (a: number) => void, outputTimestamps: boolean
}) => {
const getSuffix = (prefix: string) => `${prefix}.${captureFormat}`;
diff --git a/src/hooks/useKeyboard.ts b/src/renderer/src/hooks/useKeyboard.ts
similarity index 96%
rename from src/hooks/useKeyboard.ts
rename to src/renderer/src/hooks/useKeyboard.ts
index 5bfc29f0ff9..3692c34e589 100644
--- a/src/hooks/useKeyboard.ts
+++ b/src/renderer/src/hooks/useKeyboard.ts
@@ -4,7 +4,7 @@ import { useEffect, useRef } from 'react';
// Also document.addEventListener needs custom handling of modifier keys or C will be triggered by CTRL+C, etc
import Mousetrap from 'mousetrap';
-import { KeyBinding, KeyboardAction } from '../../types';
+import { KeyBinding, KeyboardAction } from '../../../../types';
// for all dialog actions (e.g. detectSceneChanges) we must use keyup, or we risk having the button press inserted into the dialog's input element right after the dialog opens
diff --git a/src/hooks/useKeyframes.ts b/src/renderer/src/hooks/useKeyframes.ts
similarity index 98%
rename from src/hooks/useKeyframes.ts
rename to src/renderer/src/hooks/useKeyframes.ts
index a17c9d66caa..623693390e1 100644
--- a/src/hooks/useKeyframes.ts
+++ b/src/renderer/src/hooks/useKeyframes.ts
@@ -3,7 +3,7 @@ import sortBy from 'lodash/sortBy';
import useDebounceOld from 'react-use/lib/useDebounce'; // Want to phase out this
import { readFramesAroundTime, findNearestKeyFrameTime as ffmpegFindNearestKeyFrameTime, Frame } from '../ffmpeg';
-import { FFprobeStream } from '../../ffprobe';
+import { FFprobeStream } from '../../../../ffprobe';
const maxKeyframes = 1000;
// const maxKeyframes = 100;
diff --git a/src/hooks/useNativeMenu.ts b/src/renderer/src/hooks/useNativeMenu.ts
similarity index 100%
rename from src/hooks/useNativeMenu.ts
rename to src/renderer/src/hooks/useNativeMenu.ts
diff --git a/src/hooks/useSegments.ts b/src/renderer/src/hooks/useSegments.ts
similarity index 97%
rename from src/hooks/useSegments.ts
rename to src/renderer/src/hooks/useSegments.ts
index 7483ae4f76e..4761e791527 100644
--- a/src/hooks/useSegments.ts
+++ b/src/renderer/src/hooks/useSegments.ts
@@ -16,9 +16,7 @@ import * as ffmpegParameters from '../ffmpeg-parameters';
import { maxSegmentsAllowed } from '../util/constants';
import { SegmentBase, SegmentToExport, StateSegment, UpdateSegAtIndex } from '../types';
-const remote = window.require('@electron/remote');
-
-const { blackDetect, silenceDetect } = remote.require('./ffmpeg');
+const { ffmpeg: { blackDetect, silenceDetect } } = window.require('@electron/remote').require('./index.js');
function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly }: {
@@ -81,7 +79,9 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
});
}, [clearSegCounter, createIndexedSegment, setCutSegments]);
- const detectSegments = useCallback(async ({ name, workingText, errorText, fn }) => {
+ const detectSegments = useCallback(async ({ name, workingText, errorText, fn }: {
+ name: string, workingText: string, errorText: string, fn: () => Promise,
+ }) => {
if (!filePath) return;
if (workingRef.current) return;
try {
@@ -92,7 +92,7 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
console.log(name, newSegments);
loadCutSegments(newSegments, true);
} catch (err) {
- handleError(errorText, err);
+ if (!(err instanceof Error && err.name === 'AbortError')) handleError(errorText, err);
} finally {
setWorking(undefined);
setCutProgress(undefined);
@@ -131,19 +131,25 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
const detectBlackScenes = useCallback(async () => {
const filterOptions = await showParametersDialog({ title: i18n.t('Enter parameters'), parameters: ffmpegParameters.blackdetect(), docUrl: 'https://ffmpeg.org/ffmpeg-filters.html#blackdetect' });
if (filterOptions == null) return;
+ invariant(filePath != null);
await detectSegments({ name: 'blackScenes', workingText: i18n.t('Detecting black scenes'), errorText: i18n.t('Failed to detect black scenes'), fn: async () => blackDetect({ filePath, filterOptions, onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setCutProgress]);
const detectSilentScenes = useCallback(async () => {
const filterOptions = await showParametersDialog({ title: i18n.t('Enter parameters'), parameters: ffmpegParameters.silencedetect(), docUrl: 'https://ffmpeg.org/ffmpeg-filters.html#silencedetect' });
if (filterOptions == null) return;
+ invariant(filePath != null);
await detectSegments({ name: 'silentScenes', workingText: i18n.t('Detecting silent scenes'), errorText: i18n.t('Failed to detect silent scenes'), fn: async () => silenceDetect({ filePath, filterOptions, onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setCutProgress]);
const detectSceneChanges = useCallback(async () => {
const filterOptions = await showParametersDialog({ title: i18n.t('Enter parameters'), parameters: ffmpegParameters.sceneChange() });
if (filterOptions == null) return;
- await detectSegments({ name: 'sceneChanges', workingText: i18n.t('Detecting scene changes'), errorText: i18n.t('Failed to detect scene changes'), fn: async () => ffmpegDetectSceneChanges({ filePath, minChange: filterOptions['minChange'], onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
+ invariant(filePath != null);
+ // eslint-disable-next-line prefer-destructuring
+ const minChange = filterOptions['minChange'];
+ invariant(minChange != null);
+ await detectSegments({ name: 'sceneChanges', workingText: i18n.t('Detecting scene changes'), errorText: i18n.t('Failed to detect scene changes'), fn: async () => ffmpegDetectSceneChanges({ filePath, minChange, onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setCutProgress]);
const createSegmentsFromKeyframes = useCallback(async () => {
diff --git a/src/hooks/useTimelineScroll.ts b/src/renderer/src/hooks/useTimelineScroll.ts
similarity index 100%
rename from src/hooks/useTimelineScroll.ts
rename to src/renderer/src/hooks/useTimelineScroll.ts
diff --git a/src/hooks/useUserSettings.ts b/src/renderer/src/hooks/useUserSettings.ts
similarity index 100%
rename from src/hooks/useUserSettings.ts
rename to src/renderer/src/hooks/useUserSettings.ts
diff --git a/src/hooks/useUserSettingsRoot.ts b/src/renderer/src/hooks/useUserSettingsRoot.ts
similarity index 98%
rename from src/hooks/useUserSettingsRoot.ts
rename to src/renderer/src/hooks/useUserSettingsRoot.ts
index a80914c9c94..94f0f12da3b 100644
--- a/src/hooks/useUserSettingsRoot.ts
+++ b/src/renderer/src/hooks/useUserSettingsRoot.ts
@@ -1,13 +1,11 @@
import { useEffect, useState, useRef, useCallback } from 'react';
import i18n from 'i18next';
-import { StoreGetConfig, StoreResetConfig, StoreSetConfig, Config } from '../../types';
+import { Config } from '../../../../types';
import { errorToast } from '../swal';
import isDev from '../isDev';
-const remote = window.require('@electron/remote');
-
-const configStore: { get: StoreGetConfig, set: StoreSetConfig, reset: StoreResetConfig } = remote.require('./configStore');
+const { configStore } = window.require('@electron/remote').require('./index.js');
export default () => {
const firstUpdateRef = useRef(true);
diff --git a/src/hooks/useWaveform.ts b/src/renderer/src/hooks/useWaveform.ts
similarity index 98%
rename from src/hooks/useWaveform.ts
rename to src/renderer/src/hooks/useWaveform.ts
index 7083ef99fbb..1fbe0c4d648 100644
--- a/src/hooks/useWaveform.ts
+++ b/src/renderer/src/hooks/useWaveform.ts
@@ -5,7 +5,7 @@ import { waveformColorDark, waveformColorLight } from '../colors';
import { renderWaveformPng } from '../ffmpeg';
import { RenderableWaveform } from '../types';
-import { FFprobeStream } from '../../ffprobe';
+import { FFprobeStream } from '../../../../ffprobe';
const maxWaveforms = 100;
diff --git a/src/hooks/useWhatChanged.js b/src/renderer/src/hooks/useWhatChanged.js
similarity index 100%
rename from src/hooks/useWhatChanged.js
rename to src/renderer/src/hooks/useWhatChanged.js
diff --git a/src/i18n.ts b/src/renderer/src/i18n.ts
similarity index 90%
rename from src/i18n.ts
rename to src/renderer/src/i18n.ts
index 603b054fd08..dbad35f7fb8 100644
--- a/src/i18n.ts
+++ b/src/renderer/src/i18n.ts
@@ -3,9 +3,7 @@ import { initReactI18next } from 'react-i18next';
const Backend = window.require('i18next-fs-backend');
-const remote = window.require('@electron/remote');
-
-const { commonI18nOptions, fallbackLng, loadPath, addPath } = remote.require('./i18n-common');
+const { i18n: { commonI18nOptions, fallbackLng, loadPath, addPath } } = window.require('@electron/remote').require('./index.js');
// https://www.i18next.com/overview/typescript#argument-of-type-defaulttfuncreturn-is-not-assignable-to-parameter-of-type-xyz
// todo This should not be necessary anymore since v23.0.0
diff --git a/src/icon-mac.svg b/src/renderer/src/icon-mac.svg
similarity index 100%
rename from src/icon-mac.svg
rename to src/renderer/src/icon-mac.svg
diff --git a/src/icon.svg b/src/renderer/src/icon.svg
similarity index 100%
rename from src/icon.svg
rename to src/renderer/src/icon.svg
diff --git a/src/index.tsx b/src/renderer/src/index.tsx
similarity index 79%
rename from src/index.tsx
rename to src/renderer/src/index.tsx
index f1205709982..6645e69271c 100644
--- a/src/index.tsx
+++ b/src/renderer/src/index.tsx
@@ -20,6 +20,8 @@ import '@fontsource/open-sans/700-italic.css';
import '@fontsource/open-sans/800.css';
import '@fontsource/open-sans/800-italic.css';
+import type * as main from '../../main/index';
+
import App from './App';
import ErrorBoundary from './ErrorBoundary';
import './i18n';
@@ -27,12 +29,22 @@ import './i18n';
import './main.css';
+type TypedRemote = Omit & {
+ require: (module: T) => (
+ T extends './index.js' ? typeof main :
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ any
+ );
+}
+
declare global {
interface Window {
- require: (module: T) => T extends '@electron/remote' ? typeof Remote :
+ require: (module: T) => (
+ T extends '@electron/remote' ? TypedRemote :
T extends 'electron' ? typeof Electron :
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- any;
+ any
+ );
}
}
diff --git a/src/renderer/src/isDev.ts b/src/renderer/src/isDev.ts
new file mode 100644
index 00000000000..56aafd99b6f
--- /dev/null
+++ b/src/renderer/src/isDev.ts
@@ -0,0 +1,3 @@
+const { isDev } = window.require('@electron/remote').require('./index.js');
+
+export default isDev;
diff --git a/src/main.css b/src/renderer/src/main.css
similarity index 100%
rename from src/main.css
rename to src/renderer/src/main.css
diff --git a/src/mifi.js b/src/renderer/src/mifi.js
similarity index 100%
rename from src/mifi.js
rename to src/renderer/src/mifi.js
diff --git a/src/outFormats.js b/src/renderer/src/outFormats.js
similarity index 100%
rename from src/outFormats.js
rename to src/renderer/src/outFormats.js
diff --git a/src/reporting.jsx b/src/renderer/src/reporting.tsx
similarity index 76%
rename from src/reporting.jsx
rename to src/renderer/src/reporting.tsx
index 63bf65e8ec1..33f10543322 100644
--- a/src/reporting.jsx
+++ b/src/renderer/src/reporting.tsx
@@ -1,24 +1,28 @@
import withReactContent from 'sweetalert2-react-content';
import i18n from 'i18next';
import { Trans } from 'react-i18next';
+import { CSSProperties } from 'react';
import CopyClipboardButton from './components/CopyClipboardButton';
import { isStoreBuild, isMasBuild, isWindowsStoreBuild } from './util';
import Swal from './swal';
const electron = window.require('electron');
-const os = window.require('os');
-const { app } = window.require('@electron/remote');
+const remote = window.require('@electron/remote');
+
+const { app } = remote;
+
+const { platform } = remote.require('./index.js');
const ReactSwal = withReactContent(Swal);
-const linkStyle = { fontWeight: 'bold', cursor: 'pointer' };
+const linkStyle: CSSProperties = { fontWeight: 'bold', cursor: 'pointer' };
// eslint-disable-next-line import/prefer-default-export
-export function openSendReportDialog(err, state) {
+export function openSendReportDialog(err: unknown | undefined, state: unknown) {
const reportInstructions = isStoreBuild
? (
Please send an email to electron.shell.openExternal('mailto:losslesscut@mifi.no')}>losslesscut@mifi.no where you describe what you were doing.
@@ -33,19 +37,18 @@ export function openSendReportDialog(err, state) {
);
- const platform = os.platform();
const version = app.getVersion();
- const text = `${err ? err.stack : 'No error occurred.'}\n\n${JSON.stringify({
- err: err && {
- code: err.code,
- killed: err.killed,
- failed: err.failed,
- timedOut: err.timedOut,
- isCanceled: err.isCanceled,
- exitCode: err.exitCode,
- signal: err.signal,
- signalDescription: err.signalDescription,
+ const text = `${err instanceof Error ? err.stack : 'No error occurred.'}\n\n${JSON.stringify({
+ err: err instanceof Error && {
+ code: err['code'],
+ killed: err['killed'],
+ failed: err['failed'],
+ timedOut: err['timedOut'],
+ isCanceled: err['isCanceled'],
+ exitCode: err['exitCode'],
+ signal: err['signal'],
+ signalDescription: err['signalDescription'],
},
state,
diff --git a/src/segments.test.ts b/src/renderer/src/segments.test.ts
similarity index 100%
rename from src/segments.test.ts
rename to src/renderer/src/segments.test.ts
diff --git a/src/segments.ts b/src/renderer/src/segments.ts
similarity index 100%
rename from src/segments.ts
rename to src/renderer/src/segments.ts
diff --git a/src/smartcut.ts b/src/renderer/src/smartcut.ts
similarity index 98%
rename from src/smartcut.ts
rename to src/renderer/src/smartcut.ts
index 0507bf434eb..b478f629ffd 100644
--- a/src/smartcut.ts
+++ b/src/renderer/src/smartcut.ts
@@ -1,7 +1,7 @@
import { getRealVideoStreams, getVideoTimebase } from './util/streams';
import { readKeyframesAroundTime, findNextKeyframe, findKeyframeAtExactTime } from './ffmpeg';
-import { FFprobeStream } from '../ffprobe';
+import { FFprobeStream } from '../../../ffprobe';
const { stat } = window.require('fs-extra');
diff --git a/src/swal.ts b/src/renderer/src/swal.ts
similarity index 100%
rename from src/swal.ts
rename to src/renderer/src/swal.ts
diff --git a/src/theme.ts b/src/renderer/src/theme.ts
similarity index 100%
rename from src/theme.ts
rename to src/renderer/src/theme.ts
diff --git a/src/types.ts b/src/renderer/src/types.ts
similarity index 95%
rename from src/types.ts
rename to src/renderer/src/types.ts
index be2b6b1012c..45e16d779d8 100644
--- a/src/types.ts
+++ b/src/renderer/src/types.ts
@@ -61,8 +61,6 @@ export interface InverseCutSegment {
export type PlaybackMode = 'loop-segment-start-end' | 'loop-segment' | 'play-segment-once' | 'loop-selected-segments';
-export type Html5ifyMode = 'fastest' | 'fast-audio-remux' | 'fast-audio' | 'fast' | 'slow' | 'slow-audio' | 'slowest';
-
export type EdlFileType = 'csv' | 'csv-frames' | 'xmeml' | 'fcpxml' | 'dv-analyzer-summary-txt' | 'cue' | 'pbf' | 'mplayer' | 'srt' | 'llc';
export type EdlImportType = 'youtube' | EdlFileType;
diff --git a/src/util.ts b/src/renderer/src/util.ts
similarity index 98%
rename from src/util.ts
rename to src/renderer/src/util.ts
index b9166232fa2..81568f1ba9e 100644
--- a/src/util.ts
+++ b/src/renderer/src/util.ts
@@ -6,7 +6,6 @@ import sortBy from 'lodash/sortBy';
import pRetry, { Options } from 'p-retry';
import { ExecaError } from 'execa';
import type * as FsPromises from 'fs/promises';
-import type * as Os from 'os';
import type * as FsExtra from 'fs-extra';
import type { PlatformPath } from 'path';
@@ -17,9 +16,11 @@ import { ffmpegExtractWindow } from './util/constants';
const { dirname, parse: parsePath, join, extname, isAbsolute, resolve, basename }: PlatformPath = window.require('path');
const fsExtra: typeof FsExtra = window.require('fs-extra');
const { stat, lstat, readdir, utimes, unlink }: typeof FsPromises = window.require('fs/promises');
-const os: typeof Os = window.require('os');
const { ipcRenderer } = window.require('electron');
const remote = window.require('@electron/remote');
+const { isWindows, isMac } = remote.require('./index.js');
+
+export { isWindows, isMac };
const trashFile = async (path: string) => ipcRenderer.invoke('tryTrashItem', path);
@@ -195,12 +196,6 @@ export const isMasBuild = window.process.mas;
export const isWindowsStoreBuild = window.process.windowsStore;
export const isStoreBuild = isMasBuild || isWindowsStoreBuild;
-export const platform = os.platform();
-export const arch = os.arch();
-
-export const isWindows = platform === 'win32';
-export const isMac = platform === 'darwin';
-
export function getExtensionForFormat(format: string) {
const ext = {
matroska: 'mkv',
@@ -270,7 +265,7 @@ export async function findExistingHtml5FriendlyFile(fp, cod) {
};
}
-export function getHtml5ifiedPath(cod, fp, type) {
+export function getHtml5ifiedPath(cod: string | undefined, fp, type) {
// See also inside ffmpegHtml5ify
const ext = (isMac && ['slowest', 'slow', 'slow-audio'].includes(type)) ? 'mp4' : 'mkv';
return getSuffixedOutPath({ customOutDir: cod, filePath: fp, nameSuffix: `${html5ifiedPrefix}${type}.${ext}` });
@@ -311,6 +306,10 @@ export const deleteDispositionValue = 'llc_disposition_remove';
export const mirrorTransform = 'matrix(-1, 0, 0, 1, 0, 0)';
+export function isExecaError(err: unknown): err is Pick {
+ return err instanceof Error && 'stdout' in err && 'stderr' in err;
+}
+
// I *think* Windows will throw error with code ENOENT if ffprobe/ffmpeg fails (execa), but other OS'es will return this error code if a file is not found, so it would be wrong to attribute it to exec failure.
// see https://github.com/mifi/lossless-cut/issues/451
export const isExecaFailure = (err): err is ExecaError => err.exitCode === 1 || (isWindows && err.code === 'ENOENT');
diff --git a/src/util/colors.ts b/src/renderer/src/util/colors.ts
similarity index 100%
rename from src/util/colors.ts
rename to src/renderer/src/util/colors.ts
diff --git a/src/util/constants.ts b/src/renderer/src/util/constants.ts
similarity index 100%
rename from src/util/constants.ts
rename to src/renderer/src/util/constants.ts
diff --git a/src/util/duration.test.ts b/src/renderer/src/util/duration.test.ts
similarity index 100%
rename from src/util/duration.test.ts
rename to src/renderer/src/util/duration.test.ts
diff --git a/src/util/duration.ts b/src/renderer/src/util/duration.ts
similarity index 100%
rename from src/util/duration.ts
rename to src/renderer/src/util/duration.ts
diff --git a/src/util/outputNameTemplate.ts b/src/renderer/src/util/outputNameTemplate.ts
similarity index 100%
rename from src/util/outputNameTemplate.ts
rename to src/renderer/src/util/outputNameTemplate.ts
diff --git a/src/util/rate-calculator.js b/src/renderer/src/util/rate-calculator.js
similarity index 100%
rename from src/util/rate-calculator.js
rename to src/renderer/src/util/rate-calculator.js
diff --git a/src/util/rate-calculator.test.ts b/src/renderer/src/util/rate-calculator.test.ts
similarity index 100%
rename from src/util/rate-calculator.test.ts
rename to src/renderer/src/util/rate-calculator.test.ts
diff --git a/src/util/streams.test.ts b/src/renderer/src/util/streams.test.ts
similarity index 98%
rename from src/util/streams.test.ts
rename to src/renderer/src/util/streams.test.ts
index 347f8f862b9..2ba7c59548d 100644
--- a/src/util/streams.test.ts
+++ b/src/renderer/src/util/streams.test.ts
@@ -1,7 +1,7 @@
import { test, expect } from 'vitest';
import { LiteFFprobeStream, getMapStreamsArgs, getStreamIdsToCopy } from './streams';
-import { FFprobeStreamDisposition } from '../../ffprobe';
+import { FFprobeStreamDisposition } from '../../../../ffprobe';
const makeDisposition = (override?: Partial): FFprobeStreamDisposition => ({
diff --git a/src/util/streams.ts b/src/renderer/src/util/streams.ts
similarity index 99%
rename from src/util/streams.ts
rename to src/renderer/src/util/streams.ts
index 8f392830d63..74cfd613f88 100644
--- a/src/util/streams.ts
+++ b/src/renderer/src/util/streams.ts
@@ -1,4 +1,4 @@
-import { FFprobeStream, FFprobeStreamDisposition } from '../../ffprobe';
+import { FFprobeStream, FFprobeStreamDisposition } from '../../../../ffprobe';
import { ChromiumHTMLAudioElement, ChromiumHTMLVideoElement } from '../types';
// https://www.ffmpeg.org/doxygen/3.2/libavutil_2utils_8c_source.html#l00079
diff --git a/translation.md b/translation.md
index 858a8c0619d..6d99ec7bbc1 100644
--- a/translation.md
+++ b/translation.md
@@ -41,11 +41,11 @@ Master language is English.
To test new weblate translations you made in the app itself, you need to:
1. Download the translation for your language from Weblate: **Files -> Download translation**
2. Rename the downloaded `.json` file to: `translation.json`
-3. Create a [folder structure](https://github.com/mifi/lossless-cut/tree/master/public/locales) somewhere on your computer that looks like this:
+3. Create a [folder structure](https://github.com/mifi/lossless-cut/tree/master/src/main/locales) somewhere on your computer that looks like this:
```
translations/locales/localeCode
```
-You can find a list of the available [`localeCode`s here](https://github.com/mifi/lossless-cut/tree/master/public/locales). In our example we will use `nb_NO` (Norwegian) with this path:
+You can find a list of the available [`localeCode`s here](https://github.com/mifi/lossless-cut/tree/master/src/main/locales). In our example we will use `nb_NO` (Norwegian) with this path:
```
/Users/mifi/Desktop/translations/locales/nb_NO
```
diff --git a/tsconfig.json b/tsconfig.json
index 768fb6b0404..0cdc39fc0b8 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,6 +2,7 @@
"references": [
{ "path": "./tsconfig.web.json" },
{ "path": "./tsconfig.main.json" },
+ { "path": "./tsconfig.node.json" },
],
"files": [],
}
\ No newline at end of file
diff --git a/tsconfig.main.json b/tsconfig.main.json
index f9df49611ff..ad7911f5ae0 100644
--- a/tsconfig.main.json
+++ b/tsconfig.main.json
@@ -10,12 +10,9 @@
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
-
- "noImplicitAny": false, // todo
- "checkJs": true, // todo
- "allowJs": true, // todo
},
"include": [
- "public/**/*", "types.ts",
+ "src/main/**/*",
+ "types.ts",
],
}
\ No newline at end of file
diff --git a/tsconfig.node.json b/tsconfig.node.json
new file mode 100644
index 00000000000..2ad1fad0ec1
--- /dev/null
+++ b/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "extends": ["@tsconfig/strictest", "@tsconfig/node18/tsconfig.json"],
+ "compilerOptions": {
+ "noEmit": true,
+ },
+ "include": [
+ "script/**/*",
+ ],
+}
\ No newline at end of file
diff --git a/tsconfig.web.json b/tsconfig.web.json
index a0fd7acceb6..6e8ae2130a2 100644
--- a/tsconfig.web.json
+++ b/tsconfig.web.json
@@ -12,6 +12,6 @@
{ "path": "./tsconfig.main.json" },
],
"include": [
- "src/**/*",
+ "src/renderer/**/*",
],
}
\ No newline at end of file
diff --git a/types.ts b/types.ts
index 2e8d15f635a..698027f367c 100644
--- a/types.ts
+++ b/types.ts
@@ -99,10 +99,13 @@ export interface Config {
invertTimelineScroll: boolean | undefined,
}
-export type StoreGetConfig = (key: T) => Config[T];
-export type StoreSetConfig = (key: T, value: Config[T]) => void;
-export type StoreResetConfig = (key: T) => void;
-
export interface Waveform {
buffer: Buffer,
}
+
+export interface ApiKeyboardActionRequest {
+ id: number
+ action: string
+}
+
+export type Html5ifyMode = 'fastest' | 'fast-audio-remux' | 'fast-audio' | 'fast' | 'slow' | 'slow-audio' | 'slowest';
diff --git a/vite.config.js b/vite.config.js
deleted file mode 100644
index d0da754e6be..00000000000
--- a/vite.config.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { defineConfig } from 'vite';
-import react from '@vitejs/plugin-react';
-
-
-// https://vitejs.dev/config/
-export default defineConfig({
- plugins: [react()],
- base: '',
- build: {
- chunkSizeWarningLimit: 3e6,
- sourcemap: true,
- },
-});
diff --git a/yarn.lock b/yarn.lock
index 8c14cb96099..257ac8dc969 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -29,6 +29,16 @@ __metadata:
languageName: node
linkType: hard
+"@ampproject/remapping@npm:^2.2.0":
+ version: 2.3.0
+ resolution: "@ampproject/remapping@npm:2.3.0"
+ dependencies:
+ "@jridgewell/gen-mapping": "npm:^0.3.5"
+ "@jridgewell/trace-mapping": "npm:^0.3.24"
+ checksum: f3451525379c68a73eb0a1e65247fbf28c0cccd126d93af21c75fceff77773d43c0d4a2d51978fb131aff25b5f2cb41a9fe48cc296e61ae65e679c4f6918b0ab
+ languageName: node
+ linkType: hard
+
"@babel/code-frame@npm:^7.0.0":
version: 7.23.5
resolution: "@babel/code-frame@npm:7.23.5"
@@ -58,6 +68,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.1, @babel/code-frame@npm:^7.24.2":
+ version: 7.24.2
+ resolution: "@babel/code-frame@npm:7.24.2"
+ dependencies:
+ "@babel/highlight": "npm:^7.24.2"
+ picocolors: "npm:^1.0.0"
+ checksum: 7db8f5b36ffa3f47a37f58f61e3d130b9ecad21961f3eede7e2a4ac2c7e4a5efb6e9d03a810c669bc986096831b6c0dfc2c3082673d93351b82359c1b03e0590
+ languageName: node
+ linkType: hard
+
"@babel/compat-data@npm:^7.20.5":
version: 7.20.14
resolution: "@babel/compat-data@npm:7.20.14"
@@ -65,6 +85,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/compat-data@npm:^7.23.5":
+ version: 7.24.1
+ resolution: "@babel/compat-data@npm:7.24.1"
+ checksum: d5460b99c07ff8487467c52f742a219c7e3bcdcaa2882456a13c0d0c8116405f0c85a651fb60511284dc64ed627a5e989f24c3cd6e71d07a9947e7c8954b433c
+ languageName: node
+ linkType: hard
+
"@babel/core@npm:^7.20.12":
version: 7.20.12
resolution: "@babel/core@npm:7.20.12"
@@ -88,6 +115,29 @@ __metadata:
languageName: node
linkType: hard
+"@babel/core@npm:^7.23.5":
+ version: 7.24.3
+ resolution: "@babel/core@npm:7.24.3"
+ dependencies:
+ "@ampproject/remapping": "npm:^2.2.0"
+ "@babel/code-frame": "npm:^7.24.2"
+ "@babel/generator": "npm:^7.24.1"
+ "@babel/helper-compilation-targets": "npm:^7.23.6"
+ "@babel/helper-module-transforms": "npm:^7.23.3"
+ "@babel/helpers": "npm:^7.24.1"
+ "@babel/parser": "npm:^7.24.1"
+ "@babel/template": "npm:^7.24.0"
+ "@babel/traverse": "npm:^7.24.1"
+ "@babel/types": "npm:^7.24.0"
+ convert-source-map: "npm:^2.0.0"
+ debug: "npm:^4.1.0"
+ gensync: "npm:^1.0.0-beta.2"
+ json5: "npm:^2.2.3"
+ semver: "npm:^6.3.1"
+ checksum: 3a7b9931fe0d93c500dcdb6b36f038b0f9d5090c048818e62aa8321c8f6e8ccc3d47373f0b40591c1fe3b13e5096bacabb1ade83f9f4d86f57878c39a9d1ade1
+ languageName: node
+ linkType: hard
+
"@babel/generator@npm:^7.20.7":
version: 7.20.14
resolution: "@babel/generator@npm:7.20.14"
@@ -111,6 +161,18 @@ __metadata:
languageName: node
linkType: hard
+"@babel/generator@npm:^7.24.1":
+ version: 7.24.1
+ resolution: "@babel/generator@npm:7.24.1"
+ dependencies:
+ "@babel/types": "npm:^7.24.0"
+ "@jridgewell/gen-mapping": "npm:^0.3.5"
+ "@jridgewell/trace-mapping": "npm:^0.3.25"
+ jsesc: "npm:^2.5.1"
+ checksum: c6160e9cd63d7ed7168dee27d827f9c46fab820c45861a5df56cd5c78047f7c3fc97c341e9ccfa1a6f97c87ec2563d9903380b5f92794e3540a6c5f99eb8f075
+ languageName: node
+ linkType: hard
+
"@babel/helper-compilation-targets@npm:^7.20.7":
version: 7.20.7
resolution: "@babel/helper-compilation-targets@npm:7.20.7"
@@ -126,6 +188,19 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-compilation-targets@npm:^7.23.6":
+ version: 7.23.6
+ resolution: "@babel/helper-compilation-targets@npm:7.23.6"
+ dependencies:
+ "@babel/compat-data": "npm:^7.23.5"
+ "@babel/helper-validator-option": "npm:^7.23.5"
+ browserslist: "npm:^4.22.2"
+ lru-cache: "npm:^5.1.1"
+ semver: "npm:^6.3.1"
+ checksum: 05595cd73087ddcd81b82d2f3297aac0c0422858dfdded43d304786cf680ec33e846e2317e6992d2c964ee61d93945cbf1fa8ec80b55aee5bfb159227fb02cb9
+ languageName: node
+ linkType: hard
+
"@babel/helper-environment-visitor@npm:^7.18.9":
version: 7.18.9
resolution: "@babel/helper-environment-visitor@npm:7.18.9"
@@ -168,6 +243,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-module-imports@npm:^7.22.15":
+ version: 7.24.3
+ resolution: "@babel/helper-module-imports@npm:7.24.3"
+ dependencies:
+ "@babel/types": "npm:^7.24.0"
+ checksum: 42fe124130b78eeb4bb6af8c094aa749712be0f4606f46716ce74bc18a5ea91c918c547c8bb2307a2e4b33f163e4ad2cb6a7b45f80448e624eae45b597ea3499
+ languageName: node
+ linkType: hard
+
"@babel/helper-module-transforms@npm:^7.20.11":
version: 7.20.11
resolution: "@babel/helper-module-transforms@npm:7.20.11"
@@ -184,6 +268,21 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-module-transforms@npm:^7.23.3":
+ version: 7.23.3
+ resolution: "@babel/helper-module-transforms@npm:7.23.3"
+ dependencies:
+ "@babel/helper-environment-visitor": "npm:^7.22.20"
+ "@babel/helper-module-imports": "npm:^7.22.15"
+ "@babel/helper-simple-access": "npm:^7.22.5"
+ "@babel/helper-split-export-declaration": "npm:^7.22.6"
+ "@babel/helper-validator-identifier": "npm:^7.22.20"
+ peerDependencies:
+ "@babel/core": ^7.0.0
+ checksum: 583fa580f8e50e6f45c4f46aa76a8e49c2528deb84e25f634d66461b9a0e2420e13979b0a607b67aef67eaf8db8668eb9edc038b4514b16e3879fe09e8fd294b
+ languageName: node
+ linkType: hard
+
"@babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.19.0":
version: 7.20.2
resolution: "@babel/helper-plugin-utils@npm:7.20.2"
@@ -191,6 +290,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-plugin-utils@npm:^7.24.0":
+ version: 7.24.0
+ resolution: "@babel/helper-plugin-utils@npm:7.24.0"
+ checksum: dc8c7af321baf7653d93315beffee1790eb2c464b4f529273a24c8743a3f3095bf3f2d11828cb2c52d56282ef43a4bdc67a79c9ab8dd845e35d01871f3f28a0e
+ languageName: node
+ linkType: hard
+
"@babel/helper-simple-access@npm:^7.20.2":
version: 7.20.2
resolution: "@babel/helper-simple-access@npm:7.20.2"
@@ -200,6 +306,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-simple-access@npm:^7.22.5":
+ version: 7.22.5
+ resolution: "@babel/helper-simple-access@npm:7.22.5"
+ dependencies:
+ "@babel/types": "npm:^7.22.5"
+ checksum: 7d5430eecf880937c27d1aed14245003bd1c7383ae07d652b3932f450f60bfcf8f2c1270c593ab063add185108d26198c69d1aca0e6fb7c6fdada4bcf72ab5b7
+ languageName: node
+ linkType: hard
+
"@babel/helper-split-export-declaration@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/helper-split-export-declaration@npm:7.18.6"
@@ -232,6 +347,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-string-parser@npm:^7.23.4":
+ version: 7.24.1
+ resolution: "@babel/helper-string-parser@npm:7.24.1"
+ checksum: 04c0ede77b908b43e6124753b48bc485528112a9335f0a21a226bff1ace75bb6e64fab24c85cb4b1610ef3494dacd1cb807caeb6b79a7b36c43d48c289b35949
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1":
version: 7.19.1
resolution: "@babel/helper-validator-identifier@npm:7.19.1"
@@ -253,6 +375,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-validator-option@npm:^7.23.5":
+ version: 7.23.5
+ resolution: "@babel/helper-validator-option@npm:7.23.5"
+ checksum: 537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e
+ languageName: node
+ linkType: hard
+
"@babel/helpers@npm:^7.20.7":
version: 7.20.13
resolution: "@babel/helpers@npm:7.20.13"
@@ -264,6 +393,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helpers@npm:^7.24.1":
+ version: 7.24.1
+ resolution: "@babel/helpers@npm:7.24.1"
+ dependencies:
+ "@babel/template": "npm:^7.24.0"
+ "@babel/traverse": "npm:^7.24.1"
+ "@babel/types": "npm:^7.24.0"
+ checksum: 82d3cdd3beafc4583f237515ef220bc205ced8b0540c6c6e191fc367a9589bd7304b8f9800d3d7574d4db9f079bd555979816b1874c86e53b3e7dd2032ad6c7c
+ languageName: node
+ linkType: hard
+
"@babel/highlight@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/highlight@npm:7.18.6"
@@ -297,6 +437,18 @@ __metadata:
languageName: node
linkType: hard
+"@babel/highlight@npm:^7.24.2":
+ version: 7.24.2
+ resolution: "@babel/highlight@npm:7.24.2"
+ dependencies:
+ "@babel/helper-validator-identifier": "npm:^7.22.20"
+ chalk: "npm:^2.4.2"
+ js-tokens: "npm:^4.0.0"
+ picocolors: "npm:^1.0.0"
+ checksum: 4555124235f34403bb28f55b1de58edf598491cc181c75f8afc8fe529903cb598cd52fe3bf2faab9bc1f45c299681ef0e44eea7a848bb85c500c5a4fe13f54f6
+ languageName: node
+ linkType: hard
+
"@babel/parser@npm:^7.20.7":
version: 7.20.15
resolution: "@babel/parser@npm:7.20.15"
@@ -315,6 +467,26 @@ __metadata:
languageName: node
linkType: hard
+"@babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1":
+ version: 7.24.1
+ resolution: "@babel/parser@npm:7.24.1"
+ bin:
+ parser: ./bin/babel-parser.js
+ checksum: 561d9454091e07ecfec3828ce79204c0fc9d24e17763f36181c6984392be4ca6b79c8225f2224fdb7b1b3b70940e243368c8f83ac77ec2dc20f46d3d06bd6795
+ languageName: node
+ linkType: hard
+
+"@babel/plugin-transform-arrow-functions@npm:^7.23.3":
+ version: 7.24.1
+ resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.1"
+ dependencies:
+ "@babel/helper-plugin-utils": "npm:^7.24.0"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: 58f9aa9b0de8382f8cfa3f1f1d40b69d98cd2f52340e2391733d0af745fdddda650ba392e509bc056157c880a2f52834a38ab2c5aa5569af8c61bb6ecbf45f34
+ languageName: node
+ linkType: hard
+
"@babel/plugin-transform-react-jsx-self@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/plugin-transform-react-jsx-self@npm:7.18.6"
@@ -395,6 +567,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/template@npm:^7.24.0":
+ version: 7.24.0
+ resolution: "@babel/template@npm:7.24.0"
+ dependencies:
+ "@babel/code-frame": "npm:^7.23.5"
+ "@babel/parser": "npm:^7.24.0"
+ "@babel/types": "npm:^7.24.0"
+ checksum: 8c538338c7de8fac8ada691a5a812bdcbd60bd4a4eb5adae2cc9ee19773e8fb1a724312a00af9e1ce49056ffd3c3475e7287b5668cf6360bfb3f8ac827a06ffe
+ languageName: node
+ linkType: hard
+
"@babel/traverse@npm:^7.20.10, @babel/traverse@npm:^7.20.12, @babel/traverse@npm:^7.20.13":
version: 7.23.2
resolution: "@babel/traverse@npm:7.23.2"
@@ -413,6 +596,24 @@ __metadata:
languageName: node
linkType: hard
+"@babel/traverse@npm:^7.24.1":
+ version: 7.24.1
+ resolution: "@babel/traverse@npm:7.24.1"
+ dependencies:
+ "@babel/code-frame": "npm:^7.24.1"
+ "@babel/generator": "npm:^7.24.1"
+ "@babel/helper-environment-visitor": "npm:^7.22.20"
+ "@babel/helper-function-name": "npm:^7.23.0"
+ "@babel/helper-hoist-variables": "npm:^7.22.5"
+ "@babel/helper-split-export-declaration": "npm:^7.22.6"
+ "@babel/parser": "npm:^7.24.1"
+ "@babel/types": "npm:^7.24.0"
+ debug: "npm:^4.3.1"
+ globals: "npm:^11.1.0"
+ checksum: b9b0173c286ef549e179f3725df3c4958069ad79fe5b9840adeb99692eb4a5a08db4e735c0f086aab52e7e08ec711cee9e7c06cb908d8035641d1382172308d3
+ languageName: node
+ linkType: hard
+
"@babel/types@npm:^7.18.6, @babel/types@npm:^7.20.2, @babel/types@npm:^7.8.3":
version: 7.20.2
resolution: "@babel/types@npm:7.20.2"
@@ -446,6 +647,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/types@npm:^7.24.0":
+ version: 7.24.0
+ resolution: "@babel/types@npm:7.24.0"
+ dependencies:
+ "@babel/helper-string-parser": "npm:^7.23.4"
+ "@babel/helper-validator-identifier": "npm:^7.22.20"
+ to-fast-properties: "npm:^2.0.0"
+ checksum: a0b4875ce2e132f9daff0d5b27c7f4c4fcc97f2b084bdc5834e92c9d32592778489029e65d99d00c406da612d87b72d7a236c0afccaa1435c028d0c94c9b6da4
+ languageName: node
+ linkType: hard
+
"@colors/colors@npm:1.5.0":
version: 1.5.0
resolution: "@colors/colors@npm:1.5.0"
@@ -1107,22 +1319,6 @@ __metadata:
languageName: node
linkType: hard
-"@hapi/hoek@npm:^9.0.0":
- version: 9.2.1
- resolution: "@hapi/hoek@npm:9.2.1"
- checksum: dd1268451a5072b005233da5b1d13d9e2d232b22ca44526275dc8d21992a5669221ec6c0706adc4341f85e24ca0fd6988b727e356b9c436128ab4e336593c35d
- languageName: node
- linkType: hard
-
-"@hapi/topo@npm:^5.0.0":
- version: 5.1.0
- resolution: "@hapi/topo@npm:5.1.0"
- dependencies:
- "@hapi/hoek": "npm:^9.0.0"
- checksum: 084bfa647015f4fd3fdd51fadb2747d09ef2f5e1443d6cbada2988b0c88494f85edf257ec606c790db146ac4e34ff57f3fcb22e3299b8e06ed5c87ba7583495c
- languageName: node
- linkType: hard
-
"@humanwhocodes/config-array@npm:^0.11.13":
version: 0.11.14
resolution: "@humanwhocodes/config-array@npm:0.11.14"
@@ -1148,6 +1344,20 @@ __metadata:
languageName: node
linkType: hard
+"@isaacs/cliui@npm:^8.0.2":
+ version: 8.0.2
+ resolution: "@isaacs/cliui@npm:8.0.2"
+ dependencies:
+ string-width: "npm:^5.1.2"
+ string-width-cjs: "npm:string-width@^4.2.0"
+ strip-ansi: "npm:^7.0.1"
+ strip-ansi-cjs: "npm:strip-ansi@^6.0.1"
+ wrap-ansi: "npm:^8.1.0"
+ wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0"
+ checksum: e9ed5fd27c3aec1095e3a16e0c0cf148d1fee55a38665c35f7b3f86a9b5d00d042ddaabc98e8a1cb7463b9378c15f22a94eb35e99469c201453eb8375191f243
+ languageName: node
+ linkType: hard
+
"@jest/schemas@npm:^29.6.3":
version: 29.6.3
resolution: "@jest/schemas@npm:29.6.3"
@@ -1178,6 +1388,17 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/gen-mapping@npm:^0.3.5":
+ version: 0.3.5
+ resolution: "@jridgewell/gen-mapping@npm:0.3.5"
+ dependencies:
+ "@jridgewell/set-array": "npm:^1.2.1"
+ "@jridgewell/sourcemap-codec": "npm:^1.4.10"
+ "@jridgewell/trace-mapping": "npm:^0.3.24"
+ checksum: 81587b3c4dd8e6c60252122937cea0c637486311f4ed208b52b62aae2e7a87598f63ec330e6cd0984af494bfb16d3f0d60d3b21d7e5b4aedd2602ff3fe9d32e2
+ languageName: node
+ linkType: hard
+
"@jridgewell/resolve-uri@npm:^3.0.3":
version: 3.1.0
resolution: "@jridgewell/resolve-uri@npm:3.1.0"
@@ -1199,6 +1420,13 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/set-array@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "@jridgewell/set-array@npm:1.2.1"
+ checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10
+ languageName: node
+ linkType: hard
+
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13":
version: 1.4.14
resolution: "@jridgewell/sourcemap-codec@npm:1.4.14"
@@ -1223,6 +1451,16 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25":
+ version: 0.3.25
+ resolution: "@jridgewell/trace-mapping@npm:0.3.25"
+ dependencies:
+ "@jridgewell/resolve-uri": "npm:^3.1.0"
+ "@jridgewell/sourcemap-codec": "npm:^1.4.14"
+ checksum: dced32160a44b49d531b80a4a2159dceab6b3ddf0c8e95a0deae4b0e894b172defa63d5ac52a19c2068e1fe7d31ea4ba931fbeec103233ecb4208953967120fc
+ languageName: node
+ linkType: hard
+
"@jridgewell/trace-mapping@npm:^0.3.9":
version: 0.3.14
resolution: "@jridgewell/trace-mapping@npm:0.3.14"
@@ -1366,6 +1604,95 @@ __metadata:
languageName: node
linkType: hard
+"@octokit/auth-token@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@octokit/auth-token@npm:4.0.0"
+ checksum: 60e42701e341d700f73c518c7a35675d36d79fa9d5e838cc3ade96d147e49f5ba74db2e07b2337c2b95aaa540aa42088116df2122daa25633f9e70a2c8785c44
+ languageName: node
+ linkType: hard
+
+"@octokit/core@npm:5":
+ version: 5.1.0
+ resolution: "@octokit/core@npm:5.1.0"
+ dependencies:
+ "@octokit/auth-token": "npm:^4.0.0"
+ "@octokit/graphql": "npm:^7.0.0"
+ "@octokit/request": "npm:^8.0.2"
+ "@octokit/request-error": "npm:^5.0.0"
+ "@octokit/types": "npm:^12.0.0"
+ before-after-hook: "npm:^2.2.0"
+ universal-user-agent: "npm:^6.0.0"
+ checksum: 8062e86a3088f24a691b36d2c3e9f33e864cefcb5f544b0633650358bce280708b111551cbe855ecf6a5190d6fc4fec1220117c329a2c27525940dd97b868614
+ languageName: node
+ linkType: hard
+
+"@octokit/endpoint@npm:^9.0.0":
+ version: 9.0.4
+ resolution: "@octokit/endpoint@npm:9.0.4"
+ dependencies:
+ "@octokit/types": "npm:^12.0.0"
+ universal-user-agent: "npm:^6.0.0"
+ checksum: 7df35c96f2b5628fe5b3f44a72614be9b439779c06b4dd1bb72283b3cb2ea53e59e1f9a108798efe5404b6856f4380a4c5be12d93255d854f0683cd6e22f3a27
+ languageName: node
+ linkType: hard
+
+"@octokit/graphql@npm:^7.0.0":
+ version: 7.0.2
+ resolution: "@octokit/graphql@npm:7.0.2"
+ dependencies:
+ "@octokit/request": "npm:^8.0.1"
+ "@octokit/types": "npm:^12.0.0"
+ universal-user-agent: "npm:^6.0.0"
+ checksum: f5dcc51fed5304f65dab83fcea4c2a569107d3b71e8d084199dc44f0d0cfc852c9e1f341b06ae66601f9da4af3aad416b0c62dcd0567ac7568f072d8d90d502e
+ languageName: node
+ linkType: hard
+
+"@octokit/openapi-types@npm:^20.0.0":
+ version: 20.0.0
+ resolution: "@octokit/openapi-types@npm:20.0.0"
+ checksum: 9f60572af1201dd92626c412253d83d986b8ab1956250b95f417013ee8e7baf25870eeb801d16672cabc2c420544bc9c2f0a979e07603ff5997eff038c71a8c3
+ languageName: node
+ linkType: hard
+
+"@octokit/request-error@npm:^5.0.0":
+ version: 5.0.1
+ resolution: "@octokit/request-error@npm:5.0.1"
+ dependencies:
+ "@octokit/types": "npm:^12.0.0"
+ deprecation: "npm:^2.0.0"
+ once: "npm:^1.4.0"
+ checksum: a21a4614c46cb173e4ba73fa048576204f1ddc541dee3e7c938ef36088566e3b25e04ca1f96f375ec2e3cc29b7ba970b3b078a89a20bc50cdcdbed879db94573
+ languageName: node
+ linkType: hard
+
+"@octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2":
+ version: 8.2.0
+ resolution: "@octokit/request@npm:8.2.0"
+ dependencies:
+ "@octokit/endpoint": "npm:^9.0.0"
+ "@octokit/request-error": "npm:^5.0.0"
+ "@octokit/types": "npm:^12.0.0"
+ universal-user-agent: "npm:^6.0.0"
+ checksum: 553ba8b99ea6fe2d3b66b2be6df06f7fe62a0b81e441d334ef25388cf0fcdab4a888fcfe2c1fb1ada262c233bcf7169da3ad5e03f024060ea5723f7753b0de3e
+ languageName: node
+ linkType: hard
+
+"@octokit/types@npm:^12.0.0":
+ version: 12.6.0
+ resolution: "@octokit/types@npm:12.6.0"
+ dependencies:
+ "@octokit/openapi-types": "npm:^20.0.0"
+ checksum: 19b77a8d25af2a5df4561f8750f807edfc9fca5b07cfa9fb21dce4665e1b188c966688f5ed5e08089404428100dfe44ad353f8d8532f1d30fe47e61c5faa1440
+ languageName: node
+ linkType: hard
+
+"@pkgjs/parseargs@npm:^0.11.0":
+ version: 0.11.0
+ resolution: "@pkgjs/parseargs@npm:0.11.0"
+ checksum: 115e8ceeec6bc69dff2048b35c0ab4f8bbee12d8bb6c1f4af758604586d802b6e669dcb02dda61d078de42c2b4ddce41b3d9e726d7daa6b4b850f4adbf7333ff
+ languageName: node
+ linkType: hard
+
"@radix-ui/colors@npm:^0.1.8":
version: 0.1.8
resolution: "@radix-ui/colors@npm:0.1.8"
@@ -1607,29 +1934,6 @@ __metadata:
languageName: node
linkType: hard
-"@sideway/address@npm:^4.1.3":
- version: 4.1.3
- resolution: "@sideway/address@npm:4.1.3"
- dependencies:
- "@hapi/hoek": "npm:^9.0.0"
- checksum: 7224cd7127abb315573bd697836a1277edaaf4a93043e0ea76d5584191937e350dab85191176e19e3dbaa0ece888267bfcaa6e2c41541e151bdb0f7209a814f3
- languageName: node
- linkType: hard
-
-"@sideway/formula@npm:^3.0.1":
- version: 3.0.1
- resolution: "@sideway/formula@npm:3.0.1"
- checksum: 8d3ee7f80df4e5204b2cbe92a2a711ca89684965a5c9eb3b316b7051212d3522e332a65a0bb2a07cc708fcd1d0b27fcb30f43ff0bcd5089d7006c7160a89eefe
- languageName: node
- linkType: hard
-
-"@sideway/pinpoint@npm:^2.0.0":
- version: 2.0.0
- resolution: "@sideway/pinpoint@npm:2.0.0"
- checksum: 1ed21800128b2b23280ba4c9db26c8ff6142b97a8683f17639fd7f2128aa09046461574800b30fb407afc5b663c2331795ccf3b654d4b38fa096e41a5c786bf8
- languageName: node
- linkType: hard
-
"@sinclair/typebox@npm:^0.27.8":
version: 0.27.8
resolution: "@sinclair/typebox@npm:0.27.8"
@@ -1667,6 +1971,13 @@ __metadata:
languageName: node
linkType: hard
+"@tsconfig/node18@npm:^18.2.2":
+ version: 18.2.2
+ resolution: "@tsconfig/node18@npm:18.2.2"
+ checksum: 1c4b04b570e33de14bf518492e077079db2dcfba738c8d40c6ff916d94c9410246f4cb56f0802d9771423862140bf714c35d4a5f6cec2446d851cf61d3f8f9df
+ languageName: node
+ linkType: hard
+
"@tsconfig/strictest@npm:^2.0.2":
version: 2.0.2
resolution: "@tsconfig/strictest@npm:2.0.2"
@@ -1681,6 +1992,16 @@ __metadata:
languageName: node
linkType: hard
+"@types/body-parser@npm:*":
+ version: 1.19.5
+ resolution: "@types/body-parser@npm:1.19.5"
+ dependencies:
+ "@types/connect": "npm:*"
+ "@types/node": "npm:*"
+ checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82
+ languageName: node
+ linkType: hard
+
"@types/cacheable-request@npm:^6.0.1":
version: 6.0.3
resolution: "@types/cacheable-request@npm:6.0.3"
@@ -1718,6 +2039,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/connect@npm:*":
+ version: 3.4.38
+ resolution: "@types/connect@npm:3.4.38"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99
+ languageName: node
+ linkType: hard
+
"@types/css-modules@npm:^1.0.5":
version: 1.0.5
resolution: "@types/css-modules@npm:1.0.5"
@@ -1751,6 +2081,30 @@ __metadata:
languageName: node
linkType: hard
+"@types/express-serve-static-core@npm:^4.17.33":
+ version: 4.17.43
+ resolution: "@types/express-serve-static-core@npm:4.17.43"
+ dependencies:
+ "@types/node": "npm:*"
+ "@types/qs": "npm:*"
+ "@types/range-parser": "npm:*"
+ "@types/send": "npm:*"
+ checksum: 9079e137470e0456bb8e77ae66df9505ee12591e94860bde574cfe52c5c60bbc5bf7dd44f5689c3cbb1baf0aa84442d9a21f53dcd921d18745727293cd5a5fd6
+ languageName: node
+ linkType: hard
+
+"@types/express@npm:^4.17.21":
+ version: 4.17.21
+ resolution: "@types/express@npm:4.17.21"
+ dependencies:
+ "@types/body-parser": "npm:*"
+ "@types/express-serve-static-core": "npm:^4.17.33"
+ "@types/qs": "npm:*"
+ "@types/serve-static": "npm:*"
+ checksum: 7a6d26cf6f43d3151caf4fec66ea11c9d23166e4f3102edfe45a94170654a54ea08cf3103d26b3928d7ebcc24162c90488e33986b7e3a5f8941225edd5eb18c7
+ languageName: node
+ linkType: hard
+
"@types/fs-extra@npm:9.0.13, @types/fs-extra@npm:^9.0.11":
version: 9.0.13
resolution: "@types/fs-extra@npm:9.0.13"
@@ -1776,6 +2130,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/http-errors@npm:*":
+ version: 2.0.4
+ resolution: "@types/http-errors@npm:2.0.4"
+ checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3
+ languageName: node
+ linkType: hard
+
"@types/js-cookie@npm:^2.2.6":
version: 2.2.7
resolution: "@types/js-cookie@npm:2.2.7"
@@ -1813,6 +2174,27 @@ __metadata:
languageName: node
linkType: hard
+"@types/luxon@npm:^3.4.2":
+ version: 3.4.2
+ resolution: "@types/luxon@npm:3.4.2"
+ checksum: fd89566e3026559f2bc4ddcc1e70a2c16161905ed50be9473ec0cfbbbe919165041408c4f6e06c4bcf095445535052e2c099087c76b1b38e368127e618fc968d
+ languageName: node
+ linkType: hard
+
+"@types/mime@npm:*":
+ version: 3.0.4
+ resolution: "@types/mime@npm:3.0.4"
+ checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843
+ languageName: node
+ linkType: hard
+
+"@types/mime@npm:^1":
+ version: 1.3.5
+ resolution: "@types/mime@npm:1.3.5"
+ checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78
+ languageName: node
+ linkType: hard
+
"@types/minimatch@npm:^3.0.3":
version: 3.0.5
resolution: "@types/minimatch@npm:3.0.5"
@@ -1820,6 +2202,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/morgan@npm:^1.9.9":
+ version: 1.9.9
+ resolution: "@types/morgan@npm:1.9.9"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: a6969b4494de964d6b682fce93decd51988ec15a69be0d2766adacd5e942e06d9b4a5cad1708d6698b242edc5dee76ec6f909b81d68e148eb0634a0b6a4efb66
+ languageName: node
+ linkType: hard
+
"@types/ms@npm:*":
version: 0.7.31
resolution: "@types/ms@npm:0.7.31"
@@ -1874,6 +2265,20 @@ __metadata:
languageName: node
linkType: hard
+"@types/qs@npm:*":
+ version: 6.9.14
+ resolution: "@types/qs@npm:6.9.14"
+ checksum: d3b76021d36b86c0063ec4b7373e9fa470754914e486fbfe54b3a8866dad037800a2c2068ecbcaa9399ae3ed15772a26b07e67793ed2519cf2de199104014716
+ languageName: node
+ linkType: hard
+
+"@types/range-parser@npm:*":
+ version: 1.2.7
+ resolution: "@types/range-parser@npm:1.2.7"
+ checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a
+ languageName: node
+ linkType: hard
+
"@types/react-dom@npm:^18.2.22":
version: 18.2.22
resolution: "@types/react-dom@npm:18.2.22"
@@ -1955,6 +2360,27 @@ __metadata:
languageName: node
linkType: hard
+"@types/send@npm:*":
+ version: 0.17.4
+ resolution: "@types/send@npm:0.17.4"
+ dependencies:
+ "@types/mime": "npm:^1"
+ "@types/node": "npm:*"
+ checksum: 28320a2aa1eb704f7d96a65272a07c0bf3ae7ed5509c2c96ea5e33238980f71deeed51d3631927a77d5250e4091b3e66bce53b42d770873282c6a20bb8b0280d
+ languageName: node
+ linkType: hard
+
+"@types/serve-static@npm:*":
+ version: 1.15.5
+ resolution: "@types/serve-static@npm:1.15.5"
+ dependencies:
+ "@types/http-errors": "npm:*"
+ "@types/mime": "npm:*"
+ "@types/node": "npm:*"
+ checksum: 49aa21c367fffe4588fc8c57ea48af0ea7cbadde7418bc53cde85d8bd57fd2a09a293970d9ea86e79f17a87f8adeb3e20da76aab38e1c4d1567931fa15c8af38
+ languageName: node
+ linkType: hard
+
"@types/sortablejs@npm:^1.15.0":
version: 1.15.0
resolution: "@types/sortablejs@npm:1.15.0"
@@ -1983,6 +2409,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/yargs-parser@npm:^21.0.3":
+ version: 21.0.3
+ resolution: "@types/yargs-parser@npm:21.0.3"
+ checksum: a794eb750e8ebc6273a51b12a0002de41343ffe46befef460bdbb57262d187fdf608bc6615b7b11c462c63c3ceb70abe2564c8dd8ee0f7628f38a314f74a9b9b
+ languageName: node
+ linkType: hard
+
"@types/yauzl@npm:^2.9.1":
version: 2.10.0
resolution: "@types/yauzl@npm:2.10.0"
@@ -2318,13 +2751,6 @@ __metadata:
languageName: node
linkType: hard
-"ansi-regex@npm:^2.0.0":
- version: 2.1.1
- resolution: "ansi-regex@npm:2.1.1"
- checksum: 190abd03e4ff86794f338a31795d262c1dfe8c91f7e01d04f13f646f1dcb16c5800818f886047876f1272f065570ab86b24b99089f8b68a0e11ff19aed4ca8f1
- languageName: node
- linkType: hard
-
"ansi-regex@npm:^5.0.1":
version: 5.0.1
resolution: "ansi-regex@npm:5.0.1"
@@ -2332,6 +2758,13 @@ __metadata:
languageName: node
linkType: hard
+"ansi-regex@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "ansi-regex@npm:6.0.1"
+ checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169
+ languageName: node
+ linkType: hard
+
"ansi-styles@npm:^3.2.1":
version: 3.2.1
resolution: "ansi-styles@npm:3.2.1"
@@ -2357,6 +2790,13 @@ __metadata:
languageName: node
linkType: hard
+"ansi-styles@npm:^6.1.0":
+ version: 6.2.1
+ resolution: "ansi-styles@npm:6.2.1"
+ checksum: 70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32
+ languageName: node
+ linkType: hard
+
"app-builder-bin@npm:4.0.0":
version: 4.0.0
resolution: "app-builder-bin@npm:4.0.0"
@@ -2445,13 +2885,6 @@ __metadata:
languageName: node
linkType: hard
-"aproba@npm:^1.0.3":
- version: 1.2.0
- resolution: "aproba@npm:1.2.0"
- checksum: 48def777330afca699880126b555273cd9912525500edc5866b527da6fd6c54badd3ae6cc6039081e5bc22e9b349d8e65fd70f8499beb090f86aa6261e4242dd
- languageName: node
- linkType: hard
-
"aproba@npm:^1.0.3 || ^2.0.0":
version: 2.0.0
resolution: "aproba@npm:2.0.0"
@@ -2469,16 +2902,6 @@ __metadata:
languageName: node
linkType: hard
-"are-we-there-yet@npm:~1.1.2":
- version: 1.1.7
- resolution: "are-we-there-yet@npm:1.1.7"
- dependencies:
- delegates: "npm:^1.0.0"
- readable-stream: "npm:^2.0.6"
- checksum: 5fc14ea29ed1ae480117c177b31c6e6da6f02c0fd6d5071b7e4a1373adf42539f5d81f178358dab58b10fc929bf7650c5ed0153ae9cc98eff97285189cb6b836
- languageName: node
- linkType: hard
-
"argparse@npm:^2.0.1":
version: 2.0.1
resolution: "argparse@npm:2.0.1"
@@ -2706,25 +3129,6 @@ __metadata:
languageName: node
linkType: hard
-"axios@npm:^0.21.1":
- version: 0.21.4
- resolution: "axios@npm:0.21.4"
- dependencies:
- follow-redirects: "npm:^1.14.0"
- checksum: da644592cb6f8f9f8c64fdabd7e1396d6769d7a4c1ea5f8ae8beb5c2eb90a823e3a574352b0b934ac62edc762c0f52647753dc54f7d07279127a7e5c4cd20272
- languageName: node
- linkType: hard
-
-"axios@npm:^0.27.2":
- version: 0.27.2
- resolution: "axios@npm:0.27.2"
- dependencies:
- follow-redirects: "npm:^1.14.9"
- form-data: "npm:^4.0.0"
- checksum: 2efaf18dd0805f7bc772882bc86f004abd92d51007b54c5081f74db0d08ce3593e2c010261896d25a14318eeaa2e966fd825e34f810e8a3339dc64b9d177cf70
- languageName: node
- linkType: hard
-
"axobject-query@npm:^3.2.1":
version: 3.2.1
resolution: "axobject-query@npm:3.2.1"
@@ -2764,6 +3168,13 @@ __metadata:
languageName: node
linkType: hard
+"before-after-hook@npm:^2.2.0":
+ version: 2.2.3
+ resolution: "before-after-hook@npm:2.2.3"
+ checksum: e676f769dbc4abcf4b3317db2fd2badb4a92c0710e0a7da12cf14b59c3482d4febf835ad7de7874499060fd4e13adf0191628e504728b3c5bb4ec7a878c09940
+ languageName: node
+ linkType: hard
+
"bl@npm:^4.0.3":
version: 4.1.0
resolution: "bl@npm:4.1.0"
@@ -2914,7 +3325,7 @@ __metadata:
languageName: node
linkType: hard
-"browserslist@npm:^4.22.3":
+"browserslist@npm:^4.22.2, browserslist@npm:^4.22.3":
version: 4.23.0
resolution: "browserslist@npm:4.23.0"
dependencies:
@@ -3349,16 +3760,9 @@ __metadata:
resolution: "cloneable-readable@npm:1.1.3"
dependencies:
inherits: "npm:^2.0.1"
- process-nextick-args: "npm:^2.0.0"
- readable-stream: "npm:^2.3.5"
- checksum: 81e17fe4b2901e2d9899717e1d4ed88bd1ede700b819b77c61f7402b9ca97c4769692d85bd74710be806f31caf33c62acdea49d5bbe8794a66ade01c9c2d5a6d
- languageName: node
- linkType: hard
-
-"code-point-at@npm:^1.0.0":
- version: 1.1.0
- resolution: "code-point-at@npm:1.1.0"
- checksum: 17d5666611f9b16d64fdf48176d9b7fb1c7d1c1607a189f7e600040a11a6616982876af148230336adb7d8fe728a559f743a4e29db3747e3b1a32fa7f4529681
+ process-nextick-args: "npm:^2.0.0"
+ readable-stream: "npm:^2.3.5"
+ checksum: 81e17fe4b2901e2d9899717e1d4ed88bd1ede700b819b77c61f7402b9ca97c4769692d85bd74710be806f31caf33c62acdea49d5bbe8794a66ade01c9c2d5a6d
languageName: node
linkType: hard
@@ -3423,7 +3827,7 @@ __metadata:
languageName: node
linkType: hard
-"color@npm:^4.0.1, color@npm:^4.2.3":
+"color@npm:^4.2.3":
version: 4.2.3
resolution: "color@npm:4.2.3"
dependencies:
@@ -3573,7 +3977,7 @@ __metadata:
languageName: node
linkType: hard
-"console-control-strings@npm:^1.0.0, console-control-strings@npm:^1.1.0, console-control-strings@npm:~1.1.0":
+"console-control-strings@npm:^1.1.0":
version: 1.1.0
resolution: "console-control-strings@npm:1.1.0"
checksum: 27b5fa302bc8e9ae9e98c03c66d76ca289ad0c61ce2fe20ab288d288bee875d217512d2edb2363fc83165e88f1c405180cf3f5413a46e51b4fe1a004840c6cdb
@@ -3605,6 +4009,13 @@ __metadata:
languageName: node
linkType: hard
+"convert-source-map@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "convert-source-map@npm:2.0.0"
+ checksum: c987be3ec061348cdb3c2bfb924bec86dea1eacad10550a85ca23edb0fe3556c3a61c7399114f3331ccb3499d7fd0285ab24566e5745929412983494c3926e15
+ languageName: node
+ linkType: hard
+
"cookie-signature@npm:1.0.6":
version: 1.0.6
resolution: "cookie-signature@npm:1.0.6"
@@ -3667,19 +4078,7 @@ __metadata:
languageName: node
linkType: hard
-"cross-env@npm:^7.0.3":
- version: 7.0.3
- resolution: "cross-env@npm:7.0.3"
- dependencies:
- cross-spawn: "npm:^7.0.1"
- bin:
- cross-env: src/bin/cross-env.js
- cross-env-shell: src/bin/cross-env-shell.js
- checksum: e99911f0d31c20e990fd92d6fd001f4b01668a303221227cc5cb42ed155f086351b1b3bd2699b200e527ab13011b032801f8ce638e6f09f854bdf744095e604c
- languageName: node
- linkType: hard
-
-"cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
+"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
dependencies:
@@ -3909,22 +4308,6 @@ __metadata:
languageName: node
linkType: hard
-"del@npm:^6.0.0":
- version: 6.0.0
- resolution: "del@npm:6.0.0"
- dependencies:
- globby: "npm:^11.0.1"
- graceful-fs: "npm:^4.2.4"
- is-glob: "npm:^4.0.1"
- is-path-cwd: "npm:^2.2.0"
- is-path-inside: "npm:^3.0.2"
- p-map: "npm:^4.0.0"
- rimraf: "npm:^3.0.2"
- slash: "npm:^3.0.0"
- checksum: 5742891627e91aaf62385714025233f4664da28bc55b6ab825649dcdea4691fed3cf329a2b1913fd2d2612e693e99e08a03c84cac7f36ef54bacac9390520192
- languageName: node
- linkType: hard
-
"delayed-stream@npm:~1.0.0":
version: 1.0.0
resolution: "delayed-stream@npm:1.0.0"
@@ -3953,6 +4336,13 @@ __metadata:
languageName: node
linkType: hard
+"deprecation@npm:^2.0.0":
+ version: 2.3.1
+ resolution: "deprecation@npm:2.3.1"
+ checksum: f56a05e182c2c195071385455956b0c4106fe14e36245b00c689ceef8e8ab639235176a96977ba7c74afb173317fac2e0ec6ec7a1c6d1e6eaa401c586c714132
+ languageName: node
+ linkType: hard
+
"dequal@npm:^2.0.3":
version: 2.0.3
resolution: "dequal@npm:2.0.3"
@@ -3967,15 +4357,6 @@ __metadata:
languageName: node
linkType: hard
-"detect-libc@npm:^1.0.3":
- version: 1.0.3
- resolution: "detect-libc@npm:1.0.3"
- bin:
- detect-libc: ./bin/detect-libc.js
- checksum: 3849fe7720feb153e4ac9407086956e073f1ce1704488290ef0ca8aab9430a8d48c8a9f8351889e7cdc64e5b1128589501e4fef48f3a4a49ba92cd6d112d0757
- languageName: node
- linkType: hard
-
"detect-libc@npm:^2.0.0":
version: 2.0.1
resolution: "detect-libc@npm:2.0.1"
@@ -4174,6 +4555,13 @@ __metadata:
languageName: node
linkType: hard
+"eastasianwidth@npm:^0.2.0":
+ version: 0.2.0
+ resolution: "eastasianwidth@npm:0.2.0"
+ checksum: 9b1d3e1baefeaf7d70799db8774149cef33b97183a6addceeba0cf6b85ba23ee2686f302f14482006df32df75d32b17c509c143a3689627929e4a8efaf483952
+ languageName: node
+ linkType: hard
+
"ee-first@npm:1.1.1":
version: 1.1.1
resolution: "ee-first@npm:1.1.1"
@@ -4285,6 +4673,28 @@ __metadata:
languageName: node
linkType: hard
+"electron-vite@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "electron-vite@npm:2.1.0"
+ dependencies:
+ "@babel/core": "npm:^7.23.5"
+ "@babel/plugin-transform-arrow-functions": "npm:^7.23.3"
+ cac: "npm:^6.7.14"
+ esbuild: "npm:^0.19.8"
+ magic-string: "npm:^0.30.5"
+ picocolors: "npm:^1.0.0"
+ peerDependencies:
+ "@swc/core": ^1.0.0
+ vite: ^4.0.0 || ^5.0.0
+ peerDependenciesMeta:
+ "@swc/core":
+ optional: true
+ bin:
+ electron-vite: bin/electron-vite.js
+ checksum: 29f1d1d80e88db27952ba0ba7039dccfe161acd20186e0d6d2a7af5e38a303821e3ab09d058041d9d929e6c2fabdae95d182c1f38872946872100e837ff9e9b5
+ languageName: node
+ linkType: hard
+
"electron@npm:^27.0.0":
version: 27.0.0
resolution: "electron@npm:27.0.0"
@@ -4691,7 +5101,7 @@ __metadata:
languageName: node
linkType: hard
-"esbuild@npm:^0.19.3":
+"esbuild@npm:^0.19.3, esbuild@npm:^0.19.8, esbuild@npm:~0.19.10":
version: 0.19.12
resolution: "esbuild@npm:0.19.12"
dependencies:
@@ -5151,23 +5561,6 @@ __metadata:
languageName: node
linkType: hard
-"execa@npm:5":
- version: 5.1.1
- resolution: "execa@npm:5.1.1"
- dependencies:
- cross-spawn: "npm:^7.0.3"
- get-stream: "npm:^6.0.0"
- human-signals: "npm:^2.1.0"
- is-stream: "npm:^2.0.0"
- merge-stream: "npm:^2.0.0"
- npm-run-path: "npm:^4.0.1"
- onetime: "npm:^5.1.2"
- signal-exit: "npm:^3.0.3"
- strip-final-newline: "npm:^2.0.0"
- checksum: 8ada91f2d70f7dff702c861c2c64f21dfdc1525628f3c0454fd6f02fce65f7b958616cbd2b99ca7fa4d474e461a3d363824e91b3eb881705231abbf387470597
- languageName: node
- linkType: hard
-
"execa@npm:^8.0.1":
version: 8.0.1
resolution: "execa@npm:8.0.1"
@@ -5515,16 +5908,6 @@ __metadata:
languageName: node
linkType: hard
-"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.9":
- version: 1.15.6
- resolution: "follow-redirects@npm:1.15.6"
- peerDependenciesMeta:
- debug:
- optional: true
- checksum: 70c7612c4cab18e546e36b991bbf8009a1a41cf85354afe04b113d1117569abf760269409cb3eb842d9f7b03d62826687086b081c566ea7b1e6613cf29030bf7
- languageName: node
- linkType: hard
-
"for-each@npm:^0.3.3":
version: 0.3.3
resolution: "for-each@npm:0.3.3"
@@ -5534,6 +5917,16 @@ __metadata:
languageName: node
linkType: hard
+"foreground-child@npm:^3.1.0":
+ version: 3.1.1
+ resolution: "foreground-child@npm:3.1.1"
+ dependencies:
+ cross-spawn: "npm:^7.0.0"
+ signal-exit: "npm:^4.0.1"
+ checksum: 087edd44857d258c4f73ad84cb8df980826569656f2550c341b27adf5335354393eec24ea2fabd43a253233fb27cee177ebe46bd0b7ea129c77e87cb1e9936fb
+ languageName: node
+ linkType: hard
+
"form-data@npm:^4.0.0":
version: 4.0.0
resolution: "form-data@npm:4.0.0"
@@ -5793,22 +6186,6 @@ __metadata:
languageName: node
linkType: hard
-"gauge@npm:~2.7.3":
- version: 2.7.4
- resolution: "gauge@npm:2.7.4"
- dependencies:
- aproba: "npm:^1.0.3"
- console-control-strings: "npm:^1.0.0"
- has-unicode: "npm:^2.0.0"
- object-assign: "npm:^4.1.0"
- signal-exit: "npm:^3.0.0"
- string-width: "npm:^1.0.1"
- strip-ansi: "npm:^3.0.1"
- wide-align: "npm:^1.1.0"
- checksum: 0db20a7def238f0e8eab50226247e1f94f1446ab24700eab0a56e5ccf23ce85ccf8f0c0c462112b89beb964431b1edabd3f7b31f1f6d5f62294c453594523993
- languageName: node
- linkType: hard
-
"gensync@npm:^1.0.0-beta.2":
version: 1.0.0-beta.2
resolution: "gensync@npm:1.0.0-beta.2"
@@ -5863,13 +6240,6 @@ __metadata:
languageName: node
linkType: hard
-"get-stream@npm:^6.0.0":
- version: 6.0.1
- resolution: "get-stream@npm:6.0.1"
- checksum: 781266d29725f35c59f1d214aedc92b0ae855800a980800e2923b3fbc4e56b3cb6e462c42e09a1cf1a00c64e056a78fa407cbe06c7c92b7e5cd49b4b85c2a497
- languageName: node
- linkType: hard
-
"get-stream@npm:^8.0.1":
version: 8.0.1
resolution: "get-stream@npm:8.0.1"
@@ -5888,15 +6258,12 @@ __metadata:
languageName: node
linkType: hard
-"github-api@npm:^3.2.2":
- version: 3.4.0
- resolution: "github-api@npm:3.4.0"
+"get-tsconfig@npm:^4.7.2":
+ version: 4.7.3
+ resolution: "get-tsconfig@npm:4.7.3"
dependencies:
- axios: "npm:^0.21.1"
- debug: "npm:^2.2.0"
- js-base64: "npm:^2.1.9"
- utf8: "npm:^2.1.1"
- checksum: fdf48af33b1ec8eeeb37cceca102d21f82a9de6da6e31aa355bbcddf92af24d17938b7eebbc3e9c3a327944ccc5d9b5526e3d7cbc0b5371091969432dcd07d62
+ resolve-pkg-maps: "npm:^1.0.0"
+ checksum: 7397bb4f8aef936df4d9016555b662dcf5279f3c46428b7c7c1ff5e94ab2b87d018b3dda0f4bc1a28b154d5affd0eac5d014511172c085fd8a9cdff9ea7fe043
languageName: node
linkType: hard
@@ -5966,6 +6333,21 @@ __metadata:
languageName: node
linkType: hard
+"glob@npm:^10.3.7":
+ version: 10.3.10
+ resolution: "glob@npm:10.3.10"
+ dependencies:
+ foreground-child: "npm:^3.1.0"
+ jackspeak: "npm:^2.3.5"
+ minimatch: "npm:^9.0.1"
+ minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0"
+ path-scurry: "npm:^1.10.1"
+ bin:
+ glob: dist/esm/bin.mjs
+ checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8
+ languageName: node
+ linkType: hard
+
"glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6":
version: 7.2.0
resolution: "glob@npm:7.2.0"
@@ -6041,7 +6423,7 @@ __metadata:
languageName: node
linkType: hard
-"globby@npm:^11.0.1, globby@npm:^11.1.0":
+"globby@npm:^11.1.0":
version: 11.1.0
resolution: "globby@npm:11.1.0"
dependencies:
@@ -6083,7 +6465,7 @@ __metadata:
languageName: node
linkType: hard
-"graceful-fs@npm:^4.0.0, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6":
+"graceful-fs@npm:^4.0.0, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6":
version: 4.2.9
resolution: "graceful-fs@npm:4.2.9"
checksum: 4bcf2de4f1108a928dd64d5e894b833cba634b2e82729c0e57f327d384bf15098e4706639f3045e587e845afed06bae52e70916f74a42db5a56e9ca44f6c2fd1
@@ -6166,7 +6548,7 @@ __metadata:
languageName: node
linkType: hard
-"has-unicode@npm:^2.0.0, has-unicode@npm:^2.0.1":
+"has-unicode@npm:^2.0.1":
version: 2.0.1
resolution: "has-unicode@npm:2.0.1"
checksum: 041b4293ad6bf391e21c5d85ed03f412506d6623786b801c4ab39e4e6ca54993f13201bceb544d92963f9e0024e6e7fbf0cb1d84c9d6b31cb9c79c8c990d13d8
@@ -6351,13 +6733,6 @@ __metadata:
languageName: node
linkType: hard
-"human-signals@npm:^2.1.0":
- version: 2.1.0
- resolution: "human-signals@npm:2.1.0"
- checksum: df59be9e0af479036798a881d1f136c4a29e0b518d4abb863afbd11bf30efa3eeb1d0425fc65942dcc05ab3bf40205ea436b0ff389f2cd20b75b8643d539bf86
- languageName: node
- linkType: hard
-
"human-signals@npm:^5.0.0":
version: 5.0.0
resolution: "human-signals@npm:5.0.0"
@@ -6434,19 +6809,16 @@ __metadata:
languageName: node
linkType: hard
-"icon-gen@npm:^3.0.0":
- version: 3.0.0
- resolution: "icon-gen@npm:3.0.0"
+"icon-gen@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "icon-gen@npm:4.0.0"
dependencies:
commander: "npm:^8.3.0"
- del: "npm:^6.0.0"
- mkdirp: "npm:^1.0.4"
- pngjs: "npm:^6.0.0"
- sharp: "npm:^0.29.3"
- uuid: "npm:^8.3.2"
+ pngjs: "npm:^7.0.0"
+ sharp: "npm:^0.32.4"
bin:
icon-gen: dist/bin/index.js
- checksum: e695d5abcc3375f158e90f19d60af4b3fef95e571d6934287ce952f63f39d2ce8a9dc4411a0c974a732deb67cbd8a70430b16cde78027f24c5cc2c2dcbd964cc
+ checksum: d4c829659dfe2cde2379ea5bfae4fba2efed04af3f60aa12eecca8f4b92b2c0f82a266b044ac70db5d9869f787264bb22aab17336a5e73580c018408d8235a88
languageName: node
linkType: hard
@@ -6782,15 +7154,6 @@ __metadata:
languageName: node
linkType: hard
-"is-fullwidth-code-point@npm:^1.0.0":
- version: 1.0.0
- resolution: "is-fullwidth-code-point@npm:1.0.0"
- dependencies:
- number-is-nan: "npm:^1.0.0"
- checksum: 4d46a7465a66a8aebcc5340d3b63a56602133874af576a9ca42c6f0f4bd787a743605771c5f246db77da96605fefeffb65fc1dbe862dcc7328f4b4d03edf5a57
- languageName: node
- linkType: hard
-
"is-fullwidth-code-point@npm:^3.0.0":
version: 3.0.0
resolution: "is-fullwidth-code-point@npm:3.0.0"
@@ -6890,14 +7253,7 @@ __metadata:
languageName: node
linkType: hard
-"is-path-cwd@npm:^2.2.0":
- version: 2.2.0
- resolution: "is-path-cwd@npm:2.2.0"
- checksum: 46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048
- languageName: node
- linkType: hard
-
-"is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3":
+"is-path-inside@npm:^3.0.3":
version: 3.0.3
resolution: "is-path-inside@npm:3.0.3"
checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9
@@ -7122,6 +7478,19 @@ __metadata:
languageName: node
linkType: hard
+"jackspeak@npm:^2.3.5":
+ version: 2.3.6
+ resolution: "jackspeak@npm:2.3.6"
+ dependencies:
+ "@isaacs/cliui": "npm:^8.0.2"
+ "@pkgjs/parseargs": "npm:^0.11.0"
+ dependenciesMeta:
+ "@pkgjs/parseargs":
+ optional: true
+ checksum: 6e6490d676af8c94a7b5b29b8fd5629f21346911ebe2e32931c2a54210134408171c24cee1a109df2ec19894ad04a429402a8438cbf5cc2794585d35428ace76
+ languageName: node
+ linkType: hard
+
"jake@npm:^10.8.5":
version: 10.8.5
resolution: "jake@npm:10.8.5"
@@ -7136,26 +7505,6 @@ __metadata:
languageName: node
linkType: hard
-"joi@npm:^17.7.0":
- version: 17.7.1
- resolution: "joi@npm:17.7.1"
- dependencies:
- "@hapi/hoek": "npm:^9.0.0"
- "@hapi/topo": "npm:^5.0.0"
- "@sideway/address": "npm:^4.1.3"
- "@sideway/formula": "npm:^3.0.1"
- "@sideway/pinpoint": "npm:^2.0.0"
- checksum: 2df890d5a7de74207a089d77416bcba8004fdf42c696f0960f93d16494ae757c3216a4e0df533c746af2071287032f29c1c50d02c0efab06dfb870c944577e8c
- languageName: node
- linkType: hard
-
-"js-base64@npm:^2.1.9":
- version: 2.6.4
- resolution: "js-base64@npm:2.6.4"
- checksum: c1a740a34fbb0ad0a528c2ab8749d7f873b1856a0638826306fcd98502e3c8c833334dff233085407e3201be543e5e71bf9692da7891ca680d9b03d027247a6a
- languageName: node
- linkType: hard
-
"js-cookie@npm:^2.2.1":
version: 2.2.1
resolution: "js-cookie@npm:2.2.1"
@@ -7272,7 +7621,7 @@ __metadata:
languageName: node
linkType: hard
-"json5@npm:^2.2.2":
+"json5@npm:^2.2.2, json5@npm:^2.2.3":
version: 2.2.3
resolution: "json5@npm:2.2.3"
bin:
@@ -7560,25 +7909,30 @@ __metadata:
dependencies:
"@electron/remote": "npm:^2.0.10"
"@fontsource/open-sans": "npm:^4.5.14"
+ "@octokit/core": "npm:5"
"@radix-ui/colors": "npm:^0.1.8"
"@radix-ui/react-switch": "npm:^1.0.1"
+ "@tsconfig/node18": "npm:^18.2.2"
"@tsconfig/strictest": "npm:^2.0.2"
"@tsconfig/vite-react": "npm:^3.0.0"
"@types/color": "npm:^3.0.6"
"@types/css-modules": "npm:^1.0.5"
"@types/eslint": "npm:^8"
+ "@types/express": "npm:^4.17.21"
"@types/lodash": "npm:^4.14.202"
+ "@types/luxon": "npm:^3.4.2"
+ "@types/morgan": "npm:^1.9.9"
"@types/node": "npm:18"
"@types/react": "npm:^18.2.66"
"@types/react-dom": "npm:^18.2.22"
"@types/sortablejs": "npm:^1.15.0"
+ "@types/yargs-parser": "npm:^21.0.3"
"@typescript-eslint/eslint-plugin": "npm:^6.12.0"
"@typescript-eslint/parser": "npm:^6.12.0"
"@uidotdev/usehooks": "npm:^2.4.1"
"@vitejs/plugin-react": "npm:^3.1.0"
color: "npm:^3.1.0"
concurrently: "npm:^6.0.0"
- cross-env: "npm:^7.0.3"
csv-parse: "npm:^4.15.3"
csv-stringify: "npm:^5.6.2"
cue-parser: "npm:^0.3.0"
@@ -7586,9 +7940,9 @@ __metadata:
electron: "npm:^27.0.0"
electron-builder: "npm:^24.6.4"
electron-devtools-installer: "npm:^3.2.0"
- electron-is-dev: "npm:^2.0.0"
electron-store: "npm:5.1.1"
electron-unhandled: "npm:^4.0.1"
+ electron-vite: "npm:^2.1.0"
eslint: "npm:^8.2.0"
eslint-config-mifi: "npm:^0.0.3"
eslint-plugin-import: "npm:^2.25.3"
@@ -7597,7 +7951,7 @@ __metadata:
eslint-plugin-react-hooks: "npm:^4.3.0"
eslint-plugin-unicorn: "npm:^51.0.1"
evergreen-ui: "npm:^6.13.1"
- execa: "npm:5"
+ execa: "npm:^8.0.1"
express: "npm:^4.18.2"
express-async-handler: "npm:^1.2.0"
fast-xml-parser: "npm:^4.2.5"
@@ -7605,11 +7959,10 @@ __metadata:
file-url: "npm:^3.0.0"
framer-motion: "npm:^9.0.3"
fs-extra: "npm:^8.1.0"
- github-api: "npm:^3.2.2"
i18next: "npm:^22.4.10"
i18next-fs-backend: "npm:^2.1.1"
i18next-parser: "npm:^7.6.0"
- icon-gen: "npm:^3.0.0"
+ icon-gen: "npm:^4.0.0"
immer: "npm:^10.0.2"
json5: "npm:^2.2.2"
ky: "npm:^0.33.1"
@@ -7632,24 +7985,25 @@ __metadata:
react-sortablejs: "npm:^6.1.4"
react-syntax-highlighter: "npm:^15.4.3"
react-use: "npm:^17.4.0"
+ rimraf: "npm:^5.0.5"
screenfull: "npm:^6.0.2"
scroll-into-view-if-needed: "npm:^2.2.28"
semver: "npm:^7.5.2"
sharp: "npm:^0.32.6"
smpte-timecode: "npm:^1.2.3"
sortablejs: "npm:^1.13.0"
- string-to-stream: "npm:^1.1.1"
+ string-to-stream: "npm:^3.0.1"
sweetalert2: "npm:^11.0.0"
sweetalert2-react-content: "npm:^5.0.7"
tiny-invariant: "npm:^1.3.3"
+ tsx: "npm:^4.7.1"
typescript: "npm:~5.2.0"
use-debounce: "npm:^5.1.0"
use-trace-update: "npm:^1.3.0"
vite: "npm:^4.5.2"
vitest: "npm:^1.2.2"
- wait-on: "npm:^7.0.1"
winston: "npm:^3.8.1"
- yargs-parser: "npm:^21.0.0"
+ yargs-parser: "npm:^21.1.1"
languageName: unknown
linkType: soft
@@ -7720,6 +8074,13 @@ __metadata:
languageName: node
linkType: hard
+"lru-cache@npm:^9.1.1 || ^10.0.0":
+ version: 10.2.0
+ resolution: "lru-cache@npm:10.2.0"
+ checksum: 502ec42c3309c0eae1ce41afca471f831c278566d45a5273a0c51102dee31e0e250a62fa9029c3370988df33a14188a38e682c16143b794de78668de3643e302
+ languageName: node
+ linkType: hard
+
"luxon@npm:^3.3.0":
version: 3.3.0
resolution: "luxon@npm:3.3.0"
@@ -7934,7 +8295,7 @@ __metadata:
languageName: node
linkType: hard
-"minimatch@npm:9.0.3":
+"minimatch@npm:9.0.3, minimatch@npm:^9.0.1":
version: 9.0.3
resolution: "minimatch@npm:9.0.3"
dependencies:
@@ -7984,7 +8345,7 @@ __metadata:
languageName: node
linkType: hard
-"minimist@npm:^1.2.6, minimist@npm:^1.2.7":
+"minimist@npm:^1.2.6":
version: 1.2.8
resolution: "minimist@npm:1.2.8"
checksum: 908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f
@@ -8067,6 +8428,13 @@ __metadata:
languageName: node
linkType: hard
+"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0":
+ version: 7.0.4
+ resolution: "minipass@npm:7.0.4"
+ checksum: e864bd02ceb5e0707696d58f7ce3a0b89233f0d686ef0d447a66db705c0846a8dc6f34865cd85256c1472ff623665f616b90b8ff58058b2ad996c5de747d2d18
+ languageName: node
+ linkType: hard
+
"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2":
version: 2.1.2
resolution: "minizlib@npm:2.1.2"
@@ -8240,15 +8608,6 @@ __metadata:
languageName: node
linkType: hard
-"node-addon-api@npm:^4.2.0":
- version: 4.2.0
- resolution: "node-addon-api@npm:4.2.0"
- dependencies:
- node-gyp: "npm:latest"
- checksum: 27a51793848b9159c134378a0e19394ba02bfb1e23b856ba9feb2560f6c5f182cca77a42f011d08c2dd38725c7cad1294241b8db1ab605aa0b404046b73b297a
- languageName: node
- linkType: hard
-
"node-addon-api@npm:^6.1.0":
version: 6.1.0
resolution: "node-addon-api@npm:6.1.0"
@@ -8350,15 +8709,6 @@ __metadata:
languageName: node
linkType: hard
-"npm-run-path@npm:^4.0.1":
- version: 4.0.1
- resolution: "npm-run-path@npm:4.0.1"
- dependencies:
- path-key: "npm:^3.0.0"
- checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23
- languageName: node
- linkType: hard
-
"npm-run-path@npm:^5.1.0":
version: 5.2.0
resolution: "npm-run-path@npm:5.2.0"
@@ -8368,18 +8718,6 @@ __metadata:
languageName: node
linkType: hard
-"npmlog@npm:^4.0.1":
- version: 4.1.2
- resolution: "npmlog@npm:4.1.2"
- dependencies:
- are-we-there-yet: "npm:~1.1.2"
- console-control-strings: "npm:~1.1.0"
- gauge: "npm:~2.7.3"
- set-blocking: "npm:~2.0.0"
- checksum: b6b85c9f33da8f600f72564b6ec71136b1641b8b235fca7cc543d1041acb74c2d989d97fe443a0e65754f438d9a974a2fe1b4ff8723c78ef3f9b7a6d74b02079
- languageName: node
- linkType: hard
-
"npmlog@npm:^6.0.0":
version: 6.0.2
resolution: "npmlog@npm:6.0.2"
@@ -8401,13 +8739,6 @@ __metadata:
languageName: node
linkType: hard
-"number-is-nan@npm:^1.0.0":
- version: 1.0.1
- resolution: "number-is-nan@npm:1.0.1"
- checksum: 13656bc9aa771b96cef209ffca31c31a03b507ca6862ba7c3f638a283560620d723d52e626d57892c7fff475f4c36ac07f0600f14544692ff595abff214b9ffb
- languageName: node
- linkType: hard
-
"object-assign@npm:^4.1.0, object-assign@npm:^4.1.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
@@ -8559,7 +8890,7 @@ __metadata:
languageName: node
linkType: hard
-"onetime@npm:^5.1.0, onetime@npm:^5.1.2":
+"onetime@npm:^5.1.0":
version: 5.1.2
resolution: "onetime@npm:5.1.2"
dependencies:
@@ -8793,7 +9124,7 @@ __metadata:
languageName: node
linkType: hard
-"path-key@npm:^3.0.0, path-key@npm:^3.1.0":
+"path-key@npm:^3.1.0":
version: 3.1.1
resolution: "path-key@npm:3.1.1"
checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020
@@ -8821,6 +9152,16 @@ __metadata:
languageName: node
linkType: hard
+"path-scurry@npm:^1.10.1":
+ version: 1.10.1
+ resolution: "path-scurry@npm:1.10.1"
+ dependencies:
+ lru-cache: "npm:^9.1.1 || ^10.0.0"
+ minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0"
+ checksum: eebfb8304fef1d4f7e1486df987e4fd77413de4fce16508dea69fcf8eb318c09a6b15a7a2f4c22877cec1cb7ecbd3071d18ca9de79eeece0df874a00f1f0bdc8
+ languageName: node
+ linkType: hard
+
"path-to-regexp@npm:0.1.7":
version: 0.1.7
resolution: "path-to-regexp@npm:0.1.7"
@@ -8939,10 +9280,10 @@ __metadata:
languageName: node
linkType: hard
-"pngjs@npm:^6.0.0":
- version: 6.0.0
- resolution: "pngjs@npm:6.0.0"
- checksum: 692751ccd5e762623103900922caac982caa90258d9c6c04a6e2bc3397b1dedbaf9db826fc0fa068a29d607cad3df1d1eded0dec2ee35a0015c65cb5ef33ad18
+"pngjs@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "pngjs@npm:7.0.0"
+ checksum: e843ebbb0df092ee0f3a3e7dbd91ff87a239a4e4c4198fff202916bfb33b67622f4b83b3c29f3ccae94fcb97180c289df06068624554f61686fe6b9a4811f7db
languageName: node
linkType: hard
@@ -8975,29 +9316,6 @@ __metadata:
languageName: node
linkType: hard
-"prebuild-install@npm:^7.0.0":
- version: 7.1.0
- resolution: "prebuild-install@npm:7.1.0"
- dependencies:
- detect-libc: "npm:^2.0.0"
- expand-template: "npm:^2.0.3"
- github-from-package: "npm:0.0.0"
- minimist: "npm:^1.2.3"
- mkdirp-classic: "npm:^0.5.3"
- napi-build-utils: "npm:^1.0.1"
- node-abi: "npm:^3.3.0"
- npmlog: "npm:^4.0.1"
- pump: "npm:^3.0.0"
- rc: "npm:^1.2.7"
- simple-get: "npm:^4.0.0"
- tar-fs: "npm:^2.0.0"
- tunnel-agent: "npm:^0.6.0"
- bin:
- prebuild-install: bin.js
- checksum: 7c05e13b6778e7854a9fed7516f74d8b04d6bbe869466859506bded274980bfe28051501f57e8d57982c45d7fc74ff0937fd8db56b38c76e04d0a18ece50b463
- languageName: node
- linkType: hard
-
"prebuild-install@npm:^7.1.1":
version: 7.1.1
resolution: "prebuild-install@npm:7.1.1"
@@ -9465,7 +9783,7 @@ __metadata:
languageName: node
linkType: hard
-"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.1, readable-stream@npm:^2.0.5, readable-stream@npm:^2.0.6, readable-stream@npm:^2.1.0, readable-stream@npm:^2.1.5, readable-stream@npm:^2.3.3, readable-stream@npm:^2.3.5, readable-stream@npm:^2.3.6, readable-stream@npm:~2.3.6":
+"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.1, readable-stream@npm:^2.0.5, readable-stream@npm:^2.1.5, readable-stream@npm:^2.3.3, readable-stream@npm:^2.3.5, readable-stream@npm:^2.3.6, readable-stream@npm:~2.3.6":
version: 2.3.7
resolution: "readable-stream@npm:2.3.7"
dependencies:
@@ -9647,6 +9965,13 @@ __metadata:
languageName: node
linkType: hard
+"resolve-pkg-maps@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "resolve-pkg-maps@npm:1.0.0"
+ checksum: 0763150adf303040c304009231314d1e84c6e5ebfa2d82b7d94e96a6e82bacd1dcc0b58ae257315f3c8adb89a91d8d0f12928241cba2df1680fbe6f60bf99b0e
+ languageName: node
+ linkType: hard
+
"resolve@npm:^1.10.0, resolve@npm:^1.22.4":
version: 1.22.8
resolution: "resolve@npm:1.22.8"
@@ -9758,6 +10083,17 @@ __metadata:
languageName: node
linkType: hard
+"rimraf@npm:^5.0.5":
+ version: 5.0.5
+ resolution: "rimraf@npm:5.0.5"
+ dependencies:
+ glob: "npm:^10.3.7"
+ bin:
+ rimraf: dist/esm/bin.mjs
+ checksum: a612c7184f96258b7d1328c486b12ca7b60aa30e04229a08bbfa7e964486deb1e9a1b52d917809311bdc39a808a4055c0f950c0280fba194ba0a09e6f0d404f6
+ languageName: node
+ linkType: hard
+
"roarr@npm:^2.15.3":
version: 2.15.4
resolution: "roarr@npm:2.15.4"
@@ -9881,15 +10217,6 @@ __metadata:
languageName: node
linkType: hard
-"rxjs@npm:^7.8.0":
- version: 7.8.0
- resolution: "rxjs@npm:7.8.0"
- dependencies:
- tslib: "npm:^2.1.0"
- checksum: ff9359cc7875edecc8fc487481366b876b488901178cca8f2bdad03e00d2b5a19b01d2b02d3b4ebd47e574264db8460c6c2386076c3189b359b5e8c70a6e51e3
- languageName: node
- linkType: hard
-
"safe-array-concat@npm:^1.1.0":
version: 1.1.0
resolution: "safe-array-concat@npm:1.1.0"
@@ -10107,7 +10434,7 @@ __metadata:
languageName: node
linkType: hard
-"set-blocking@npm:^2.0.0, set-blocking@npm:~2.0.0":
+"set-blocking@npm:^2.0.0":
version: 2.0.0
resolution: "set-blocking@npm:2.0.0"
checksum: 8980ebf7ae9eb945bb036b6e283c547ee783a1ad557a82babf758a065e2fb6ea337fd82cac30dd565c1e606e423f30024a19fff7afbf4977d784720c4026a8ef
@@ -10161,24 +10488,7 @@ __metadata:
languageName: node
linkType: hard
-"sharp@npm:^0.29.3":
- version: 0.29.3
- resolution: "sharp@npm:0.29.3"
- dependencies:
- color: "npm:^4.0.1"
- detect-libc: "npm:^1.0.3"
- node-addon-api: "npm:^4.2.0"
- node-gyp: "npm:latest"
- prebuild-install: "npm:^7.0.0"
- semver: "npm:^7.3.5"
- simple-get: "npm:^4.0.0"
- tar-fs: "npm:^2.1.1"
- tunnel-agent: "npm:^0.6.0"
- checksum: 6c427b687ce4e01ec0328c5bb943a2001deaa4ad0df710dc9ebe23d800fc92a608b0dd6987b68a2666f07180c80d70258616766157385e2ba3dda8bc6d73c11b
- languageName: node
- linkType: hard
-
-"sharp@npm:^0.32.6":
+"sharp@npm:^0.32.4, sharp@npm:^0.32.6":
version: 0.32.6
resolution: "sharp@npm:0.32.6"
dependencies:
@@ -10229,21 +10539,21 @@ __metadata:
languageName: node
linkType: hard
-"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2":
+"signal-exit@npm:^3.0.2":
version: 3.0.6
resolution: "signal-exit@npm:3.0.6"
checksum: b819ac81ba757af559dad0804233ae31bf6f054591cd8a671e9cbcf09f21c72ec3076fe87d1e04861f5b33b47d63f0694b568de99c99cd733ee2060515beb6d5
languageName: node
linkType: hard
-"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7":
+"signal-exit@npm:^3.0.7":
version: 3.0.7
resolution: "signal-exit@npm:3.0.7"
checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318
languageName: node
linkType: hard
-"signal-exit@npm:^4.1.0":
+"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0":
version: 4.1.0
resolution: "signal-exit@npm:4.1.0"
checksum: c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f
@@ -10556,28 +10866,16 @@ __metadata:
languageName: node
linkType: hard
-"string-to-stream@npm:^1.1.1":
- version: 1.1.1
- resolution: "string-to-stream@npm:1.1.1"
- dependencies:
- inherits: "npm:^2.0.1"
- readable-stream: "npm:^2.1.0"
- checksum: f4ad5f2a845faa59adc4b12c1141ab2303ccdfa4e768d0f8c63af7b2a136f19bfe80e3f7eb8abf577803fd6d13895767d2b2e9560705f1aa0747329cbaea708c
- languageName: node
- linkType: hard
-
-"string-width@npm:^1.0.1":
- version: 1.0.2
- resolution: "string-width@npm:1.0.2"
+"string-to-stream@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "string-to-stream@npm:3.0.1"
dependencies:
- code-point-at: "npm:^1.0.0"
- is-fullwidth-code-point: "npm:^1.0.0"
- strip-ansi: "npm:^3.0.0"
- checksum: 5c79439e95bc3bd7233a332c5f5926ab2ee90b23816ed4faa380ce3b2576d7800b0a5bb15ae88ed28737acc7ea06a518c2eef39142dd727adad0e45c776cd37e
+ readable-stream: "npm:^3.4.0"
+ checksum: 422d68a8bbb018b63bf2c028cafb8b507f272b4c045cc6493adedb26ad7ceb81cc0e2399804cd5fd9e0207de5753bb5b0ff087181c5ebf0a5620f9c3d4a3a183
languageName: node
linkType: hard
-"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
+"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
version: 4.2.3
resolution: "string-width@npm:4.2.3"
dependencies:
@@ -10588,6 +10886,17 @@ __metadata:
languageName: node
linkType: hard
+"string-width@npm:^5.0.1, string-width@npm:^5.1.2":
+ version: 5.1.2
+ resolution: "string-width@npm:5.1.2"
+ dependencies:
+ eastasianwidth: "npm:^0.2.0"
+ emoji-regex: "npm:^9.2.2"
+ strip-ansi: "npm:^7.0.1"
+ checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193
+ languageName: node
+ linkType: hard
+
"string.prototype.matchall@npm:^4.0.8":
version: 4.0.10
resolution: "string.prototype.matchall@npm:4.0.10"
@@ -10656,16 +10965,7 @@ __metadata:
languageName: node
linkType: hard
-"strip-ansi@npm:^3.0.0, strip-ansi@npm:^3.0.1":
- version: 3.0.1
- resolution: "strip-ansi@npm:3.0.1"
- dependencies:
- ansi-regex: "npm:^2.0.0"
- checksum: 9b974de611ce5075c70629c00fa98c46144043db92ae17748fb780f706f7a789e9989fd10597b7c2053ae8d1513fd707816a91f1879b2f71e6ac0b6a863db465
- languageName: node
- linkType: hard
-
-"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
version: 6.0.1
resolution: "strip-ansi@npm:6.0.1"
dependencies:
@@ -10674,6 +10974,15 @@ __metadata:
languageName: node
linkType: hard
+"strip-ansi@npm:^7.0.1":
+ version: 7.1.0
+ resolution: "strip-ansi@npm:7.1.0"
+ dependencies:
+ ansi-regex: "npm:^6.0.1"
+ checksum: 475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2
+ languageName: node
+ linkType: hard
+
"strip-bom@npm:^3.0.0":
version: 3.0.0
resolution: "strip-bom@npm:3.0.0"
@@ -10681,13 +10990,6 @@ __metadata:
languageName: node
linkType: hard
-"strip-final-newline@npm:^2.0.0":
- version: 2.0.0
- resolution: "strip-final-newline@npm:2.0.0"
- checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64
- languageName: node
- linkType: hard
-
"strip-final-newline@npm:^3.0.0":
version: 3.0.0
resolution: "strip-final-newline@npm:3.0.0"
@@ -10819,7 +11121,7 @@ __metadata:
languageName: node
linkType: hard
-"tar-fs@npm:^2.0.0, tar-fs@npm:^2.1.1":
+"tar-fs@npm:^2.0.0":
version: 2.1.1
resolution: "tar-fs@npm:2.1.1"
dependencies:
@@ -11177,6 +11479,22 @@ __metadata:
languageName: node
linkType: hard
+"tsx@npm:^4.7.1":
+ version: 4.7.1
+ resolution: "tsx@npm:4.7.1"
+ dependencies:
+ esbuild: "npm:~0.19.10"
+ fsevents: "npm:~2.3.3"
+ get-tsconfig: "npm:^4.7.2"
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ bin:
+ tsx: dist/cli.mjs
+ checksum: 3a462b595f31ae58b31f9c6e8c450577dc87660b1225012bd972b6b58d7d2f6c4034728763ebc53bb731acff68de8b0fa50586e4c1ec4c086226f1788ccf9b7d
+ languageName: node
+ linkType: hard
+
"tunnel-agent@npm:^0.6.0":
version: 0.6.0
resolution: "tunnel-agent@npm:0.6.0"
@@ -11442,6 +11760,13 @@ __metadata:
languageName: node
linkType: hard
+"universal-user-agent@npm:^6.0.0":
+ version: 6.0.1
+ resolution: "universal-user-agent@npm:6.0.1"
+ checksum: fdc8e1ae48a05decfc7ded09b62071f571c7fe0bd793d700704c80cea316101d4eac15cc27ed2bb64f4ce166d2684777c3198b9ab16034f547abea0d3aa1c93c
+ languageName: node
+ linkType: hard
+
"universalify@npm:^0.1.0":
version: 0.1.2
resolution: "universalify@npm:0.1.2"
@@ -11534,13 +11859,6 @@ __metadata:
languageName: node
linkType: hard
-"utf8@npm:^2.1.1":
- version: 2.1.2
- resolution: "utf8@npm:2.1.2"
- checksum: 7b35ff1203d2e0209db7a28f6852cb64ff292a3bdc3b6a9c52ff2d69abcfeff992647e8d4dc787c4f1c9374613ad11f7e9c682df66985dfa516b8f8c69855860
- languageName: node
- linkType: hard
-
"util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1":
version: 1.0.2
resolution: "util-deprecate@npm:1.0.2"
@@ -11555,15 +11873,6 @@ __metadata:
languageName: node
linkType: hard
-"uuid@npm:^8.3.2":
- version: 8.3.2
- resolution: "uuid@npm:8.3.2"
- bin:
- uuid: dist/bin/uuid
- checksum: 9a5f7aa1d6f56dd1e8d5f2478f855f25c645e64e26e347a98e98d95781d5ed20062d6cca2eecb58ba7c84bc3910be95c0451ef4161906abaab44f9cb68ffbdd1
- languageName: node
- linkType: hard
-
"validate-npm-package-license@npm:^3.0.1":
version: 3.0.4
resolution: "validate-npm-package-license@npm:3.0.4"
@@ -11829,21 +12138,6 @@ __metadata:
languageName: node
linkType: hard
-"wait-on@npm:^7.0.1":
- version: 7.0.1
- resolution: "wait-on@npm:7.0.1"
- dependencies:
- axios: "npm:^0.27.2"
- joi: "npm:^17.7.0"
- lodash: "npm:^4.17.21"
- minimist: "npm:^1.2.7"
- rxjs: "npm:^7.8.0"
- bin:
- wait-on: bin/wait-on
- checksum: 9f76c0eb89785745fd0c20332d447e5f3505a84997aca4ab19e1a961c2ccd39cf60cb805ff4223184593a133cd84d6170f9eb1cdc105d0d31eb55a0703d6d432
- languageName: node
- linkType: hard
-
"walk-sync@npm:^2.2.0":
version: 2.2.0
resolution: "walk-sync@npm:2.2.0"
@@ -11944,7 +12238,7 @@ __metadata:
languageName: node
linkType: hard
-"wide-align@npm:^1.1.0, wide-align@npm:^1.1.5":
+"wide-align@npm:^1.1.5":
version: 1.1.5
resolution: "wide-align@npm:1.1.5"
dependencies:
@@ -11982,7 +12276,7 @@ __metadata:
languageName: node
linkType: hard
-"wrap-ansi@npm:^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0":
version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0"
dependencies:
@@ -11993,6 +12287,17 @@ __metadata:
languageName: node
linkType: hard
+"wrap-ansi@npm:^8.1.0":
+ version: 8.1.0
+ resolution: "wrap-ansi@npm:8.1.0"
+ dependencies:
+ ansi-styles: "npm:^6.1.0"
+ string-width: "npm:^5.0.1"
+ strip-ansi: "npm:^7.0.1"
+ checksum: 7b1e4b35e9bb2312d2ee9ee7dc95b8cb5f8b4b5a89f7dde5543fe66c1e3715663094defa50d75454ac900bd210f702d575f15f3f17fa9ec0291806d2578d1ddf
+ languageName: node
+ linkType: hard
+
"wrappy@npm:1":
version: 1.0.2
resolution: "wrappy@npm:1.0.2"
@@ -12068,13 +12373,6 @@ __metadata:
languageName: node
linkType: hard
-"yargs-parser@npm:^21.0.0":
- version: 21.0.0
- resolution: "yargs-parser@npm:21.0.0"
- checksum: bbfa0daa49d46d07954fc9c9088037628d603a4862b08fb97183d5cf905791a9b0beb95866637c63453b73475a4187d76cfba7503ccfc79fd66bbd11a8afb032
- languageName: node
- linkType: hard
-
"yargs-parser@npm:^21.1.1":
version: 21.1.1
resolution: "yargs-parser@npm:21.1.1"