Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 99 additions & 7 deletions app/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = {
'plugin:jest/recommended',
'plugin:prettier/recommended',
],
plugins: ['header', 'simple-import-sort', 'import'],
plugins: ['header', 'simple-import-sort', 'import', 'sort-exports'],
ignorePatterns: [
'ios/',
'android/',
Expand All @@ -41,34 +41,111 @@ module.exports = {
'import/ignore': ['react-native'],
},
rules: {
// Import/Export Rules
// Enhanced Import/Export Rules

'import/order': 'off',
'no-duplicate-imports': 'off',
'simple-import-sort/exports': 'warn',
'simple-import-sort/imports': 'warn',

// Header rule
// Import sorting with explicit groups for your project structure

'simple-import-sort/imports': [
'error',
{
groups: [
// Node.js built-ins

['^node:'],
['^node:.*/'],
// External packages

['^[a-zA-Z]'],
// Internal workspace packages

['^@selfxyz/'],
// Internal relative imports

['^[./]'],
],
},
],

// Export sorting - using sort-exports for better type prioritization

'sort-exports/sort-exports': [
'error',
{ sortDir: 'asc', ignoreCase: false, sortExportKindFirst: 'type' },
],

// Type import enforcement

'@typescript-eslint/consistent-type-imports': [
'error',
{ prefer: 'type-imports' },
],

// Standard import rules

'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-duplicates': 'error',

// Header rule - configured to prevent duplicates, single line header only

'header/header': [
2,
'error',
'line',
' SPDX-License-Identifier: BUSL-1.1; Copyright (c) 2025 Social Connect Labs, Inc.; Licensed under BUSL-1.1 (see LICENSE); Apache-2.0 from 2029-06-11',
2,
],

// Prevent empty lines at the beginning and end of files, and limit consecutive empty lines

'no-multiple-empty-lines': [
'error',
{
max: 1,
maxEOF: 0,
maxBOF: 0,
},
],
// Enforce empty line after header comments (but not at file start)

'lines-around-comment': [
'error',
{
beforeBlockComment: false,
afterBlockComment: false,
beforeLineComment: false,
afterLineComment: false,
allowBlockStart: true,
allowBlockEnd: false,
allowObjectStart: false,
allowObjectEnd: false,
allowArrayStart: false,
allowArrayEnd: false,
allowClassStart: false,
allowClassEnd: false,
applyDefaultIgnorePatterns: false,
},
],

// Add prettier rule to show prettier errors as ESLint errors

'prettier/prettier': ['warn', {}, { usePrettierrc: true }],

// React Core Rules

'react/no-unescaped-entities': 'off',
'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off',
'react-native/no-inline-styles': 'off',

// React Hooks Rules

'react-hooks/exhaustive-deps': 'warn',

// General JavaScript Rules
// Warn on common issues but don't block development

'no-console': 'warn',
'no-empty-pattern': 'off',
'prefer-const': 'warn',
Expand All @@ -85,6 +162,7 @@ module.exports = {
'no-empty': 'off',

// Override rules conflicting with TypeScript union formatting

'@typescript-eslint/indent': 'off',
},
overrides: [
Expand All @@ -105,5 +183,19 @@ module.exports = {
'no-undef': 'off',
},
},
{
// Disable export sorting for files with dependency issues
files: [
'src/components/NavBar/BaseNavBar.tsx',
'src/navigation/index.tsx',
'src/providers/passportDataProvider.tsx',
'src/utils/cloudBackup/helpers.ts',
'src/utils/haptic/index.ts',
'src/utils/proving/provingUtils.ts',
],
rules: {
'sort-exports/sort-exports': 'off',
},
},
],
};
4 changes: 2 additions & 2 deletions app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: BUSL-1.1; Copyright (c) 2025 Social Connect Labs, Inc.; Licensed under BUSL-1.1 (see LICENSE); Apache-2.0 from 2029-06-11

// CI/CD Pipeline Test - July 31, 2025 - With Permissions Fix
import 'react-native-get-random-values';

import { Buffer } from 'buffer';
import React from 'react';
import { YStack } from 'tamagui';
Expand All @@ -16,6 +14,8 @@ import { PassportProvider } from './src/providers/passportDataProvider';
import { RemoteConfigProvider } from './src/providers/remoteConfigProvider';
import { initSentry, wrapWithSentry } from './src/Sentry';

import 'react-native-get-random-values';

initSentry();

global.Buffer = Buffer;
Expand Down
24 changes: 14 additions & 10 deletions app/env.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
// SPDX-License-Identifier: BUSL-1.1; Copyright (c) 2025 Social Connect Labs, Inc.; Licensed under BUSL-1.1 (see LICENSE); Apache-2.0 from 2029-06-11
export const DEFAULT_DOB = undefined;

/* This file provides compatiblity between how web expects env variables to be and how native does.
* on web it is aliased to @env on native it is not used
*/
export const DEFAULT_DOE = undefined;

export const DEFAULT_PNUMBER = undefined;

export const ENABLE_DEBUG_LOGS = process.env.ENABLE_DEBUG_LOGS === 'true';

