@alphatechma/expo-rn-template 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +31 -5
- package/.github/workflows/release.yml +25 -3
- package/App.tsx +37 -37
- package/README.md +12 -0
- package/babel.config.js +27 -0
- package/package.json +25 -15
- package/prettier.config.js +3 -3
- package/src/hooks/index.tsx +5 -9
- package/src/routes/index.tsx +2 -11
- package/src/screens/Home/styles.ts +0 -85
|
@@ -10,6 +10,9 @@ jobs:
|
|
|
10
10
|
publish:
|
|
11
11
|
name: Publish package
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write # habilita OIDC
|
|
15
|
+
contents: write
|
|
13
16
|
steps:
|
|
14
17
|
- name: Checkout repository
|
|
15
18
|
uses: actions/checkout@v4
|
|
@@ -20,8 +23,28 @@ jobs:
|
|
|
20
23
|
node-version: '18'
|
|
21
24
|
registry-url: 'https://registry.npmjs.org'
|
|
22
25
|
|
|
26
|
+
- name: Show versions
|
|
27
|
+
run: |
|
|
28
|
+
node --version
|
|
29
|
+
npm --version
|
|
30
|
+
|
|
23
31
|
- name: Install dependencies
|
|
24
|
-
run:
|
|
32
|
+
run: |
|
|
33
|
+
if [ -f package-lock.json ]; then
|
|
34
|
+
npm ci --no-audit --no-fund || npm install --legacy-peer-deps --no-audit --no-fund
|
|
35
|
+
else
|
|
36
|
+
npm install --legacy-peer-deps --no-audit --no-fund
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
- name: Verify OIDC authentication (npm whoami)
|
|
40
|
+
run: |
|
|
41
|
+
echo "Attempting OIDC authentication (trusted publisher must be configured on npmjs)."
|
|
42
|
+
if npm whoami; then
|
|
43
|
+
echo "OIDC authentication succeeded"
|
|
44
|
+
else
|
|
45
|
+
echo "OIDC authentication failed. Configure Trusted Publishers on npmjs for this repository/workflow or add NODE_AUTH_TOKEN as a secret as a fallback."
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
25
48
|
|
|
26
49
|
- name: Run lint
|
|
27
50
|
run: npm run lint || true
|
|
@@ -32,9 +55,12 @@ jobs:
|
|
|
32
55
|
- name: Build (if defined)
|
|
33
56
|
run: npm run build --if-present
|
|
34
57
|
|
|
58
|
+
- name: Publish (dry-run)
|
|
59
|
+
run: |
|
|
60
|
+
echo "Dry-run publish (OIDC)..."
|
|
61
|
+
npm publish --dry-run --access public || true
|
|
62
|
+
|
|
35
63
|
- name: Publish to npm
|
|
36
|
-
env:
|
|
37
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
38
64
|
run: |
|
|
39
|
-
echo "Publishing package..."
|
|
40
|
-
npm publish --access public
|
|
65
|
+
echo "Publishing package (OIDC)..."
|
|
66
|
+
npm publish --access public --provenance
|
|
@@ -8,6 +8,9 @@ on:
|
|
|
8
8
|
jobs:
|
|
9
9
|
release:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
contents: write
|
|
11
14
|
steps:
|
|
12
15
|
- name: Checkout
|
|
13
16
|
uses: actions/checkout@v4
|
|
@@ -18,11 +21,30 @@ jobs:
|
|
|
18
21
|
node-version: '18'
|
|
19
22
|
registry-url: 'https://registry.npmjs.org'
|
|
20
23
|
|
|
24
|
+
- name: Show environment versions
|
|
25
|
+
run: |
|
|
26
|
+
node --version
|
|
27
|
+
npm --version
|
|
28
|
+
|
|
21
29
|
- name: Install dependencies
|
|
22
|
-
run: npm
|
|
30
|
+
run: npm install --legacy-peer-deps --no-audit --no-fund
|
|
31
|
+
|
|
32
|
+
- name: Verify OIDC authentication (npm whoami)
|
|
33
|
+
run: |
|
|
34
|
+
echo "Attempting OIDC authentication (trusted publisher must be configured on npmjs)."
|
|
35
|
+
if npm whoami; then
|
|
36
|
+
echo "OIDC authentication succeeded"
|
|
37
|
+
else
|
|
38
|
+
echo "OIDC authentication failed. Configure Trusted Publishers on npmjs for this repository/workflow or add NODE_AUTH_TOKEN as a secret as a fallback."
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
- name: Semantic-release (dry-run)
|
|
43
|
+
env:
|
|
44
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
45
|
+
run: npx semantic-release --dry-run
|
|
23
46
|
|
|
24
|
-
- name:
|
|
47
|
+
- name: Semantic-release (publish)
|
|
25
48
|
env:
|
|
26
49
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
28
50
|
run: npx semantic-release
|
package/App.tsx
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
Roboto_300Light,
|
|
3
|
+
Roboto_400Regular,
|
|
4
|
+
Roboto_500Medium,
|
|
5
|
+
Roboto_700Bold,
|
|
6
|
+
Roboto_900Black,
|
|
7
|
+
useFonts,
|
|
8
8
|
} from '@expo-google-fonts/roboto';
|
|
9
9
|
import Routes from '@routes/index';
|
|
10
|
-
import {setupStore} from '@src/store/store';
|
|
11
|
-
import {StatusBar} from 'expo-status-bar';
|
|
10
|
+
import { setupStore } from '@src/store/store';
|
|
11
|
+
import { StatusBar } from 'expo-status-bar';
|
|
12
12
|
import React from 'react';
|
|
13
|
-
import {ActivityIndicator, View} from 'react-native';
|
|
14
|
-
import {GestureHandlerRootView} from 'react-native-gesture-handler';
|
|
15
|
-
import {Provider} from 'react-redux';
|
|
13
|
+
import { ActivityIndicator, View } from 'react-native';
|
|
14
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
15
|
+
import { Provider } from 'react-redux';
|
|
16
16
|
|
|
17
17
|
import AppProvider from './src/hooks';
|
|
18
18
|
|
|
19
19
|
export default function App() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!fontsLoaded) {
|
|
29
|
-
return (
|
|
30
|
-
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
|
|
31
|
-
<ActivityIndicator color="aliceblue"/>
|
|
32
|
-
</View>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
const store = setupStore();
|
|
20
|
+
const [fontsLoaded] = useFonts({
|
|
21
|
+
Roboto_300Light,
|
|
22
|
+
Roboto_400Regular,
|
|
23
|
+
Roboto_500Medium,
|
|
24
|
+
Roboto_700Bold,
|
|
25
|
+
Roboto_900Black,
|
|
26
|
+
});
|
|
36
27
|
|
|
28
|
+
if (!fontsLoaded) {
|
|
37
29
|
return (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<AppProvider>
|
|
42
|
-
<View style={{flex: 1}}>
|
|
43
|
-
<Routes/>
|
|
44
|
-
</View>
|
|
45
|
-
</AppProvider>
|
|
46
|
-
</Provider>
|
|
47
|
-
</GestureHandlerRootView>
|
|
30
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
31
|
+
<ActivityIndicator color="aliceblue" />
|
|
32
|
+
</View>
|
|
48
33
|
);
|
|
34
|
+
}
|
|
35
|
+
const store = setupStore();
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
39
|
+
<Provider store={store}>
|
|
40
|
+
<StatusBar style="light" />
|
|
41
|
+
<AppProvider>
|
|
42
|
+
<View style={{ flex: 1 }}>
|
|
43
|
+
<Routes />
|
|
44
|
+
</View>
|
|
45
|
+
</AppProvider>
|
|
46
|
+
</Provider>
|
|
47
|
+
</GestureHandlerRootView>
|
|
48
|
+
);
|
|
49
49
|
}
|
package/README.md
CHANGED
|
@@ -257,3 +257,15 @@ Se quiser eu:
|
|
|
257
257
|
- 3) adiciono um script `create-app` simples que copia o template e roda um assistant de setup.
|
|
258
258
|
|
|
259
259
|
Diga qual das opções acima prefere que eu crie em seguida.
|
|
260
|
+
|
|
261
|
+
### Nota sobre lockfile (recomendado)
|
|
262
|
+
|
|
263
|
+
Para builds reprodutíveis e para que o workflow `npm ci` funcione sem problemas, é recomendável commitar o `package-lock.json` no repositório. Porém, alguns ambientes (ou templates) não incluem o lockfile — por isso os workflows desse template utilizam `npm install --legacy-peer-deps --no-audit --no-fund` quando necessário, que é mais tolerante a ausência do lockfile e a conflitos de peer.
|
|
264
|
+
|
|
265
|
+
Se quiser garantir installs idempotentes em CI, gere o lockfile localmente e commite:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
npm install --legacy-peer-deps
|
|
269
|
+
git add package-lock.json
|
|
270
|
+
git commit -m "chore: add package-lock.json"
|
|
271
|
+
```
|
package/babel.config.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module.exports = function (api) {
|
|
2
|
+
api.cache(true);
|
|
3
|
+
return {
|
|
4
|
+
presets: ['babel-preset-expo'],
|
|
5
|
+
plugins: [
|
|
6
|
+
[
|
|
7
|
+
'module-resolver',
|
|
8
|
+
{
|
|
9
|
+
root: ['./src'],
|
|
10
|
+
alias: {
|
|
11
|
+
'@src': './src',
|
|
12
|
+
'@assets': './src/assets',
|
|
13
|
+
'@components': './src/components',
|
|
14
|
+
'@routes': './src/routes',
|
|
15
|
+
'@screens': './src/screens',
|
|
16
|
+
'@globals': './src/globals',
|
|
17
|
+
'@hooks': './src/hooks',
|
|
18
|
+
'@services': './src/services',
|
|
19
|
+
'@theme': './src/styles',
|
|
20
|
+
'@contexts': './src/contexts',
|
|
21
|
+
'@utils': './src/utils',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alphatechma/expo-rn-template",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"description": "Expo React Native template by Alphatech - base templatizada para apps Expo.",
|
|
6
|
-
"keywords": [
|
|
6
|
+
"keywords": [
|
|
7
|
+
"expo",
|
|
8
|
+
"react-native",
|
|
9
|
+
"template",
|
|
10
|
+
"starter",
|
|
11
|
+
"typescript",
|
|
12
|
+
"mobile",
|
|
13
|
+
"alphatech"
|
|
14
|
+
],
|
|
7
15
|
"repository": {
|
|
8
16
|
"type": "git",
|
|
9
17
|
"url": "https://github.com/alphatechma/expo-rn-template.git"
|
|
@@ -39,41 +47,43 @@
|
|
|
39
47
|
"buffer": "^6.0.3",
|
|
40
48
|
"core-js": "^3.47.0",
|
|
41
49
|
"date-fns": "^4.1.0",
|
|
42
|
-
"expo": "
|
|
50
|
+
"expo": "^52.0.23",
|
|
43
51
|
"expo-location": "^19.0.8",
|
|
44
52
|
"expo-splash-screen": "^31.0.13",
|
|
45
53
|
"expo-status-bar": "~3.0.9",
|
|
46
54
|
"expo-updates": "^29.0.16",
|
|
47
|
-
"react": "
|
|
55
|
+
"react": "18.3.1",
|
|
48
56
|
"react-dom": "19.1.0",
|
|
49
57
|
"react-hook-form": "^7.71.1",
|
|
50
|
-
"react-native": "0.
|
|
58
|
+
"react-native": "0.76.5",
|
|
51
59
|
"react-native-date-picker": "^5.0.13",
|
|
52
60
|
"react-native-gesture-handler": "^2.30.0",
|
|
53
61
|
"react-native-iphone-x-helper": "^1.3.1",
|
|
54
|
-
"react-native-reanimated": "~
|
|
62
|
+
"react-native-reanimated": "~4.1.1",
|
|
55
63
|
"react-native-responsive-fontsize": "^0.5.1",
|
|
56
64
|
"react-native-safe-area-context": "^5.6.2",
|
|
57
|
-
"react-native-screens": "
|
|
65
|
+
"react-native-screens": "~4.4.0",
|
|
58
66
|
"react-native-svg": "^15.15.1",
|
|
67
|
+
"react-native-worklets": "0.5.1",
|
|
59
68
|
"react-redux": "^9.2.0",
|
|
60
69
|
"styled-components": "^6.3.8",
|
|
61
70
|
"yup": "^1.7.1"
|
|
62
71
|
},
|
|
63
72
|
"devDependencies": {
|
|
73
|
+
"@semantic-release/changelog": "^6.0.0",
|
|
74
|
+
"@semantic-release/commit-analyzer": "^10.0.0",
|
|
75
|
+
"@semantic-release/git": "^10.0.0",
|
|
76
|
+
"@semantic-release/npm": "^9.0.0",
|
|
77
|
+
"@semantic-release/release-notes-generator": "^10.0.0",
|
|
64
78
|
"@types/react": "^19.2.8",
|
|
79
|
+
"babel-plugin-module-resolver": "^5.0.0",
|
|
65
80
|
"eslint": "^8.52.0",
|
|
66
81
|
"eslint-config-universe": "^12.0.0",
|
|
67
|
-
"prettier": "^3.0.3",
|
|
68
82
|
"husky": "^8.0.0",
|
|
69
83
|
"lint-staged": "^15.0.0",
|
|
70
|
-
"
|
|
84
|
+
"prettier": "^3.0.3",
|
|
71
85
|
"semantic-release": "^21.0.0",
|
|
72
|
-
"
|
|
73
|
-
"@semantic-release/git": "^10.0.0",
|
|
74
|
-
"@semantic-release/npm": "^9.0.0",
|
|
75
|
-
"@semantic-release/release-notes-generator": "^10.0.0",
|
|
76
|
-
"@semantic-release/commit-analyzer": "^10.0.0"
|
|
86
|
+
"typescript": "^5.3.3"
|
|
77
87
|
},
|
|
78
88
|
"lint-staged": {
|
|
79
89
|
"src/**/*.{js,jsx,ts,tsx}": [
|
|
@@ -89,4 +99,4 @@
|
|
|
89
99
|
"publishConfig": {
|
|
90
100
|
"access": "public"
|
|
91
101
|
}
|
|
92
|
-
}
|
|
102
|
+
}
|
package/prettier.config.js
CHANGED
package/src/hooks/index.tsx
CHANGED
|
@@ -6,8 +6,6 @@ import { View } from 'react-native';
|
|
|
6
6
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
7
7
|
import { ThemeProvider } from 'styled-components/native';
|
|
8
8
|
|
|
9
|
-
const PopupRootProvider: any = require('react-native-popup-confirm-toast').Root;
|
|
10
|
-
|
|
11
9
|
interface AppProviderProps {
|
|
12
10
|
children: ReactElement;
|
|
13
11
|
}
|
|
@@ -16,13 +14,11 @@ const AppProvider = ({ children }: AppProviderProps) => {
|
|
|
16
14
|
return (
|
|
17
15
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
18
16
|
<ThemeProvider theme={theme}>
|
|
19
|
-
<
|
|
20
|
-
<
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</LoadingProvider>
|
|
25
|
-
</PopupRootProvider>
|
|
17
|
+
<LoadingProvider>
|
|
18
|
+
<NavigationContainer>
|
|
19
|
+
<View style={{ flex: 1 }}>{children}</View>
|
|
20
|
+
</NavigationContainer>
|
|
21
|
+
</LoadingProvider>
|
|
26
22
|
</ThemeProvider>
|
|
27
23
|
</GestureHandlerRootView>
|
|
28
24
|
);
|
package/src/routes/index.tsx
CHANGED
|
@@ -4,7 +4,6 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
|
4
4
|
import { Home } from '@screens/index';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
// Tipos de navegação (ajuste conforme sua aplicação)
|
|
8
7
|
export type StackParamList = {
|
|
9
8
|
Home: undefined;
|
|
10
9
|
};
|
|
@@ -18,21 +17,13 @@ const Tab = createBottomTabNavigator<BottomTabRoutes>();
|
|
|
18
17
|
|
|
19
18
|
const HomeStackRoutes: React.FC = () => (
|
|
20
19
|
<Stack.Navigator>
|
|
21
|
-
<Stack.Screen
|
|
22
|
-
name="Home"
|
|
23
|
-
component={Home}
|
|
24
|
-
options={{ headerShown: true }}
|
|
25
|
-
/>
|
|
20
|
+
<Stack.Screen name="Home" component={Home} />
|
|
26
21
|
</Stack.Navigator>
|
|
27
22
|
);
|
|
28
23
|
|
|
29
24
|
export default function Routes() {
|
|
30
25
|
return (
|
|
31
|
-
<Tab.Navigator
|
|
32
|
-
screenOptions={{
|
|
33
|
-
headerShown: false,
|
|
34
|
-
}}
|
|
35
|
-
>
|
|
26
|
+
<Tab.Navigator>
|
|
36
27
|
<Tab.Screen
|
|
37
28
|
name="Inicio"
|
|
38
29
|
component={HomeStackRoutes}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import theme from '@theme/theme';
|
|
2
|
-
import { Dimensions } from 'react-native';
|
|
3
|
-
import { getStatusBarHeight } from 'react-native-iphone-x-helper';
|
|
4
|
-
import { RFValue } from 'react-native-responsive-fontsize';
|
|
5
|
-
import styled from 'styled-components/native';
|
|
6
|
-
|
|
7
|
-
export const Container = styled.ScrollView`
|
|
8
|
-
flex: 1;
|
|
9
|
-
background-color: ${({ theme }: any) => theme.colors.white};
|
|
10
|
-
`;
|
|
11
|
-
|
|
12
|
-
export const ContentContainer = styled.View`
|
|
13
|
-
padding: 0 20px 20px;
|
|
14
|
-
`;
|
|
15
|
-
|
|
16
|
-
export const Logo = styled.Image`
|
|
17
|
-
height: ${RFValue(70)}px;
|
|
18
|
-
width: ${RFValue(80)}px;
|
|
19
|
-
`;
|
|
20
|
-
|
|
21
|
-
export const Header = styled.ImageBackground.attrs({
|
|
22
|
-
blurRadius: 5,
|
|
23
|
-
})`
|
|
24
|
-
flex-direction: row;
|
|
25
|
-
height: 160px;
|
|
26
|
-
width: 100%;
|
|
27
|
-
padding-top: ${getStatusBarHeight() + 30}px;
|
|
28
|
-
background-color: ${({ theme }: any) => theme.colors.secondary};
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
export const HeaderContainer = styled.View.attrs({})`
|
|
32
|
-
flex-direction: row;
|
|
33
|
-
width: 100%;
|
|
34
|
-
height: 100%;
|
|
35
|
-
justify-content: center;
|
|
36
|
-
align-items: center;
|
|
37
|
-
padding-left: 16px;
|
|
38
|
-
padding-right: 16px;
|
|
39
|
-
`;
|
|
40
|
-
|
|
41
|
-
export const HeadingContainer = styled.View`
|
|
42
|
-
padding: 20px 16px;
|
|
43
|
-
margin-top: -60px;
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
export const CardsContainer = styled.View``;
|
|
47
|
-
|
|
48
|
-
const { width } = Dimensions.get('window');
|
|
49
|
-
const CARD_WIDTH = width - 60;
|
|
50
|
-
const CARD_WIDTH_SPACING = CARD_WIDTH + theme.spacing.l;
|
|
51
|
-
export const CardsList = styled.FlatList.attrs({
|
|
52
|
-
horizontal: true,
|
|
53
|
-
decelerationRate: 'fast',
|
|
54
|
-
showsHorizontalScrollIndicator: false,
|
|
55
|
-
snapToInterval: CARD_WIDTH_SPACING,
|
|
56
|
-
})`
|
|
57
|
-
margin-top: 20px;
|
|
58
|
-
height: 250px;
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
|
-
export const HighlightsContainer = styled.View`
|
|
62
|
-
margin-top: ${RFValue(15)}px;
|
|
63
|
-
flex-direction: row;
|
|
64
|
-
justify-content: space-between;
|
|
65
|
-
flex-wrap: wrap;
|
|
66
|
-
`;
|
|
67
|
-
|
|
68
|
-
export const TitleSection = styled.View`
|
|
69
|
-
margin-top: 10px;
|
|
70
|
-
width: 100%;
|
|
71
|
-
justify-content: center;
|
|
72
|
-
padding: 10px 0;
|
|
73
|
-
`;
|
|
74
|
-
|
|
75
|
-
export const BannerImageContainer = styled.TouchableOpacity`
|
|
76
|
-
height: ${RFValue(200)}px;
|
|
77
|
-
border-radius: ${RFValue(10)}px;
|
|
78
|
-
background-color: ${({ theme }: any) => theme.colors.secondary};
|
|
79
|
-
`;
|
|
80
|
-
|
|
81
|
-
export const BannerImage = styled.Image`
|
|
82
|
-
height: 100%;
|
|
83
|
-
width: 100%;
|
|
84
|
-
border-radius: ${RFValue(5)}px;
|
|
85
|
-
`;
|