[ENG-1472] Frontend bug fixes and dependencies update (#2137)

* Fix onboarding sometimes not redirecting to Explorer on prod builds
 - Fix failure trying to compile landing prod builds outside Vercel
 - Fix Server docker failing to restart due to some incorrecting logic for creating the unprivileged users erroring out
 - Fix Storybook failing to build due to updates to Vite
 - Update Storybook dependencies
 - Remove unused Inter font dependency
 - Fix some incorrect references to NodeJS types inside web code
 - Fix $libraryId index using the incorrect redirect function
 - Improve error handling for the $libraryId index route
 - Fix Prism not being correctly loaded, and failing to register its plugins
 - Improve Prism loading error handling
 - Small improvement to the text highlight logic
 - Fix SCSS deprecation for untyped hsl values
 - Fix library query cache incorrectly saving empty values, which lead to the onboarding redirect bug
 - Patch contentLayer to fix an error during the final part of it's build process
 - Update most dev dependencies
 - Update publish-artifact to be compatible with new @actions/artifact
 - Fix issue with new vite-plugin-solid failing to build our .ts files due to the removal of the typescript plugin
 - Fix pnpm overrides not applying due to incorrect placement in package.json
 - Replace deprecated react-tsparticles and updated three used by the Bubbles background in the landing page
 - Rework Bubbles background to be compatible with new @tsparticles/react
 - Update @sd/config dependencies
 - Update @sd/scripts dependencies

* Implement suggestions
 - Replace mobile JS node setup with custom setup-pnpm action
 - Handle GITHUB_SECRET default value in code and throw a warning when it is not set
 - Fix pnpm now resolving the correct node version when building Spacedrive server docker
 - Add missing getent command to spacedrive server docker
 - Fix typo in entrypoint.sh
 - Implement a more robust check if the user is already in a group
 - Fix adduser failing due to missing default group
 - Disconnect IntersectionObserver on component unmount
 - Improve prism import comment

* Implement more suggestions
 - Pin genent version to latest stable release of UClibc
 - Add checksum checks for all ADD clauses in Spacedrive server Dockerfile

* Increase Maestro timeout to reduce CI failures due to slow simulator startup

* Dowgrade maestro to workaround CI timeout

* Improvements to the script that run maestro mobile tests
 - Increase the amount of retries for a maestro test run to 6
 - Increase Maestro driver startup timeout to 2 minutes

* Let run-maestro-tests.sh decide how to run itself

* ¯\_(ツ)_/¯
This commit is contained in:
Vítor Vasconcellos 2024-02-28 20:52:24 -03:00 committed by GitHub
parent 1b834dd4be
commit 5a103fb21b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 7028 additions and 8139 deletions

View file

@ -0,0 +1,8 @@
module.exports = {
extends: [require.resolve('@sd/config/eslint/base.js')],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
},
ignorePatterns: ['dist/**/*']
};

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
import * as artifact from '@actions/artifact';
import client from '@actions/artifact';
import * as core from '@actions/core';
import * as glob from '@actions/glob';
import * as io from '@actions/io';
@ -49,8 +49,6 @@ const ARTIFACTS_DIR = '.artifacts';
const ARTIFACT_BASE = `Spacedrive-${OS}-${ARCH}`;
const UPDATER_ARTIFACT_NAME = `Spacedrive-Updater-${OS}-${ARCH}`;
const client = artifact.create();
async function globFiles(pattern: string) {
const globber = await glob.create(pattern);
return await globber.glob();

View file

@ -2,16 +2,18 @@
"name": "@sd/publish-artifacts",
"private": true,
"scripts": {
"build": "ncc build index.ts --minify"
"build": "ncc build index.ts --minify",
"typecheck": "tsc -b",
"lint": "eslint . --cache"
},
"dependencies": {
"@actions/artifact": "^1.1.2",
"@actions/artifact": "^2.1.3",
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"@actions/glob": "^0.4.0",
"@actions/io": "^1.1.3"
},
"devDependencies": {
"@vercel/ncc": "^0.38.1"
"@vercel/ncc": "^0.38.1",
"@sd/config": "workspace:*"
}
}

View file

@ -6,6 +6,7 @@
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
"strict": true /* Enable all strict type-checking options. */,
"skipLibCheck": true /* Skip type checking all .d.ts files. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */,
"noEmit": true
}
}

View file

