Skip to content

Commit 2492612

Browse files
committed
RU-T42 PR#214 fixes
1 parent 98288c7 commit 2492612

File tree

81 files changed

+3327
-1773
lines changed

Some content is hidden

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

81 files changed

+3327
-1773
lines changed

.eslintignore

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.eslintignorenode_modules
1+
node_modules
22
__tests__/
33
.vscode/
44
android/
@@ -7,4 +7,9 @@ ios/
77
.expo
88
.expo-shared
99
docs/
10-
cli/
10+
cli/
11+
electron/
12+
fastlane/
13+
patches/
14+
public/
15+
scripts/

.eslintrc.js

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
const path = require('path');
22

33
module.exports = {
4-
extends: ['expo', 'plugin:tailwindcss/recommended', 'prettier'],
5-
plugins: ['prettier', 'unicorn', '@typescript-eslint', 'unused-imports', 'tailwindcss', 'simple-import-sort', 'eslint-plugin-react-compiler'],
6-
parserOptions: {
7-
project: './tsconfig.json',
8-
},
4+
extends: ['expo', 'prettier'],
5+
plugins: ['prettier', 'unicorn', '@typescript-eslint', 'unused-imports', 'simple-import-sort', 'eslint-plugin-react-compiler'],
6+
// parserOptions: {
7+
// project: './tsconfig.json',
8+
// },
99
rules: {
1010
'prettier/prettier': 'warn',
1111
'max-params': ['error', 10], // Limit the number of parameters in a function to use object instead
@@ -24,17 +24,10 @@ module.exports = {
2424
},
2525
], // Ensure `import type` is used when it's necessary
2626
'import/prefer-default-export': 'off', // Named export is easier to refactor automatically
27-
'import/no-cycle': ['error', { maxDepth: '∞' }],
28-
'tailwindcss/classnames-order': [
29-
'warn',
30-
{
31-
officialSorting: true,
32-
},
33-
], // Follow the same ordering as the official plugin `prettier-plugin-tailwindcss`
27+
'import/no-cycle': 'off', // Disabled due to performance issues
3428
'simple-import-sort/imports': 'error', // Import configuration for `eslint-plugin-simple-import-sort`
3529
'simple-import-sort/exports': 'error', // Export configuration for `eslint-plugin-simple-import-sort`
3630
'@typescript-eslint/no-unused-vars': 'off',
37-
'tailwindcss/no-custom-classname': 'off',
3831
'unused-imports/no-unused-imports': 'off',
3932
'unused-imports/no-unused-vars': [
4033
'off',

__mocks__/react-native-svg.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
3+
const createMockComponent = (name: string) => {
4+
const Component = React.forwardRef((props: any, ref: any) =>
5+
React.createElement(name, { ...props, ref })
6+
);
7+
Component.displayName = name;
8+
return Component;
9+
};
10+
11+
export const Svg = createMockComponent('Svg');
12+
export const Circle = createMockComponent('Circle');
13+
export const Ellipse = createMockComponent('Ellipse');
14+
export const G = createMockComponent('G');
15+
export const Text = createMockComponent('SvgText');
16+
export const TSpan = createMockComponent('TSpan');
17+
export const TextPath = createMockComponent('TextPath');
18+
export const Path = createMockComponent('Path');
19+
export const Polygon = createMockComponent('Polygon');
20+
export const Polyline = createMockComponent('Polyline');
21+
export const Line = createMockComponent('Line');
22+
export const Rect = createMockComponent('Rect');
23+
export const Use = createMockComponent('Use');
24+
export const Image = createMockComponent('SvgImage');
25+
export const Symbol = createMockComponent('SvgSymbol');
26+
export const Defs = createMockComponent('Defs');
27+
export const LinearGradient = createMockComponent('LinearGradient');
28+
export const RadialGradient = createMockComponent('RadialGradient');
29+
export const Stop = createMockComponent('Stop');
30+
export const ClipPath = createMockComponent('ClipPath');
31+
export const Pattern = createMockComponent('Pattern');
32+
export const Mask = createMockComponent('Mask');
33+
export const ForeignObject = createMockComponent('ForeignObject');
34+
export const Marker = createMockComponent('Marker');
35+
export const SvgFromUri = createMockComponent('SvgFromUri');
36+
export const SvgFromXml = createMockComponent('SvgFromXml');
37+
export const SvgXml = createMockComponent('SvgXml');
38+
export const SvgUri = createMockComponent('SvgUri');
39+
export const SvgCss = createMockComponent('SvgCss');
40+
export const SvgCssUri = createMockComponent('SvgCssUri');
41+
export const parse = jest.fn();
42+
43+
export default Svg;

electron/main.js

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const { app, BrowserWindow, ipcMain, Notification, nativeTheme, Menu, protocol, net } = require('electron');
33
const path = require('path');
44
const fs = require('fs');
5+
const { pathToFileURL } = require('url');
56

67
// Register custom protocol scheme before app is ready
78
// This allows serving the Expo web export with absolute paths (/_expo/static/...)
@@ -179,25 +180,35 @@ app.whenReady().then(() => {
179180
// Register custom protocol handler for serving the Expo web export
180181
// This resolves absolute paths like /_expo/static/js/... from the dist directory
181182
const distPath = path.join(__dirname, '..', 'dist');
183+
const resolvedDist = path.resolve(distPath);
182184

183185
protocol.handle('app', (request) => {
184186
const url = new URL(request.url);
185187
// Decode the pathname and resolve to a file in dist/
186-
let filePath = path.join(distPath, decodeURIComponent(url.pathname));
187-
188-
// If the path points to a directory or file doesn't exist, fall back to index.html
189-
// This supports SPA client-side routing
190-
try {
191-
const stat = fs.statSync(filePath);
192-
if (stat.isDirectory()) {
193-
filePath = path.join(distPath, 'index.html');
188+
const resolvedPath = path.resolve(distPath, decodeURIComponent(url.pathname));
189+
190+
// Security check: ensure resolved path is within distPath to prevent directory traversal
191+
let filePath;
192+
if (!resolvedPath.startsWith(resolvedDist + path.sep) && resolvedPath !== resolvedDist) {
193+
// Path escapes distPath - fall back to index.html
194+
filePath = path.join(resolvedDist, 'index.html');
195+
} else {
196+
filePath = resolvedPath;
197+
198+
// If the path points to a directory or file doesn't exist, fall back to index.html
199+
// This supports SPA client-side routing
200+
try {
201+
const stat = fs.statSync(filePath);
202+
if (stat.isDirectory()) {
203+
filePath = path.join(resolvedDist, 'index.html');
204+
}
205+
} catch {
206+
// File not found - serve index.html for client-side routing
207+
filePath = path.join(resolvedDist, 'index.html');
194208
}
195-
} catch {
196-
// File not found - serve index.html for client-side routing
197-
filePath = path.join(distPath, 'index.html');
198209
}
199210

200-
return net.fetch('file://' + filePath);
211+
return net.fetch(pathToFileURL(filePath).toString());
201212
});
202213

203214
createMenu();

jest-setup.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,34 @@ global.window = {};
66
// @ts-ignore
77
global.window = global;
88

9+
// Mock react-native Platform globally
10+
// Must include `default` export because react-native/index.js and processColor.js
11+
// access Platform via require('./Libraries/Utilities/Platform').default
12+
jest.mock('react-native/Libraries/Utilities/Platform', () => {
13+
const platform = {
14+
OS: 'ios' as const,
15+
select: jest.fn((obj: any) => obj.ios ?? obj.native ?? obj.default),
16+
Version: 14,
17+
constants: {
18+
osVersion: '14.0',
19+
interfaceIdiom: 'phone',
20+
isTesting: true,
21+
reactNativeVersion: { major: 0, minor: 76, patch: 0 },
22+
systemName: 'iOS',
23+
},
24+
isTesting: true,
25+
isPad: false,
26+
isTV: false,
27+
isVision: false,
28+
isMacCatalyst: false,
29+
};
30+
return {
31+
__esModule: true,
32+
default: platform,
33+
...platform,
34+
};
35+
});
36+
937
// Mock expo-audio globally
1038
jest.mock('expo-audio', () => ({
1139
createAudioPlayer: jest.fn(() => ({

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"build:internal:android": "cross-env APP_ENV=internal EXPO_NO_DOTENV=1 eas build --profile internal --platform android",
3636
"postinstall": "patch-package",
3737
"app-release": "cross-env SKIP_BRANCH_PROTECTION=true np --no-publish --no-cleanup --no-release-draft",
38-
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
38+
"lint": "eslint src --ext .ts,.tsx --cache --cache-location node_modules/.cache/eslint",
3939
"type-check": "tsc --noemit",
4040
"lint:translations": "eslint ./src/translations/ --fix --ext .json ",
4141
"test": "jest --coverage=true --coverageReporters=cobertura",

0 commit comments

Comments
 (0)