export const IS_TEST_BUILD = process.env.IS_TEST_BUILD === 'true';
export const GOOGLE_SIGNIN_ANDROID_CLIENT_ID =
process.env.GOOGLE_SIGNIN_ANDROID_CLIENT_ID;

export const GOOGLE_SIGNIN_WEB_CLIENT_ID =
process.env.GOOGLE_SIGNIN_WEB_CLIENT_ID;
export const SENTRY_DSN = process.env.SENTRY_DSN;
export const SEGMENT_KEY = process.env.SEGMENT_KEY;
export const ENABLE_DEBUG_LOGS = process.env.ENABLE_DEBUG_LOGS === 'true';
export const DEFAULT_PNUMBER = undefined;
export const DEFAULT_DOB = undefined;
export const DEFAULT_DOE = undefined;

/* This file provides compatiblity between how web expects env variables to be and how native does.
* on web it is aliased to @env on native it is not used
*/
export const IS_TEST_BUILD = process.env.IS_TEST_BUILD === 'true';
export const MIXPANEL_NFC_PROJECT_TOKEN = undefined;
export const SEGMENT_KEY = process.env.SEGMENT_KEY;
export const SENTRY_DSN = process.env.SENTRY_DSN;
8 changes: 4 additions & 4 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
/**
* @format
*/
import './src/utils/ethers';
import 'react-native-gesture-handler';

import { config } from '@tamagui/config/v2-native';
import React from 'react';
import { AppRegistry, LogBox } from 'react-native';
import { createTamagui, TamaguiProvider } from 'tamagui';

import App from './App';
import { name as appName } from './app.json';

import './src/utils/ethers';
import 'react-native-gesture-handler';
import { config } from '@tamagui/config/v2-native';

const tamaguiConfig = createTamagui(config);

LogBox.ignoreLogs([
Expand Down
8 changes: 5 additions & 3 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
"install-app:setup": "yarn install && yarn build:deps && cd ios && bundle install && bundle exec pod install && cd ..",
"ios": "yarn build:deps && react-native run-ios --scheme OpenPassport",
"ios:fastlane-debug": "yarn reinstall && bundle exec fastlane --verbose ios internal_test",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"lint": "yarn lint:headers && eslint .",
"lint:fix": "yarn lint:headers && eslint --fix .",
"lint:headers": "node scripts/check-duplicate-headers.cjs",
"mobile-deploy": "node scripts/mobile-deploy-confirm.cjs both",
"mobile-deploy:android": "node scripts/mobile-deploy-confirm.cjs android",
"mobile-deploy:ios": "node scripts/mobile-deploy-confirm.cjs ios",
Expand All @@ -52,7 +53,7 @@
"tag:release": "node scripts/tag.js release",
"tag:remove": "node scripts/tag.js remove",
"test": "jest --passWithNoTests && node --test scripts/tests/*.cjs",
"test:build": "yarn build:deps && yarn web:build && yarn types && yarn analyze:bundle:ios",
"test:build": "yarn build:deps && yarn web:build && yarn types && yarn analyze:bundle:ios && yarn test",
"test:coverage": "jest --coverage --passWithNoTests",
"test:coverage:ci": "jest --coverage --passWithNoTests --ci --coverageReporters=lcov --coverageReporters=text --coverageReporters=json",
"test:fastlane": "bundle exec ruby -Itest fastlane/test/helpers_test.rb",
Expand Down Expand Up @@ -175,6 +176,7 @@
"eslint-plugin-jest": "^28.11.1",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-sort-exports": "^0.9.1",
"jest": "^29.6.3",
"prettier": "^3.5.3",
"react-native-svg-transformer": "^1.5.0",
Expand Down
62 changes: 62 additions & 0 deletions app/scripts/check-duplicate-headers.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const { glob } = require('glob');

const LICENSE_HEADER_PATTERN = /SPDX-License-Identifier:/;
const EXTENSIONS = ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'];

function checkFile(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');

const headerLines = lines
.map((line, index) => ({ line, index: index + 1 }))
.filter(({ line }) => LICENSE_HEADER_PATTERN.test(line));

if (headerLines.length > 1) {
console.error(`\n❌ Multiple license headers found in ${filePath}:`);
headerLines.forEach(({ index }) => {
console.error(` Line ${index}`);
});
return false;
}

return true;
}

function main() {
let hasErrors = false;

// Get all relevant files
const patterns = EXTENSIONS.map(ext => path.join('src', ext));
patterns.push('*.ts', '*.tsx', '*.js', '*.jsx');

for (const pattern of patterns) {
const files = glob.sync(pattern, {
ignore: ['node_modules/**', 'dist/**', 'build/**', '**/*.d.ts'],
});

for (const file of files) {
if (!checkFile(file)) {
hasErrors = true;
}
}
}

if (hasErrors) {
console.error(
'\n💡 Fix: Remove duplicate license headers. Only keep the one at the top of each file.\n',
);
process.exit(1);
} else {
console.log('✅ No duplicate license headers found');
}
}

if (require.main === module) {
main();
}

module.exports = { checkFile };
Loading
Loading