@ -35,18 +35,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v3
- name: Setup Node.js, pnpm and dependencies
uses: ./.github/actions/setup-pnpm
with:
node-version: latest
- uses: pnpm/action-setup@v2
name: Install pnpm
with:
version: latest
run_install: true
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build mobile JS
run: pnpm mobile export
@ -57,7 +51,7 @@ jobs:
# runs-on: macos-12
# steps:
# - name: Checkout repository
# uses: actions/checkout@v3
# uses: actions/checkout@v4
#
# - name: Setup Java JDK
# uses: actions/setup-java@v3.10.0
@ -140,14 +134,14 @@ jobs:
# script: |
# adb install -r apps/mobile/android/app/build/outputs/apk/release/app-release.apk
# adb wait-for-device
# bash ./apps/mobile/scripts/run-maestro-tests android
# ./apps/mobile/scripts/run-maestro-tests.sh android
ios:
name: iOS
runs-on: macos-14
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Xcode
uses: maxim-lobanov/setup-xcode@v1
@ -195,18 +189,24 @@ jobs:
run: xcodebuild -workspace ./Spacedrive.xcworkspace -scheme Spacedrive -configuration Release -sdk iphonesimulator -derivedDataPath build -arch "$(uname -m)"
- name: Install Maestro
env:
# Workaround: https://github.com/mobile-dev-inc/maestro/issues/1585
MAESTRO_VERSION: '1.33.1'
run: |
curl -Ls "https://get.maestro.mobile.dev" | bash
brew tap facebook/fb
brew install facebook/fb/idb-companion
echo "$HOME/.maestro/bin" >> $GITHUB_PATH
echo "${HOME}/.maestro/bin" >> $GITHUB_PATH
- name: Run Simulator
uses: futureware-tech/simulator-action@v2
uses: futureware-tech/simulator-action@v3
with:
model: 'iPhone SE (3rd generation)'
- name: Run Tests
env:
# https://github.com/expo/expo/blob/339fa68/apps/bare-expo/scripts/start-ios-e2e-test.ts#L12
MAESTRO_DRIVER_STARTUP_TIMEOUT: 120000
run: |
xcrun simctl install booted apps/mobile/ios/build/Build/Products/Release-iphonesimulator/Spacedrive.app
bash ./apps/mobile/scripts/run-maestro-tests ios
./apps/mobile/scripts/run-maestro-tests.sh ios

View file

@ -17,7 +17,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Trigger Algolia Crawler
run: |

View file

@ -25,7 +25,7 @@ apps/desktop/src/index.tsx
apps/desktop/src/commands.ts
# Import only file, which order is relevant
interface/components/TextViewer/prism.tsx
interface/components/TextViewer/prism-lazy.ts
.next/
.contentlayer/

View file

@ -79,7 +79,7 @@
"*.tsx": "${capture}.ts",
".npmrc": ".nvmrc, .yarnrc.yml",
".gitignore": ".eslintignore, .prettierignore",
"README.md": "CONTRIBUTING.md, CODE_OF_CONDUCT.md",
"README.md": "CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md",
"Cargo.toml": "Cargo.lock",
".eslintrc.js": ".eslintcache",
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, pnpm-workspace.yaml, .pnp.cjs, .pnp.loader.mjs",

View file

@ -30,13 +30,13 @@
},
"devDependencies": {
"@sd/config": "workspace:*",
"@sentry/vite-plugin": "^2.9.0",
"@tauri-apps/cli": "^1.5.6",
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",
"sass": "^1.69.5",
"@sentry/vite-plugin": "^2.14.2",
"@tauri-apps/cli": "^1.5.10",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"sass": "^1.71.1",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite-tsconfig-paths": "^4.2.1"
"vite": "^5.1.4",
"vite-tsconfig-paths": "^4.3.1"
}
}

View file

@ -35,7 +35,6 @@
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.11",
"react-github-btn": "^1.4.0",
"react-tsparticles": "^2.12.2",
"reading-time": "^1.5.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-external-links": "^2.1.0",
@ -46,25 +45,26 @@
"remark-math": "^5.1.1",
"remark-mdx-images": "^2.0.0",
"tailwind-merge": "^1.14.0",
"three": "^0.158.0",
"tsparticles": "^2.12.0",
"three": "^0.161.0",
"tsparticles": "^3.3.0",
"@tsparticles/react": "^3.0.0",
"unist-util-visit": "^5.0.0",
"zod": "~3.22.4"
},
"devDependencies": {
"@next/bundle-analyzer": "^13.5.6",
"@octokit/openapi-types": "^19.0.2",
"@octokit/openapi-types": "^20.0.0",
"@sd/config": "workspace:*",
"@svgr/webpack": "^8.1.0",
"@types/node": "~18.17.19",
"@types/react": "^18.2.34",
"@types/react-burger-menu": "^2.8.5",
"@types/react-dom": "^18.2.14",
"@types/three": "^0.158.2",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31",
"sharp": "^0.32.6",
"@types/react": "^18.2.60",
"@types/react-burger-menu": "^2.8.7",
"@types/react-dom": "^18.2.19",
"@types/three": "^0.161.2",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.35",
"sharp": "^0.33.2",
"tailwindcss": "^3.4.1",
"typescript": "^5.2.2"
"typescript": "^5.3.3"
}
}

View file

@ -7,8 +7,10 @@ import { getLatestRelease, getRecentReleases, getRelease } from '..';
export const runtime = 'edge';
if (env.GITHUB_SECRET == null) console.warn('GITHUB_SECRET is not set, using dummy value');
const webhook = new Webhooks({
secret: env.GITHUB_SECRET
secret: env.GITHUB_SECRET || '00000000000000000000000000000000000000000'
});
export async function POST(req: Request) {

View file

@ -1,5 +1,5 @@
import { useCallback } from 'react';
import Particles from 'react-tsparticles';
import Particles, { initParticlesEngine } from '@tsparticles/react';
import { useEffect, useState } from 'react';
import { loadFull } from 'tsparticles';
const options: NonNullable<React.ComponentProps<typeof Particles>['options']> = {
@ -10,7 +10,9 @@ const options: NonNullable<React.ComponentProps<typeof Particles>['options']> =
enable: false,
mode: 'push'
},
resize: false
resize: {
enable: false
}
}
},
particles: {
@ -32,10 +34,9 @@ const options: NonNullable<React.ComponentProps<typeof Particles>['options']> =
},
number: {
density: {
enable: true,
area: 900
enable: true
},
value: 100
value: 400
},
opacity: {
value: 0.1
@ -51,19 +52,17 @@ const options: NonNullable<React.ComponentProps<typeof Particles>['options']> =
};
export const Bubbles = () => {
const particlesInit = useCallback<NonNullable<React.ComponentProps<typeof Particles>['init']>>(
async (engine) => {
await loadFull(engine);
},
[]
);
const [init, setInit] = useState(false);
return (
<Particles
id="tsparticles"
className="absolute inset-0 z-0"
init={particlesInit}
options={options}
/>
);
useEffect(() => {
// this should be run only once per application lifetime
initParticlesEngine(async (engine) => {
await loadFull(engine);
}).then(() => {
setInit(true);
}, console.error);
}, []);
if (init)
return <Particles id="tsparticles" className="absolute inset-0 z-0" options={options} />;
};

View file

@ -12,7 +12,7 @@
"xcode": "open ios/Spacedrive.xcworkspace",
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
"lint": "eslint src --cache",
"test": "cd ../.. && ./apps/mobile/scripts/run-maestro-tests ios",
"test": "./apps/mobile/scripts/run-maestro-tests.sh ios",
"export": "expo export",
"typecheck": "tsc -b",
"format": "prettier --write ."
@ -73,13 +73,13 @@
"zod": "~3.22.4"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@rnx-kit/metro-config": "^1.3.12",
"@babel/core": "^7.23.9",
"@rnx-kit/metro-config": "^1.3.14",
"@sd/config": "workspace:*",
"@types/react": "^18.2.52",
"@types/react": "^18.2.60",
"babel-plugin-module-resolver": "^5.0.0",
"eslint-plugin-react-native": "^4.1.0",
"react-native-svg-transformer": "^1.1.0",
"react-native-svg-transformer": "^1.3.0",
"typescript": "^5.3.3"
}
}

View file

@ -1,77 +0,0 @@
#!/bin/bash
trap 'exit' INT
PLATFORM=${1:-}
case $PLATFORM in
ios | android )
;;
*)
echo "Error! You must pass either 'android' or 'ios'"
echo ""
exit 1
;;
esac
# NOTE: This script is intended to be run from the root of the project (CI)
if [ "$PLATFORM" == "ios" ]; then
testFiles=$(ls apps/mobile/tests/*.yml apps/mobile/tests/ios-only/*.yml)
else
testFiles=$(ls apps/mobile/tests/*.yml apps/mobile/tests/android-only/*.yml)
fi
# Run onboarding first
onboardingFile="apps/mobile/tests/onboarding.yml"
if ! maestro test "$onboardingFile"
then
echo "Onboarding test failed. Retrying in 30 seconds..."
sleep 30
if ! maestro test "$onboardingFile"
then
echo "Onboarding test failed again. Retrying for the last time in 120 seconds..."
sleep 120
if ! maestro test "$onboardingFile"
then
echo "Onboarding test failed again. Exiting..."
exit 1
fi
fi
fi
failedTests=()
# Run the rest of the files
for file in $testFiles
do
# Skip onboarding.yml since it has already been run
if [ "$file" == "$onboardingFile" ]
then
continue
fi
if ! maestro test "$file"
then
echo "Test ${file} failed. Retrying in 30 seconds..."
sleep 30
if ! maestro test "$file"
then
echo "Test ${file} failed again. Retrying for the last time in 120 seconds..."
sleep 120
if ! maestro test "$file"
then
failedTests+=("$file")
fi
fi
fi
done
if [ ${#failedTests[@]} -eq 0 ]; then
exit 0
else
echo "These tests failed:"
printf '%s\n' "${failedTests[@]}"
exit 1
fi

View file

@ -0,0 +1,84 @@
#!/usr/bin/env bash
set -eEuo pipefail
if [ "${CI:-}" = "true" ]; then
set -x
fi
# Script root
_root="$(CDPATH='' cd -- "$(dirname "$0")" && pwd -P)"
_test_dir="$(CDPATH='' cd -- "${_root}/../tests" && pwd -P)"
PLATFORM=${1:-}
case $PLATFORM in
ios | android) ;;
*)
echo "Usage: run-maestro-tests.sh <android|ios>" >&2
exit 1
;;
esac
run_maestro_test() {
if [ $# -ne 1 ]; then
echo "Usage: run_maestro_test <test_file>" >&2
exit 1
fi
local i
local retry_seconds
for i in {1..6}; do
if maestro test "$1"; then
# Test succeeded
return
else
retry_seconds=$((20 * i))
echo "Test $1 failed. Retrying in $retry_seconds seconds..."
sleep $retry_seconds
fi
done
echo "Test $1 failed after 6 retries. Exiting..." >&2
return 1
}
# Find all test files
testFiles=()
while IFS='' read -r testFile; do testFiles+=("$testFile"); done < <(
find "${_test_dir}" -maxdepth 1 -name '*.yml' -o -name '*.yaml'
)
if [ "$PLATFORM" == "ios" ]; then
while IFS='' read -r testFile; do testFiles+=("$testFile"); done < <(
find "${_test_dir}/ios-only" -name '*.yml' -o -name '*.yaml'
)
else
while IFS='' read -r testFile; do testFiles+=("$testFile"); done < <(
find "${_test_dir}/android-only" -name '*.yml' -o -name '*.yaml'
)
fi
# Run onboarding first
onboardingFile="${_test_dir}/onboarding.yml"
if ! run_maestro_test "$onboardingFile"; then
echo "Onboarding test failed. Exiting..." >&2
exit 1
fi
# Run the rest of the files
failedTests=()
for file in "${testFiles[@]}"; do
# Skip onboarding.yml since it has already been run
if [ "$file" == "$onboardingFile" ]; then
continue
fi
if ! run_maestro_test "$file"; then
failedTests+=("$file")
fi
done
if [ ${#failedTests[@]} -gt 0 ]; then
echo "These tests failed:" >&2
printf '%s\n' "${failedTests[@]}" >&2
exit 1
fi

View file

@ -5,7 +5,8 @@ ARG REPO_REF=main
FROM debian:bookworm as base
ADD https://gist.githubusercontent.com/HeavenVolkoff/ff7b77b9087f956b8df944772e93c071/raw \
ADD --chmod=644 --checksum=sha256:8bea540b2cd1a47c94555e746c75fd41a42847a46d8c8c36c7ab6dd9c8526ab4 \
https://gist.githubusercontent.com/HeavenVolkoff/ff7b77b9087f956b8df944772e93c071/raw \
/etc/apt/apt.conf.d/99docker-apt-config
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
@ -28,6 +29,7 @@ ENV PNPM_HOME="/usr/share/pnpm" \
PATH="/usr/share/pnpm:$PATH"
RUN pnpm env use --global latest
RUN pnpm add -g pnpm@latest-8
WORKDIR /srv
@ -101,7 +103,11 @@ ENV TZ=UTC \
COPY --from=server --chmod=755 /srv/spacedrive/target/release/sd-server /usr/bin/
COPY --from=server --chmod=755 /lib/x86_64-linux-gnu/libgcc_s.so.1 /usr/lib/
COPY --from=server --chmod=755 /srv/spacedrive/apps/.deps/lib /usr/lib/spacedrive
ADD --chmod=755 https://github.com/spacedriveapp/native-deps/releases/download/yolo-2024-02-07/yolov8s.onnx /usr/share/spacedrive/models/yolov8s.onnx
ADD --chmod=755 --checksum=sha256:a99beabea22571cfad4f77422e5d3ed922d9490232d94cb87cf32956766bc42a \
https://github.com/kraj/uClibc/raw/v0.9.33.2/extra/scripts/getent /usr/bin/
ADD --chmod=755 --checksum=sha256:1d127c69218f2cd14964036f2b057c4b2652cda3996c6908605cc139192f66aa \
https://github.com/spacedriveapp/native-deps/releases/download/yolo-2024-02-07/yolov8s.onnx /usr/share/spacedrive/models/yolov8s.onnx
COPY --chmod=755 entrypoint.sh /usr/bin/

View file

@ -12,19 +12,70 @@ if [ -n "${1:-}" ] && [ "${1#-}" = "${1}" ] \
fi
if [ "$(id -u)" -ne 0 ]; then
echo "This container requires executing as root for initial setup, privilages are dropped after" 1>&2
echo "This container requires executing as root for initial setup, privileges are dropped shortly after" 1>&2
exit 1
fi
delpasswd () {
deluser "$@"
}
create () {
if [ "$#" -ne 3 ] || ! { [ "$1" = "group" ] || [ "$1" = "passwd" ]; } || [ -z "$2" ] || [ "$3" -le 0 ] ; then
echo "Usage: create <group|passwd> <NAME> <ID>" 1>&2
echo " NAME: Group or user name to be created" 1>&2
echo " ID: ID > 1000 to be assigned to the group or user" 1>&2
exit 1
fi
if getent "$1" "$2" >/dev/null; then
if [ "$(getent "$1" "$2" | cut -d: -f3)" = "$3" ]; then
echo "$1 $2 already exists with ID: $3"
return
else
"del${1}" "$2"
fi
fi
if getent "$1" "$3" >/dev/null; then
# WARNING: This need to be modified if this functions arguments are changed
set -- "$1" "$2" "$3" "$(getent "$1" "$3" | cut -d: -f1)"
if [ "$2" = "$4" ]; then
echo "$1 $2 already exists with ID: $3"
return
else
"del${1}" "$4"
fi
fi
case "$1" in
group)
addgroup --system --gid "$3" "$2"
;;
passwd)
rm -rf /var/empty
adduser \
--system \
--uid "$3" \
--home /var/empty \
--shell /bin/nologin \
--gecos "$2 system account" \
-G nobody \
--no-create-home \
"$2"
passwd -l "$2"
;;
esac
}
echo "Configure unprivileged user"
addgroup --system --gid "${PGID}" spacedrive
adduser --system --disabled-password \
--uid "${PUID}" \
--home /var/empty \
--gecos 'Spacedrive system account' \
--ingroup spacedrive \
spacedrive
passwd -l spacedrive
create group spacedrive 1000
create passwd spacedrive 1000
# Add spacedrive user to spacedrive group, if it is not already in it
if ! id -Gn spacedrive | tr '[:space:]+' '\n' | grep -x 'spacedrive'; then
adduser spacedrive spacedrive
fi
if [ -n "${TZ:-}" ]; then
echo "Set Timezone to $TZ"

View file

@ -18,12 +18,7 @@ const config: StorybookConfig = {
'@storybook/addon-essentials',
'@storybook/addon-interactions',
{
name: '@storybook/addon-styling',
options: {
// Check out https://github.com/storybookjs/addon-styling/blob/main/docs/api.md
// For more details on this addon's options.
postCss: true
}
name: '@storybook/addon-styling'
}
],
framework: {

View file

@ -6,13 +6,13 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@storybook/addon-essentials": "^7.5.1",
"@storybook/addon-interactions": "^7.5.1",
"@storybook/addon-links": "^7.5.1",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-interactions": "^7.6.17",
"@storybook/addon-links": "^7.6.17",
"@storybook/addon-styling": "^1.3.7",
"@storybook/blocks": "^7.5.1",
"@storybook/react": "^7.5.1",
"@storybook/react-vite": "^7.5.1",
"@storybook/blocks": "^7.6.17",
"@storybook/react": "^7.6.17",
"@storybook/react-vite": "^7.6.17",
"@storybook/testing-library": "^0.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
@ -20,15 +20,16 @@
"devDependencies": {
"@sd/config": "workspace:*",
"@sd/ui": "workspace:*",
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.35",
"postcss-pseudo-companion-classes": "^0.1.1",
"prop-types": "^15.8.1",
"storybook": "^7.5.2",
"rollup-plugin-node-builtins": "^2.1.2",
"storybook": "^7.6.17",
"tailwindcss": "^3.4.1",
"typescript": "^5.3.3",
"vite": "^5.0.10"
"vite": "^5.1.4"
}
}

View file

@ -0,0 +1,15 @@
import { createRequire } from 'node:module';
import baseConfig from '../../packages/config/vite';
const require = createRequire(import.meta.url);
// https://vitejs.dev/config/
export default {
...baseConfig,
resolve: {
alias: {
crypto: require.resolve('rollup-plugin-node-builtins')
}
}
};

View file

@ -1,4 +0,0 @@
import baseConfig from '../../packages/config/vite';
// https://vitejs.dev/config/
export default baseConfig;

View file

@ -7,10 +7,10 @@
"build": "vite build",
"preview": "vite preview",
"test": "VITE_SD_DEMO_MODE=true playwright test",
"typecheck": "tsc -b"
"typecheck": "tsc -b",
"lint": "eslint src --cache"
},
"dependencies": {
"@fontsource/inter": "^4.5.15",
"@oscartbeaumont-sd/rspc-client": "=0.0.0-main-dc31e5b2",
"@sd/client": "workspace:*",
"@sd/interface": "workspace:*",
@ -22,16 +22,16 @@
"react-router-dom": "6.20.1"
},
"devDependencies": {
"@playwright/test": "^1.39.0",
"@playwright/test": "^1.42.0",
"@sd/config": "workspace:*",
"@sd/ui": "workspace:*",
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31",
"rollup-plugin-visualizer": "^5.9.2",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.35",
"rollup-plugin-visualizer": "^5.12.0",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite-tsconfig-paths": "^4.2.1"
"vite": "^5.1.4",
"vite-tsconfig-paths": "^4.3.1"
}
}

View file

@ -3,13 +3,14 @@ import { ContextMenu, ModifierKeys } from '@sd/ui';
import { useLocale } from '~/hooks';
import { useKeybindFactory } from '~/hooks/useKeybindFactory';
import { isNonEmpty } from '~/util';
import { useLibraryMutation } from '@sd/client';
import { useExplorerContext } from '../../Context';
import { useExplorerCopyPaste } from '../../hooks/useExplorerCopyPaste';
import { ConditionalItem } from '../ConditionalItem';
import { useContextMenuContext } from '../context';
import type {} from '@sd/client';
export const CutCopyItems = new ConditionalItem({
useCondition: () => {
const { parent } = useExplorerContext();

View file

@ -34,7 +34,7 @@ export const RenameTextBox = forwardRef<HTMLDivElement, RenameTextBoxProps>(
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(_ref, () => ref.current);
const renamable = useRef<boolean>(false);
const timeout = useRef<NodeJS.Timeout | null>(null);
const timeout = useRef<number | null>(null);
const [allowRename, setAllowRename] = useState(false);
const [isTruncated, setIsTruncated] = useState(false);

View file

@ -11,8 +11,8 @@ export const useDragScrollable = ({ direction }: { direction: 'up' | 'down' }) =
const [node, setNode] = useState<HTMLElement | null>(null);
const timeout = useRef<NodeJS.Timeout | null>(null);
const interval = useRef<NodeJS.Timer | null>(null);
const timeout = useRef<number | null>(null);
const interval = useRef<number | null>(null);
useEffect(() => {
const element = node;

View file

@ -1,4 +1,4 @@
import { redirect } from '@remix-run/router';
import { redirect } from 'react-router';
import { type RouteObject } from 'react-router-dom';
import { Platform } from '~/util/Platform';
@ -43,9 +43,18 @@ export default (platform: Platform) =>
{
index: true,
loader: async () => {
if (!platform.userHomeDir) return redirect(`network`);
const homeDir = await platform.userHomeDir();
return redirect(`ephemeral/0?${new URLSearchParams({ path: homeDir })}`, {
try {
if (platform.userHomeDir) {
const homeDir = await platform.userHomeDir();
return redirect(`ephemeral/0?${new URLSearchParams({ path: homeDir })}`, {
replace: true
});
}
} catch (e) {
console.error('Failed to redirect to user home', e);
}
return redirect(`network`, {
replace: true
});
}

View file

@ -5,6 +5,7 @@ import { memo, useEffect, useRef, useState } from 'react';
import { languageMapping } from './prism';
const prismaLazy = import('./prism-lazy');
prismaLazy.catch((e) => console.error('Failed to load prism-lazy', e));
export interface TextViewerProps {
src: string;
@ -104,29 +105,33 @@ function TextRow({
const contentRef = useRef<HTMLSpanElement>(null);
useEffect(() => {
if (contentRef.current) {
const cb: IntersectionObserverCallback = async (events) => {
const ref = contentRef.current;
if (ref == null) return;
let intersectionObserver: null | IntersectionObserver = null;
prismaLazy.then(({ highlightElement }) => {
intersectionObserver = new IntersectionObserver((events) => {
for (const event of events) {
if (
!event.isIntersecting ||
contentRef.current?.getAttribute('data-highlighted') === 'true'
)
if (!event.isIntersecting || ref.getAttribute('data-highlighted') === 'true')
continue;
contentRef.current?.setAttribute('data-highlighted', 'true');
(await prismaLazy).highlightElement(event.target, false); // Prism's async seems to be broken
ref.setAttribute('data-highlighted', 'true');
highlightElement(event.target, false); // Prism's async seems to be broken
// With this class present TOML headers are broken Eg. `[dependencies]` will format over multiple lines
const children = contentRef.current?.children;
const children = ref.children;
if (children) {
for (const elem of children) {
elem.classList.remove('table');
}
}
}
};
});
intersectionObserver.observe(ref);
});
new IntersectionObserver(cb).observe(contentRef.current);
}
return () => intersectionObserver?.disconnect();
}, []);
return (

View file

@ -386,7 +386,7 @@ pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {
/* Border around popup */
.prism-previewer.prism-previewer:before,
.prism-previewer-gradient.prism-previewer-gradient div {
border-color: hsl(0, 0, 95%);
border-color: hsl(0, 0%, 95%);
}
/* Angle and time should remain as circles and are hence not included */
@ -398,11 +398,11 @@ pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {
/* Triangles pointing to the code */
.prism-previewer.prism-previewer:after {
border-top-color: hsl(0, 0, 95%);
border-top-color: hsl(0, 0%, 95%);
}
.prism-previewer-flipped.prism-previewer-flipped.after {
border-bottom-color: hsl(0, 0, 95%);
border-bottom-color: hsl(0, 0%, 95%);
}
/* Background colour within the popup */

View file

@ -1,3 +1,13 @@
//@ts-nocheck
// WARNING: Import order matters
window.Prism = window.Prism || {};
window.Prism.manual = true;
// This import must be first, to ensure that the `Prism` global is available before importing its language plugins
import "prismjs";
// Languages
// Do not include default ones: markup, html, xml, svg, mathml, ssml, atom, rss, css, clike, javascript, js
import 'prismjs/components/prism-applescript.js';
@ -49,11 +59,4 @@ import 'prismjs/components/prism-vala.js';
import 'prismjs/components/prism-yaml.js';
import 'prismjs/components/prism-zig.js';
//@ts-nocheck
// WARNING: Import order matters
window.Prism = window.Prism || {};
window.Prism.manual = true;
export { highlightElement } from 'prismjs';

View file

@ -1,10 +1,9 @@
// We keep these out of the `prism.tsx` as that stuff is lazy-loaded, and this stuff is not.
// We keep these out of the `prism-lazy.ts` as that stuff is lazy-loaded, and this stuff is not.
import { useThemeStore } from '@sd/client';
import { useThemeStore } from "@sd/client";
import oneDarkCss from "./one-dark.scss?url";
import oneLightCss from "./one-light.scss?url";
import oneDarkCss from './one-dark.scss?url';
import oneLightCss from './one-light.scss?url';
// Mapping between extensions and prismjs language identifier
// Only for those that are not already internally resolved by prismjs
@ -35,11 +34,9 @@ export const languageMapping = Object.entries({
export function WithPrismTheme() {
const theme = useThemeStore();
return (
theme.theme === "dark" ? (
<link rel="stylesheet" href={oneDarkCss} />
) : (
<link rel="stylesheet" href={oneLightCss} />
)
)
return theme.theme === 'dark' ? (
<link rel="stylesheet" href={oneDarkCss} />
) : (
<link rel="stylesheet" href={oneLightCss} />
);
}

View file

@ -1,5 +1,3 @@
import '@fontsource/inter/variable.css';
import dayjs from 'dayjs';
import advancedFormat from 'dayjs/plugin/advancedFormat';
import duration from 'dayjs/plugin/duration';

View file

@ -11,7 +11,6 @@
"dependencies": {
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/utilities": "^3.2.2",
"@fontsource/inter": "^4.5.15",
"@headlessui/react": "^1.7.17",
"@icons-pack/react-simple-icons": "^9.1.0",
"@phosphor-icons/react": "^2.0.13",
@ -72,13 +71,13 @@
"devDependencies": {
"@sd/config": "workspace:*",
"@types/node": "~18.17.19",
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",
"@types/uuid": "^9.0.6",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"@types/uuid": "^9.0.8",
"tailwindcss": "^3.4.1",
"type-fest": "^4.6.0",
"type-fest": "^4.10.3",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite": "^5.1.4",
"vite-plugin-svgr": "^3.3.0"
}
}

View file

@ -4,7 +4,7 @@
"paths": {
"~/*": ["./*"]
},
"types": ["vite-plugin-svgr/client", "vite/client", "node"],
"types": ["vite-plugin-svgr/client", "vite/client"],
"declarationDir": "dist"
},
"include": ["**/*"],

View file

@ -32,30 +32,27 @@
"clean": "git clean -qfX ."
},
"pnpm": {
"overrides": {
"@radix-ui/react-dismissable-layer": "1.0.2"
},
"patchedDependencies": {
"@remix-run/router@1.13.1": "patches/@remix-run__router@1.13.1.patch"
"@remix-run/router@1.13.1": "patches/@remix-run__router@1.13.1.patch",
"@contentlayer/cli@0.3.4": "patches/@contentlayer__cli@0.3.4.patch"
},
"overrides": {
"@types/node": "~18.17.19",
"@remix-run/router": "=1.13.1"
}
},
"devDependencies": {
"@babel/plugin-syntax-import-assertions": "^7.22.5",
"@cspell/dict-rust": "^4.0.1",
"@babel/plugin-syntax-import-assertions": "^7.23.3",
"@cspell/dict-rust": "^4.0.2",
"@cspell/dict-typescript": "^3.1.2",
"@ianvs/prettier-plugin-sort-imports": "^4.1.1",
"@storybook/react-vite": "^7.5.2",
"cspell": "^7.3.8",
"prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.6",
"turbo": "^1.11.2",
"turbo-ignore": "^1.10.16",
"cspell": "^8.4.1",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"turbo": "^1.12.4",
"turbo-ignore": "^1.12.4",
"typescript": "^5.3.3",
"vite": "^5.0.10"
},
"overrides": {
"vite-plugin-svgr": "https://github.com/spacedriveapp/vite-plugin-svgr#cb4195b69849429cdb18d1f12381676bf9196a84",
"@types/node": "~18.17.19"
"vite": "^5.1.4"
},
"engines": {
"pnpm": ">=8.0.0",

View file

@ -27,8 +27,8 @@
},
"devDependencies": {
"@sd/config": "workspace:*",
"@types/react": "^18.2.34",
"typescript": "^5.2.2"
"@types/react": "^18.2.60",
"typescript": "^5.3.3"
},
"peerDependencies": {
"react": "^18.2"

View file

@ -25,7 +25,10 @@ export const useCachedLibraries = () => {
return undefined;
},
onSuccess: (data) => localStorage.setItem(libraryCacheLocalStorageKey, JSON.stringify(data))
onSuccess: (data) => {
if (data.items.length > 0 || data.nodes.length > 0)
localStorage.setItem(libraryCacheLocalStorageKey, JSON.stringify(data));
}
});
useNodes(result.data?.nodes);
@ -53,7 +56,8 @@ export async function getCachedLibraries(cache: NormalisedCache) {
cache.withNodes(result.nodes);
const libraries = cache.withCache(result.items);
localStorage.setItem(libraryCacheLocalStorageKey, JSON.stringify(result));
if (result.items.length > 0 || result.nodes.length > 0)
localStorage.setItem(libraryCacheLocalStorageKey, JSON.stringify(result));
return libraries;
}

View file

@ -11,24 +11,24 @@
"lint": "eslint . --cache"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^8.53.0",
"eslint-config-next": "^13.5.6",
"eslint-config-prettier": "^9.0.0",
"eslint-config-turbo": "^1.10.16",
"eslint-plugin-prettier": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"@vitejs/plugin-react-swc": "^3.6.0",
"eslint": "^8.57.0",
"eslint-config-next": "^14.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^1.12.4",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-solid": "^0.13.1",
"eslint-plugin-tailwindcss": "^3.13.0",
"eslint-plugin-tailwindcss": "^3.14.3",
"eslint-utils": "^3.0.0",
"regexpp": "^3.2.0",
"vite-plugin-html": "^3.2.1",
"vite-plugin-i18next-loader": "^2.0.4",
"vite-plugin-inspect": "^0.8.1",
"vite-plugin-solid": "^2.8.0",
"vite-plugin-html": "^3.2.2",
"vite-plugin-i18next-loader": "^2.0.12",
"vite-plugin-inspect": "^0.8.3",
"vite-plugin-solid": "^2.10.1",
"vite-plugin-svgr": "^3.3.0"
},
"dependencies": {

View file

@ -1,4 +1,5 @@
import { fileURLToPath } from 'node:url';
import ts from '@babel/preset-typescript';
import react from '@vitejs/plugin-react-swc';
import million from 'million/compiler';
import { defineConfig } from 'vite';
@ -20,7 +21,7 @@ export default defineConfig({
namespaceResolution: 'relativePath'
}),
react(),
narrowSolidPlugin({ include: '**/*.solid.tsx' }),
narrowSolidPlugin({ include: '**/*.solid.tsx', babel: { presets: [[ts, {}]] } }),
svg({ svgrOptions: { icon: true } }),
createHtmlPlugin({
minify: true

View file

@ -46,21 +46,21 @@
"zod": "~3.22.4"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/core": "^7.23.9",
"@headlessui/tailwindcss": "^0.2.0",
"@sd/config": "workspace:*",
"@storybook/types": "^7.5.2",
"@tailwindcss/forms": "^0.5.6",
"@storybook/types": "^7.6.17",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"@types/node": "~18.17.19",
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31",
"sass": "^1.69.5",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.35",
"sass": "^1.71.1",
"tailwindcss": "^3.4.1",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-radix": "^2.8.0",
"typescript": "^5.2.2"
"typescript": "^5.3.3"
}
}

View file

@ -0,0 +1,13 @@
diff --git a/dist/commands/BuildCommand.js b/dist/commands/BuildCommand.js
index 17ef19082c821de94e06dc468dbff62217b272cd..aebb1bcb55d0d60b3d32408943f6ef495fe66f4e 100644
--- a/dist/commands/BuildCommand.js
+++ b/dist/commands/BuildCommand.js
@@ -4,7 +4,7 @@ import { BaseCommand } from './_BaseCommand.js';
export class BuildCommand extends BaseCommand {
constructor() {
super(...arguments);
- this.executeSafe = () => pipe(this.clearCacheIfNeeded(), T.chain(() => core.getConfig({ configPath: this.configPath })), T.tap((config) => (config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig))), T.chain((config) => core.generateDotpkg({ config, verbose: this.verbose })), T.tap(core.logGenerateInfo), OT.withSpan('@contentlayer/cli/commands/BuildCommand:executeSafe'));
+ this.executeSafe = () => pipe(this.clearCacheIfNeeded(), T.chain(() => core.getConfig({ configPath: this.configPath })), T.tap((config) => (config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig))), T.chain((config) => core.generateDotpkg({ config, verbose: this.verbose })), T.tap(core.logGenerateInfo), T.map(() => 0), OT.withSpan('@contentlayer/cli/commands/BuildCommand:executeSafe'));
}
}
BuildCommand.paths = [['build']];

File diff suppressed because it is too large Load diff

View file

@ -21,22 +21,22 @@
"@iarna/toml": "^2.2.5",
"archive-wasm": "^1.6.1",
"mustache": "^4.2.0",
"semver": "^7.5.4",
"undici": "^6.0.1"
"semver": "^7.6.0",
"undici": "^6.6.2"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.22.15",
"@babel/eslint-plugin": "^7.22.10",
"@types/mustache": "^4.2.4",
"@babel/core": "^7.23.9",
"@babel/eslint-parser": "^7.23.10",
"@babel/eslint-plugin": "^7.23.5",
"@types/mustache": "^4.2.5",
"@types/node": "~18.17.19",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-jsdoc": "^46.8.2",
"eslint-plugin-prettier": "^5.0.1",
"typescript": "^5.2.2"
"eslint-plugin-jsdoc": "^48.2.0",
"eslint-plugin-prettier": "^5.1.3",
"typescript": "^5.3.3"
}
}