├── .husky └── pre-commit ├── .yo-resolve ├── generators ├── react-native │ ├── templates │ │ ├── app │ │ │ ├── shared │ │ │ │ ├── fixtures │ │ │ │ │ ├── get-user.json.ejs │ │ │ │ │ ├── update-user.json.ejs │ │ │ │ │ ├── get-users.json.ejs │ │ │ │ │ ├── entity-get-all.json.ejs │ │ │ │ │ ├── get-oauth-info.json.ejs │ │ │ │ │ ├── get-_entityFile_.json.ejs │ │ │ │ │ ├── update-_entityFile_.json.ejs │ │ │ │ │ ├── README.md.ejs │ │ │ │ │ ├── get-account.json.ejs │ │ │ │ │ └── login.json.ejs │ │ │ │ ├── util │ │ │ │ │ ├── snake-to-camel-case.js.ejs │ │ │ │ │ ├── use-did-update-effect.js.ejs │ │ │ │ │ ├── date-transforms.js.ejs │ │ │ │ │ ├── immutable-persistence-transform.js.ejs │ │ │ │ │ ├── pagination-utils.js.ejs │ │ │ │ │ └── url-utils.js.ejs │ │ │ │ ├── images │ │ │ │ │ ├── jhipster_family_member_0_head.png │ │ │ │ │ ├── jhipster_family_member_1_head.png │ │ │ │ │ ├── jhipster_family_member_2_head.png │ │ │ │ │ ├── jhipster_family_member_3_head.png │ │ │ │ │ ├── jhipster_family_member_0_head@2x.png │ │ │ │ │ ├── jhipster_family_member_0_head@3x.png │ │ │ │ │ ├── jhipster_family_member_1_head@2x.png │ │ │ │ │ ├── jhipster_family_member_1_head@3x.png │ │ │ │ │ ├── jhipster_family_member_2_head@2x.png │ │ │ │ │ ├── jhipster_family_member_2_head@3x.png │ │ │ │ │ ├── jhipster_family_member_3_head@2x.png │ │ │ │ │ ├── jhipster_family_member_3_head@3x.png │ │ │ │ │ └── toggle-drawer-icon │ │ │ │ │ │ ├── toggle-drawer-icon.png │ │ │ │ │ │ ├── toggle-drawer-icon@1x.ios.png │ │ │ │ │ │ ├── toggle-drawer-icon@2x.ios.png │ │ │ │ │ │ ├── toggle-drawer-icon@3x.ios.png │ │ │ │ │ │ ├── toggle-drawer-icon@4x.ios.png │ │ │ │ │ │ ├── toggle-drawer-icon@1.5x.ios.png │ │ │ │ │ │ ├── toggle-drawer-icon@1.5x.android.png │ │ │ │ │ │ ├── toggle-drawer-icon@1x.android.png │ │ │ │ │ │ ├── toggle-drawer-icon@2x.android.png │ │ │ │ │ │ ├── toggle-drawer-icon@3x.android.png │ │ │ │ │ │ └── toggle-drawer-icon@4x.android.png │ │ │ │ ├── themes │ │ │ │ │ ├── images.js.ejs │ │ │ │ │ ├── colors.js.ejs │ │ │ │ │ ├── index.js.ejs │ │ │ │ │ ├── metrics.js.ejs │ │ │ │ │ └── fonts.js.ejs │ │ │ │ ├── reducers │ │ │ │ │ ├── startup.reducer.js.ejs │ │ │ │ │ ├── app-state.reducer.js.ejs │ │ │ │ │ ├── auth-info.reducer.js.ejs │ │ │ │ │ ├── create-store.js.ejs │ │ │ │ │ ├── index.js.ejs │ │ │ │ │ └── account.reducer.js.ejs │ │ │ │ ├── components │ │ │ │ │ ├── rounded-button │ │ │ │ │ │ ├── rounded-button.story.js.ejs │ │ │ │ │ │ ├── rounded-button.styles.js.ejs │ │ │ │ │ │ └── rounded-button.js.ejs │ │ │ │ │ ├── form │ │ │ │ │ │ ├── jhi-form-button.js.ejs │ │ │ │ │ │ ├── inputs │ │ │ │ │ │ │ ├── jhi-switch-input.js.ejs │ │ │ │ │ │ │ ├── jhi-text-input.js.ejs │ │ │ │ │ │ │ ├── jhi-date-input.web.js.ejs │ │ │ │ │ │ │ └── jhi-date-input.js.ejs │ │ │ │ │ │ └── jhi-form.js.ejs │ │ │ │ │ ├── alert-message │ │ │ │ │ │ ├── alert-message.styles.js.ejs │ │ │ │ │ │ ├── alert-message.js.ejs │ │ │ │ │ │ └── alert-message.story.js.ejs │ │ │ │ │ └── search-bar │ │ │ │ │ │ ├── search-bar.story.js.ejs │ │ │ │ │ │ ├── search-bar.styles.js.ejs │ │ │ │ │ │ └── search-bar.js.ejs │ │ │ │ ├── sagas │ │ │ │ │ ├── startup.saga.js.ejs │ │ │ │ │ ├── auth-info.saga.js.ejs │ │ │ │ │ ├── call-api.saga.js.ejs │ │ │ │ │ ├── account.sagas.js.ejs │ │ │ │ │ └── user.sagas.js.ejs │ │ │ │ ├── websockets │ │ │ │ │ └── websocket.sagas.js.ejs │ │ │ │ └── services │ │ │ │ │ └── rehydration.service.js.ejs │ │ │ ├── modules │ │ │ │ ├── login │ │ │ │ │ ├── login-screen.styles.js.ejs │ │ │ │ │ ├── login.reducer.js.ejs │ │ │ │ │ └── login-screen.oauth2.js.ejs │ │ │ │ ├── account │ │ │ │ │ ├── register │ │ │ │ │ │ ├── register-screen.styles.js.ejs │ │ │ │ │ │ ├── register.sagas.js.ejs │ │ │ │ │ │ └── register.reducer.js.ejs │ │ │ │ │ ├── settings │ │ │ │ │ │ └── settings-screen.styles.js.ejs │ │ │ │ │ ├── password │ │ │ │ │ │ ├── change-password-screen.styles.js.ejs │ │ │ │ │ │ ├── change-password.sagas.js.ejs │ │ │ │ │ │ └── change-password.reducer.js.ejs │ │ │ │ │ └── password-reset │ │ │ │ │ │ ├── forgot-password-screen.styles.js.ejs │ │ │ │ │ │ ├── forgot-password.sagas.js.ejs │ │ │ │ │ │ └── forgot-password.reducer.js.ejs │ │ │ │ ├── entities │ │ │ │ │ ├── _entityFolder_ │ │ │ │ │ │ └── _entityFile_-styles.js.ejs │ │ │ │ │ ├── entities-screen.js.ejs │ │ │ │ │ └── entities-screen.styles.js.ejs │ │ │ │ ├── chat │ │ │ │ │ ├── chat-screen.styles.js.ejs │ │ │ │ │ └── chat.reducer.js.ejs │ │ │ │ └── home │ │ │ │ │ └── home-screen.styles.js.ejs │ │ │ ├── navigation │ │ │ │ ├── oauth-redirect-screen.tsx.ejs │ │ │ │ ├── not-found-screen.tsx.ejs │ │ │ │ ├── drawer │ │ │ │ │ ├── drawer-content.js.ejs │ │ │ │ │ └── drawer-button.js.ejs │ │ │ │ ├── nav-ref.js.ejs │ │ │ │ ├── entity-stack.js.ejs │ │ │ │ └── modal-screen.js.ejs │ │ │ └── config │ │ │ │ ├── redux-persist.js.ejs │ │ │ │ └── app-config.js.ejs │ │ ├── .gitattributes.jhi.react-native.ejs │ │ ├── assets │ │ │ ├── icon.png │ │ │ ├── splash.png │ │ │ ├── favicon.png │ │ │ └── adaptive-icon.png │ │ ├── babel.config.js.ejs │ │ ├── .prettierignore.jhi.react-native.ejs │ │ ├── .storybook │ │ │ ├── main.ts.ejs │ │ │ ├── preview.tsx.ejs │ │ │ ├── index.ts.ejs │ │ │ └── storybook.requires.ts.ejs │ │ ├── e2e │ │ │ ├── home-screen.spec.js.ejs │ │ │ ├── jest.config.cjs.ejs │ │ │ ├── scripts │ │ │ │ ├── download-expo.sh.ejs │ │ │ │ └── setup.sh.ejs │ │ │ ├── websockets │ │ │ │ └── chat-screen.spec.js.ejs │ │ │ └── account │ │ │ │ ├── login-screen.spec.js.ejs │ │ │ │ ├── settings-screen.spec.js.ejs │ │ │ │ └── change-password-screen.spec.js.ejs │ │ ├── test │ │ │ ├── spec │ │ │ │ ├── shared │ │ │ │ │ ├── reducers │ │ │ │ │ │ ├── app-state.reducer.spec.js.ejs │ │ │ │ │ │ └── account.reducer.spec.js.ejs │ │ │ │ │ ├── websockets │ │ │ │ │ │ ├── websocket-service.spec.js.ejs │ │ │ │ │ │ └── websocket.sagas.spec.js.ejs │ │ │ │ │ ├── services │ │ │ │ │ │ └── fixture-api.spec.js.ejs │ │ │ │ │ ├── sagas │ │ │ │ │ │ ├── startup.saga.spec.js.ejs │ │ │ │ │ │ ├── call-api.saga.spec.js.ejs │ │ │ │ │ │ └── account.sagas.spec.js.ejs │ │ │ │ │ ├── navigation │ │ │ │ │ │ └── drawer │ │ │ │ │ │ │ └── drawer-button.spec.js.ejs │ │ │ │ │ └── components │ │ │ │ │ │ ├── search-bar │ │ │ │ │ │ └── search-bar.spec.js.ejs │ │ │ │ │ │ ├── alert-message │ │ │ │ │ │ └── alert-message.spec.js.ejs │ │ │ │ │ │ └── rounded-button │ │ │ │ │ │ └── rounded-button.spec.js.ejs │ │ │ │ └── modules │ │ │ │ │ ├── chat │ │ │ │ │ └── chat.reducer.spec.js.ejs │ │ │ │ │ ├── account │ │ │ │ │ ├── register │ │ │ │ │ │ ├── register.reducer.spec.js.ejs │ │ │ │ │ │ └── register.sagas.spec.js.ejs │ │ │ │ │ ├── password-reset │ │ │ │ │ │ ├── forgot-password.reducer.spec.js.ejs │ │ │ │ │ │ └── forgot-password.sagas.spec.js.ejs │ │ │ │ │ └── password │ │ │ │ │ │ ├── change-password.reducer.spec.js.ejs │ │ │ │ │ │ └── change-password.sagas.spec.js.ejs │ │ │ │ │ └── login │ │ │ │ │ └── login.reducer.spec.js.ejs │ │ │ └── setup.js.ejs │ │ ├── .gitignore.jhi.react-native.ejs │ │ ├── patches │ │ │ ├── react-native-sectioned-multi-select+0.8.1.patch.ejs │ │ │ └── react-native-keyboard-aware-scroll-view+0.9.4.patch.ejs │ │ ├── app.json.ejs │ │ ├── App.js.ejs │ │ ├── metro.config.js.ejs │ │ ├── .detoxrc.cjs.ejs │ │ ├── README.md.ejs │ │ └── package.json │ ├── index.mjs │ ├── support │ │ ├── append-files.js │ │ ├── patch-babel.js │ │ └── index.js │ ├── command.mjs │ ├── resources │ │ └── expo │ │ │ └── package.json │ └── entity-files.mjs ├── heroku │ └── templates │ │ └── Procfile.ejs ├── app │ ├── index.mjs │ ├── command.mjs │ ├── generator.spec.mjs │ └── generator.mjs ├── spring-boot │ ├── index.mjs │ ├── command.mjs │ ├── templates │ │ └── src │ │ │ └── main │ │ │ └── resources │ │ │ └── config │ │ │ └── application-e2e-cors.yml │ ├── generator.spec.mjs │ └── generator.mjs └── constants.mjs ├── test ├── scripts │ ├── stop-android-emulator.sh │ ├── install-heroku-cli.sh │ ├── run-react-native-tests.sh │ ├── install-node-dependencies.sh │ ├── install-detox.sh │ ├── git-config.sh │ ├── display-tools.sh │ ├── package-jhipster-backend.sh │ ├── generate-jhipster-backend.sh │ ├── rename-detox-screenshots.sh │ ├── start-android-emulator.sh │ ├── generate-react-native-app.sh │ └── copy-jdl-file.sh └── jdl │ ├── app.jdl │ ├── entities-flickr2.jdl │ ├── entities-21points.jdl │ └── entities.jdl ├── .prettierignore ├── docs ├── images │ ├── jh-rn-logo.png │ ├── jh-rn-logo@0.5x.png │ ├── jh-rn-logo@2x.png │ └── jh-rn-logo@3x.png ├── generators.md ├── websockets.md ├── cli-flags.md ├── detox.md ├── storybook.md └── distributing-and-updating.md ├── .blueprint ├── generate-sample │ ├── index.mjs │ └── templates │ │ ├── ios.js │ │ └── samples │ │ ├── flickr2-jwt.jdl │ │ ├── 21points-jwt.jdl │ │ ├── app-jwt.jdl │ │ ├── app-oauth2.jdl │ │ └── app-websocket.jdl ├── github-build-matrix │ ├── index.mjs │ ├── command.mjs │ ├── generator.spec.mjs │ └── generator.mjs └── cli │ └── commands.mjs ├── .prettierrc ├── NOTICE ├── .prettierrc.yml ├── cli ├── commands.cjs ├── cli-customizations.cjs ├── cli.cjs └── print-jhipster-logo.js ├── vitest.test-setup.ts ├── vitest.config.ts ├── .github ├── workflows │ ├── publish.yml │ ├── merge.yml │ ├── copyright-update.yml │ └── generator.yml ├── ISSUE_TEMPLATE │ └── bug_report.md └── dependabot.yml ├── .editorconfig ├── eslint.config.js ├── .yo-rc.json ├── tsconfig.json └── CONTRIBUTING.md /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | ./node_modules/.bin/lint-staged 2 | -------------------------------------------------------------------------------- /.yo-resolve: -------------------------------------------------------------------------------- 1 | .github/workflows/** skip 2 | README.md skip 3 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/get-user.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 1 3 | } 4 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/update-user.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 1 3 | } 4 | -------------------------------------------------------------------------------- /generators/heroku/templates/Procfile.ejs: -------------------------------------------------------------------------------- 1 | web: npx http-server dist --brotli --proxy http://localhost:$PORT? 2 | -------------------------------------------------------------------------------- /test/scripts/stop-android-emulator.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | adb -s emulator-5554 emu kill 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .git 4 | 5 | # blueprint rules: 6 | generators/**/templates/**/ 7 | -------------------------------------------------------------------------------- /docs/images/jh-rn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/docs/images/jh-rn-logo.png -------------------------------------------------------------------------------- /generators/app/index.mjs: -------------------------------------------------------------------------------- 1 | export { default } from './generator.mjs'; 2 | export { default as command } from './command.mjs'; 3 | -------------------------------------------------------------------------------- /docs/images/jh-rn-logo@0.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/docs/images/jh-rn-logo@0.5x.png -------------------------------------------------------------------------------- /docs/images/jh-rn-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/docs/images/jh-rn-logo@2x.png -------------------------------------------------------------------------------- /docs/images/jh-rn-logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/docs/images/jh-rn-logo@3x.png -------------------------------------------------------------------------------- /generators/react-native/index.mjs: -------------------------------------------------------------------------------- 1 | export { default } from './generator.mjs'; 2 | export { default as command } from './command.mjs'; 3 | -------------------------------------------------------------------------------- /generators/spring-boot/index.mjs: -------------------------------------------------------------------------------- 1 | export { default } from './generator.mjs'; 2 | export { default as command } from './command.mjs'; 3 | -------------------------------------------------------------------------------- /.blueprint/generate-sample/index.mjs: -------------------------------------------------------------------------------- 1 | export { default } from './generator.mjs'; 2 | export { default as command } from './command.mjs'; 3 | -------------------------------------------------------------------------------- /.blueprint/github-build-matrix/index.mjs: -------------------------------------------------------------------------------- 1 | export { default } from './generator.mjs'; 2 | export { default as command } from './command.mjs'; 3 | -------------------------------------------------------------------------------- /test/scripts/install-heroku-cli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | npm install -g heroku 5 | 6 | heroku whoami || true 7 | -------------------------------------------------------------------------------- /test/scripts/run-react-native-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | cd ../client 5 | 6 | npm run lint 7 | 8 | npm run test -- -u 9 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 140, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "useTabs": false, 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /generators/spring-boot/command.mjs: -------------------------------------------------------------------------------- 1 | import { asCommand } from 'generator-jhipster'; 2 | 3 | export default asCommand({ 4 | configs: {}, 5 | }); 6 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/get-users.json.ejs: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1 4 | }, 5 | { 6 | "id" : 2 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/entity-get-all.json.ejs: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1 4 | }, 5 | { 6 | "id" : 2 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /test/scripts/install-node-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | # install JHipster 5 | npm i -g generator-jhipster@$JHIPSTER_VERSION 6 | -------------------------------------------------------------------------------- /generators/react-native/templates/.gitattributes.jhi.react-native.ejs: -------------------------------------------------------------------------------- 1 | <&_ if (!fragment.section) { -&> 2 | ## .PBXPROJ FILES 3 | *.pbxproj binary 4 | <&_ } -&> 5 | -------------------------------------------------------------------------------- /generators/react-native/templates/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/assets/icon.png -------------------------------------------------------------------------------- /generators/react-native/templates/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/assets/splash.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/get-oauth-info.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "issuer": "http://localhost:9080/auth/realms/jhipster", 3 | "clientId": "web_app" 4 | } 5 | -------------------------------------------------------------------------------- /generators/react-native/templates/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/assets/favicon.png -------------------------------------------------------------------------------- /test/scripts/install-detox.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | if [ "$PLATFORM" = "ios" ]; then 5 | brew tap wix/brew 6 | brew install applesimutils 7 | fi 8 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | JHipster 2 | Copyright 2017-2025 the original author or authors from the JHipster project. 3 | 4 | For more information on the JHipster project, see https://www.jhipster.tech/ 5 | -------------------------------------------------------------------------------- /generators/react-native/templates/babel.config.js.ejs: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | printWidth: 140 2 | singleQuote: true 3 | tabWidth: 2 4 | useTabs: false 5 | arrowParens: avoid 6 | bracketSameLine: false 7 | plugins: 8 | - prettier-plugin-packagejson 9 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/util/snake-to-camel-case.js.ejs: -------------------------------------------------------------------------------- 1 | export default (word) => { 2 | return word.replace(/(-\w)/g, function (m) { return m[1].toUpperCase() }) 3 | } 4 | -------------------------------------------------------------------------------- /generators/react-native/templates/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/assets/adaptive-icon.png -------------------------------------------------------------------------------- /test/jdl/app.jdl: -------------------------------------------------------------------------------- 1 | application { 2 | config { 3 | authenticationType jwt 4 | websocket false 5 | skipClient true 6 | devDatabaseType h2Disk 7 | } 8 | entities * 9 | } 10 | -------------------------------------------------------------------------------- /test/scripts/git-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | git config --global user.name "JHipster React Native Github Pipelines" 4 | git config --global user.email "jhipster-react-native@localhost" 5 | -------------------------------------------------------------------------------- /cli/commands.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'react-native': { 3 | description: 'Run react-native sub-generator (react-native blueprint)', 4 | blueprint: 'generator-jhipster-react-native', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /generators/react-native/templates/.prettierignore.jhi.react-native.ejs: -------------------------------------------------------------------------------- 1 | <&_ if (!fragment.section) { -&> 2 | android 3 | ios 4 | .expo 5 | web-build 6 | dist 7 | .jhipster 8 | package-lock.json 9 | yarn.lock 10 | <&_ } -&> 11 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_0_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_0_head.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_1_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_1_head.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_2_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_2_head.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_3_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_3_head.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_0_head@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_0_head@2x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_0_head@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_0_head@3x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_1_head@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_1_head@2x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_1_head@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_1_head@3x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_2_head@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_2_head@2x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_2_head@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_2_head@3x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_3_head@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_3_head@2x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/jhipster_family_member_3_head@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/jhipster_family_member_3_head@3x.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/login/login-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import { ApplicationStyles } from '../../shared/themes'; 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | }); 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1x.ios.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@2x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@2x.ios.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@3x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@3x.ios.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@4x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@4x.ios.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1.5x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1.5x.ios.png -------------------------------------------------------------------------------- /test/scripts/display-tools.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | 4 | pwd 5 | 6 | git version 7 | java -version 8 | node -v 9 | npm -v 10 | 11 | if [ "$PLATFORM" = "ios" ]; then 12 | applesimutils --list 13 | else 14 | echo $ANDROID_HOME 15 | fi 16 | 17 | env 18 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1.5x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1.5x.android.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@1x.android.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@2x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@2x.android.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@3x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@3x.android.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@4x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhipster/generator-jhipster-react-native/HEAD/generators/react-native/templates/app/shared/images/toggle-drawer-icon/toggle-drawer-icon@4x.android.png -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/account/register/register-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { ApplicationStyles } from '../../../shared/themes' 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | }) 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/account/settings/settings-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { ApplicationStyles } from '../../../shared/themes' 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | }) 8 | -------------------------------------------------------------------------------- /vitest.test-setup.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url'; 2 | import { defineDefaults } from 'generator-jhipster/testing'; 3 | 4 | defineDefaults({ 5 | blueprint: 'generator-jhipster-react-native', 6 | blueprintPackagePath: fileURLToPath(new URL('./', import.meta.url)), 7 | }); 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/themes/images.js.ejs: -------------------------------------------------------------------------------- 1 | // leave off @2x/@3x 2 | const images = { 3 | logoJhipster: require('../images/logo-jhipster.png'), 4 | toggleDrawerIcon: require('../images/toggle-drawer-icon/toggle-drawer-icon.png'), 5 | } 6 | 7 | export default images 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/account/password/change-password-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { ApplicationStyles } from '../../../shared/themes' 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | }) 8 | -------------------------------------------------------------------------------- /generators/app/command.mjs: -------------------------------------------------------------------------------- 1 | import { asCommand } from 'generator-jhipster'; 2 | 3 | export default asCommand({ 4 | options: { 5 | reactNativeDir: { 6 | desc: 'Directory of JHipster application', 7 | type: String, 8 | scope: 'blueprint', 9 | }, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /generators/constants.mjs: -------------------------------------------------------------------------------- 1 | export const REACT_NATIVE_NAMESPACE = 'jhipster-react-native'; 2 | export const DEFAULT_REACT_NATIVE_PATH = '../client'; 3 | export const DEFAULT_BACKEND_PATH = '../backend'; 4 | export const DEFAULT_REACT_NATIVE_APP_NAME = 'RnApp'; 5 | export const DEFAULT_ENABLE_DETOX = true; 6 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/account/password-reset/forgot-password-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { ApplicationStyles } from '../../../shared/themes' 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | }) 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/themes/colors.js.ejs: -------------------------------------------------------------------------------- 1 | const colors = { 2 | jhipsterBlue: '#3E8ACC', 3 | transparent: 'rgba(0,0,0,0)', 4 | error: 'rgba(200, 0, 0, 0.8)', 5 | white: 'white', 6 | black: 'black', 7 | text: '#E0D7E5', 8 | }; 9 | 10 | export default colors; 11 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/themes/index.js.ejs: -------------------------------------------------------------------------------- 1 | import Colors from './colors' 2 | import Fonts from './fonts' 3 | import Metrics from './metrics' 4 | import Images from './images' 5 | import ApplicationStyles from './application.styles' 6 | 7 | export { Colors, Fonts, Images, Metrics, ApplicationStyles } 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/.storybook/main.ts.ejs: -------------------------------------------------------------------------------- 1 | import { StorybookConfig } from '@storybook/react-native'; 2 | 3 | const main: StorybookConfig = { 4 | stories: ['../app/**/*.stor?(y|ies).?(ts|tsx|js|jsx)'], 5 | addons: ['@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-actions'], 6 | }; 7 | 8 | export default main; 9 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/reducers/startup.reducer.js.ejs: -------------------------------------------------------------------------------- 1 | import { createActions } from 'reduxsauce' 2 | 3 | /* ------------- Types and Action Creators ------------- */ 4 | 5 | const { Types, Creators } = createActions({ 6 | startup: null 7 | }) 8 | 9 | export const StartupTypes = Types 10 | export default Creators 11 | -------------------------------------------------------------------------------- /cli/cli-customizations.cjs: -------------------------------------------------------------------------------- 1 | // This file will not be overwritten by generate-blueprint 2 | module.exports = { 3 | defaultCommand: 'react-native', 4 | printBlueprintLogo: undefined, 5 | printLogo: async () => { 6 | const { printJHipsterLogo } = await import('./print-jhipster-logo.js'); 7 | await printJHipsterLogo(); 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /generators/react-native/support/append-files.js: -------------------------------------------------------------------------------- 1 | function appendFiles() { 2 | this.editFile( 3 | '.gitignore', 4 | content => `${content} 5 | # Misc 6 | .env 7 | ios/Index/DataStore 8 | ios/Carthage 9 | ios/Pods 10 | /dist 11 | .artifacts 12 | e2e/Exponent.app 13 | .yo-repository 14 | `, 15 | ); 16 | } 17 | 18 | export { appendFiles }; 19 | -------------------------------------------------------------------------------- /generators/react-native/support/patch-babel.js: -------------------------------------------------------------------------------- 1 | function patchBabel() { 2 | this.patchInFile('babel.config.js', { 3 | after: 'presets', 4 | insert: "plugins: ['@babel/plugin-transform-export-namespace-from', 'react-native-reanimated/plugin'],", 5 | ignoreIfContains: 'react-native-reanimated', 6 | }); 7 | } 8 | 9 | export { patchBabel }; 10 | -------------------------------------------------------------------------------- /generators/react-native/templates/.storybook/preview.tsx.ejs: -------------------------------------------------------------------------------- 1 | import type { Preview } from '@storybook/react'; 2 | 3 | const preview: Preview = { 4 | parameters: { 5 | controls: { 6 | matchers: { 7 | color: /(background|color)$/i, 8 | date: /Date$/, 9 | }, 10 | }, 11 | }, 12 | }; 13 | 14 | export default preview; 15 | -------------------------------------------------------------------------------- /generators/react-native/templates/e2e/home-screen.spec.js.ejs: -------------------------------------------------------------------------------- 1 | const { reloadApp } = require('./utils') 2 | 3 | describe('Home Screen Tests', () => { 4 | beforeEach(async () => { 5 | await reloadApp() 6 | }) 7 | 8 | it('should have welcome screen', async () => { 9 | await expect(element(by.id('homeScreen'))).toBeVisible() 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defaultExclude, defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | pool: 'forks', 6 | hookTimeout: 20000, 7 | exclude: [...defaultExclude.filter(val => val !== '**/cypress/**'), '**/templates/**', '**/resources/**'], 8 | setupFiles: ['./vitest.test-setup.ts'], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/get-_entityFile_.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 1, 3 | <%_ fields.filter(field => !field.id).forEach(function (field) { _%> 4 | <%_ if (field.fieldType === 'LocalDate' || field.fieldType === 'ZonedDateTime' || field.fieldType === 'Instant') { _%> 5 | <%= field.fieldName %>: null, 6 | <%_ } _%> 7 | <%_ }) _%> 8 | } 9 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/update-_entityFile_.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 1, 3 | <%_ fields.filter(field => !field.id).forEach(function (field) { _%> 4 | <%_ if (field.fieldType === 'LocalDate' || field.fieldType === 'ZonedDateTime' || field.fieldType === 'Instant') { _%> 5 | <%= field.fieldName %>: null, 6 | <%_ } _%> 7 | <%_ }) _%> 8 | } 9 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/shared/reducers/app-state.reducer.spec.js.ejs: -------------------------------------------------------------------------------- 1 | import Actions, { reducer, INITIAL_STATE } from '../../../../app/shared/reducers/app-state.reducer' 2 | 3 | test('rehydration complete', () => { 4 | const state = reducer(INITIAL_STATE, Actions.setRehydrationComplete()) 5 | 6 | expect(state.rehydrationComplete).toBe(true) 7 | }) 8 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/entities/_entityFolder_/_entityFile_-styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import { ApplicationStyles } from '../../../shared/themes'; 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | ...ApplicationStyles.entity, 8 | ...ApplicationStyles.entityDeleteModal, 9 | }); 10 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/README.md.ejs: -------------------------------------------------------------------------------- 1 | ### Fixtures folder 2 | 3 | All important API responses are housed here. 4 | 5 | These API responses can be used for several reasons. For example: 6 | 7 | - To bypass logins when building any screen of the application 8 | - To quickly test API parsing in unit tests 9 | - To separate Network from Data concerns while coding 10 | -------------------------------------------------------------------------------- /test/scripts/package-jhipster-backend.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | # switch to the directory the backend was generated in 5 | cd ../backend 6 | ls -al 7 | 8 | # show files modified by generator-jhipster-react-native 9 | git status 10 | 11 | # package the app into a WAR 12 | # this is currently unused, todo: test with backend in prod mode 13 | # ./mvnw clean package -Pprod -DskipTests -ntp 14 | -------------------------------------------------------------------------------- /generators/spring-boot/templates/src/main/resources/config/application-e2e-cors.yml: -------------------------------------------------------------------------------- 1 | jhipster: 2 | cors: 3 | allowed-origins: "http://localhost:8081,http://localhost" 4 | allowed-methods: "*" 5 | allowed-headers: "*" 6 | exposed-headers: "Authorization,Link,X-Total-Count,X-${jhipster.clientApp.name}-alert,X-${jhipster.clientApp.name}-error,X-${jhipster.clientApp.name}-params" 7 | allow-credentials: true 8 | max-age: 1800 9 | -------------------------------------------------------------------------------- /test/scripts/generate-jhipster-backend.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | # switch to a directory to generate the backend 5 | rm -rf ../backend && mkdir ../backend && cd ../backend 6 | 7 | # generate the app 8 | jhipster jdl ../${JHI_REACT_NATIVE_APP_NAME}.jdl --force --skip-checks --skip-commit-hook --no-insight --skip-install 9 | 10 | # list files 11 | ls -al 12 | 13 | # display jhipster info 14 | jhipster info 15 | -------------------------------------------------------------------------------- /generators/react-native/support/index.js: -------------------------------------------------------------------------------- 1 | export { appendFiles } from './append-files.js'; 2 | export { patchBabel } from './patch-babel.js'; 3 | export { patchNavigationForEntity } from './patch-navigation.js'; 4 | export { patchInFile } from './patch-in-file.js'; 5 | export { patchEntityApi } from './patch-entity-api.js'; 6 | export { getEntityFormField, getRelationshipFormField, getFieldValidateType, getEntityFormFieldType } from './entity-helpers.js'; 7 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/util/use-did-update-effect.js.ejs: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // useEffect, but it skips running on the first render 3 | export function useDidUpdateEffect(fn, inputs) { 4 | const didMountRef = React.useRef(false); 5 | React.useEffect(() => { 6 | if (didMountRef.current) fn(); 7 | else didMountRef.current = true; 8 | // eslint-disable-next-line react-hooks/exhaustive-deps 9 | }, inputs); 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v6 12 | - uses: actions/setup-node@v6 13 | with: 14 | node-version: 20 15 | registry-url: https://registry.npmjs.org/ 16 | - run: npm ci 17 | - run: npm publish --access public 18 | env: 19 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # We recommend you to keep these unchanged 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | # Change these settings to your own preference 16 | indent_style = space 17 | indent_size = 2 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/fixtures/get-account.json.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 3, 3 | "login" : "admin", 4 | "firstName" : "Administrator", 5 | "lastName" : "Administrator", 6 | "email" : "admin@localhost", 7 | "imageUrl" : "", 8 | "activated" : true, 9 | "langKey" : "en", 10 | "createdBy" : "system", 11 | "createdDate" : "2017-09-07T18:40:18.677Z", 12 | "lastModifiedBy" : "system", 13 | "lastModifiedDate" : null, 14 | "authorities" : [ "ROLE_USER", "ROLE_ADMIN" ] 15 | } 16 | -------------------------------------------------------------------------------- /generators/react-native/templates/e2e/jest.config.cjs.ejs: -------------------------------------------------------------------------------- 1 | /** @type {import('@jest/types').Config.InitialOptions} */ 2 | module.exports = { 3 | rootDir: '..', 4 | testMatch: ['/e2e/**/*.spec.js'], 5 | testTimeout: 120000, 6 | maxWorkers: 1, 7 | globalSetup: 'detox/runners/jest/globalSetup', 8 | globalTeardown: 'detox/runners/jest/globalTeardown', 9 | reporters: ['detox/runners/jest/reporter'], 10 | testEnvironment: 'detox/runners/jest/testEnvironment', 11 | verbose: true, 12 | }; 13 | -------------------------------------------------------------------------------- /generators/react-native/templates/.storybook/index.ts.ejs: -------------------------------------------------------------------------------- 1 | import AsyncStorage from '@react-native-async-storage/async-storage'; 2 | import { view } from './storybook.requires'; 3 | 4 | import AppConfig from '../app/config/app-config'; 5 | import { View } from 'react-native'; 6 | 7 | const StorybookUIRoot = AppConfig.debugMode ? view.getStorybookUI({ 8 | storage: { 9 | getItem: AsyncStorage.getItem, 10 | setItem: AsyncStorage.setItem, 11 | }, 12 | }) : View; 13 | 14 | export default StorybookUIRoot; 15 | -------------------------------------------------------------------------------- /generators/react-native/templates/.gitignore.jhi.react-native.ejs: -------------------------------------------------------------------------------- 1 | <&_ if (!fragment.section) { -&> 2 | ###################### 3 | # React Native 4 | ###################### 5 | 6 | # Expo 7 | .expo/ 8 | web-build/ 9 | 10 | # Native 11 | *.orig.* 12 | *.jks 13 | *.p8 14 | *.p12 15 | *.key 16 | *.mobileprovision 17 | 18 | # Metro 19 | .metro-health-check* 20 | 21 | # debug 22 | npm-debug.* 23 | yarn-debug.* 24 | yarn-error.* 25 | 26 | # macOS 27 | *.pem 28 | 29 | # local env files 30 | .env*.local 31 | 32 | # typescript 33 | *.tsbuildinfo 34 | <&_ } -&> 35 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/shared/websockets/websocket-service.spec.js.ejs: -------------------------------------------------------------------------------- 1 | import { call } from 'redux-saga/effects' 2 | 3 | import WebsocketService from '../../../../app/shared/websockets/websocket.service' 4 | 5 | const stepper = (fn) => (mock) => fn.next(mock).value 6 | 7 | test('websocket path', () => { 8 | const step = stepper(WebsocketService.websocketSagas()) 9 | // Call the redux with a successful chat receipt 10 | const initialCall = call(WebsocketService.initWebsocket) 11 | expect(step()).toEqual(initialCall) 12 | }) 13 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import globals from 'globals'; 2 | import prettier from 'eslint-plugin-prettier/recommended'; 3 | import jhipster from 'generator-jhipster/eslint'; 4 | // jhipster-needle-eslint-add-import - JHipster will add additional import here 5 | 6 | export default [ 7 | { 8 | languageOptions: { 9 | globals: { 10 | ...globals.node, 11 | }, 12 | }, 13 | }, 14 | { ignores: ['coverage/**'] }, 15 | jhipster.recommended, 16 | // jhipster-needle-eslint-add-config - JHipster will add additional config here 17 | prettier, 18 | ]; 19 | -------------------------------------------------------------------------------- /test/scripts/rename-detox-screenshots.sh: -------------------------------------------------------------------------------- 1 | # workaround for recent detox changes that include < and > in the filename 2 | # this is refused by the github artifact uploader as an invalid filename 3 | cd ../client/.artifacts 4 | find . -type f -name '*.png' | while read FILE ; do 5 | newfile=$FILE 6 | newfile="$(echo ${newfile} |sed -e 's/\/_/')" ; 9 | newfile="$(echo ${newfile} |sed -e 's/\>/_/')" ; 10 | mv "${FILE}" "${newfile}" ; 11 | done 12 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/components/rounded-button/rounded-button.story.js.ejs: -------------------------------------------------------------------------------- 1 | import RoundedButton from './rounded-button'; 2 | 3 | const meta = { 4 | title: 'RoundedButton', 5 | component: RoundedButton, 6 | parameters: { 7 | componentSubtitle: 'A simple rounded button component', 8 | }, 9 | }; 10 | 11 | export default meta; 12 | 13 | export const Default = { 14 | args: { 15 | text: 'A simple rounded button', 16 | }, 17 | }; 18 | 19 | export const TextAsChildren = { 20 | args: { 21 | children: 'Hello from the children!', 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /.blueprint/github-build-matrix/command.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('generator-jhipster').JHipsterCommandDefinition} 3 | */ 4 | const command = { 5 | configs: { 6 | samplesFolder: { 7 | description: 'Samples folder', 8 | cli: { 9 | type: String, 10 | }, 11 | scope: 'generator', 12 | }, 13 | samplesGroup: { 14 | description: 'Samples Group', 15 | argument: { 16 | type: String, 17 | }, 18 | default: 'samples', 19 | scope: 'generator', 20 | }, 21 | }, 22 | options: {}, 23 | }; 24 | 25 | export default command; 26 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/themes/metrics.js.ejs: -------------------------------------------------------------------------------- 1 | // Used via Metrics.baseMargin 2 | const metrics = { 3 | marginHorizontal: 10, 4 | marginVertical: 10, 5 | section: 25, 6 | baseMargin: 10, 7 | doubleBaseMargin: 20, 8 | smallMargin: 5, 9 | doubleSection: 50, 10 | horizontalLineHeight: 1, 11 | buttonRadius: 4, 12 | icons: { 13 | tiny: 15, 14 | small: 20, 15 | medium: 30, 16 | large: 45, 17 | xl: 50 18 | }, 19 | images: { 20 | small: 20, 21 | medium: 40, 22 | large: 60, 23 | logo: 100 24 | } 25 | } 26 | 27 | export default metrics 28 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/shared/services/fixture-api.spec.js.ejs: -------------------------------------------------------------------------------- 1 | import R from 'ramda' 2 | 3 | import API from '../../../../app/shared/services/api' 4 | import FixtureAPI from '../../../../app/shared/services/fixture-api' 5 | 6 | test('All fixtures map to actual API', () => { 7 | const fixtureKeys = R.keys(FixtureAPI).sort() 8 | const apiKeys = R.keys(API.create()) 9 | const intersection = R.intersection(fixtureKeys, apiKeys).sort() 10 | 11 | // There is no difference between the intersection and all fixtures, meaning all fixtures match an API 12 | expect(R.equals(fixtureKeys, intersection)).toBe(true) 13 | }) 14 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/components/form/jhi-form-button.js.ejs: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useFormikContext } from 'formik'; 3 | import { ApplicationStyles } from '../../themes'; 4 | 5 | import { Text, TouchableOpacity } from 'react-native'; 6 | 7 | export default React.forwardRef(({ title, ...otherProps}, ref) => { 8 | const { handleSubmit } = useFormikContext(); 9 | 10 | return ( 11 | 12 | {title} 13 | 14 | ); 15 | }); 16 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/account/register/register.sagas.js.ejs: -------------------------------------------------------------------------------- 1 | import { call, put } from 'redux-saga/effects' 2 | 3 | import RegisterActions from './register.reducer' 4 | 5 | // attempts to register 6 | export function * register (api, { user }) { 7 | const response = yield call(api.register, { langKey: 'en', ...user }); 8 | // success? 9 | if (response.ok) { 10 | console.log('Register - OK') 11 | yield put(RegisterActions.registerSuccess()) 12 | } else { 13 | console.log('Register - FAIL') 14 | yield put(RegisterActions.registerFailure((response.data && response.data.title) || 'Registration failed')) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/modules/chat/chat.reducer.spec.js.ejs: -------------------------------------------------------------------------------- 1 | import Actions, { reducer, INITIAL_STATE } from '../../../../app/modules/chat/chat.reducer' 2 | 3 | test('success', () => { 4 | const chatList = [{ username: 'user', message: 'hi' }] 5 | const state = reducer(INITIAL_STATE, Actions.chatSuccess(chatList)) 6 | 7 | expect(state.chat).toEqual(chatList) 8 | }) 9 | 10 | test('reset', () => { 11 | const chatList = [{ username: 'user', message: 'hi' }] 12 | const chatState = reducer(INITIAL_STATE, Actions.chatSuccess(chatList)) 13 | const resetState = reducer(chatState, Actions.chatReset()) 14 | 15 | expect(resetState.chat).toEqual([]) 16 | }) 17 | -------------------------------------------------------------------------------- /test/scripts/start-android-emulator.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-31;default;x86_64' > /dev/null 5 | 6 | $ANDROID_HOME/platform-tools/adb devices 7 | 8 | echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n Nexus_6_API_31 -k 'system-images;android-31;default;x86_64' --force > /dev/null 9 | 10 | nohup $ANDROID_HOME/emulator/emulator -avd Nexus_6_API_31 -no-snapshot -memory 3072 > /dev/null 2>&1 & $ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82' 11 | 12 | echo "Emulator started" 13 | -------------------------------------------------------------------------------- /docs/generators.md: -------------------------------------------------------------------------------- 1 | ## Generators 2 | 3 | ### Entity 4 | 5 | ```sh 6 | jhipster --blueprints react-native entity 7 | ``` 8 | 9 | - Prompts for the path to the entity's config (`.jhipster` folder in your app) 10 | - Generates all files needed for fetching and displaying the entity 11 | - Includes the API endpoints, redux/saga config, and the user interface 12 | 13 | ### Import JDL 14 | 15 | ```sh 16 | jhipster --blueprints react-native jdl 17 | ``` 18 | 19 | - Import several entities at once using JDL 20 | - Runs the entity generator for each entity present in the JDL 21 | - Can also generate a full application with entities, if the JDL contains application config 22 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/components/rounded-button/rounded-button.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { Fonts, Colors, Metrics } from '../../themes' 4 | 5 | export default StyleSheet.create({ 6 | button: { 7 | height: 45, 8 | borderRadius: 5, 9 | marginHorizontal: Metrics.section, 10 | marginVertical: Metrics.baseMargin, 11 | backgroundColor: Colors.jhipsterBlue, 12 | justifyContent: 'center' 13 | }, 14 | buttonText: { 15 | color: Colors.white, 16 | textAlign: 'center', 17 | fontWeight: 'bold', 18 | fontSize: Fonts.size.medium, 19 | marginVertical: Metrics.baseMargin 20 | } 21 | }) 22 | -------------------------------------------------------------------------------- /.blueprint/generate-sample/templates/ios.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url'; 2 | import { getGithubSamplesGroup } from 'generator-jhipster/testing'; 3 | 4 | const { samples } = await getGithubSamplesGroup(fileURLToPath(new URL('./', import.meta.url)), 'samples'); 5 | 6 | export default Object.fromEntries( 7 | Object.entries(samples).map(([sample, spec]) => [ 8 | sample, 9 | { 10 | ...spec, 11 | 'docker-services': `${!sample.includes('oauth2')}`, 12 | ...(sample.includes('oauth2') 13 | ? { os: 'macos-13', 'default-environment': 'prod', 'skip-e2e': 'true' } 14 | : { os: 'macos-15', 'default-environment': 'dev' }), 15 | }, 16 | ]), 17 | ); 18 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/entities/entities-screen.js.ejs: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ScrollView, Text } from 'react-native'; 3 | // Styles 4 | import RoundedButton from '../../shared/components/rounded-button/rounded-button'; 5 | 6 | import styles from './entities-screen.styles'; 7 | 8 | export default function EntitiesScreen({ navigation }) { 9 | return ( 10 | 11 | JHipster Entities will appear below 12 | {/* jhipster-react-native-entity-screen-needle */} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/entities/entities-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { ApplicationStyles, Colors } from '../../shared/themes' 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | centerText: { 8 | textAlign: 'center', 9 | }, 10 | buttonText: { 11 | fontSize: 18, 12 | color: 'white', 13 | alignSelf: 'center' 14 | }, 15 | button: { 16 | height: 36, 17 | backgroundColor: Colors.jhipsterBlue, 18 | borderColor: Colors.jhipsterBlue, 19 | borderWidth: 1, 20 | borderRadius: 8, 21 | marginBottom: 10, 22 | alignSelf: 'stretch', 23 | justifyContent: 'center' 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/chat/chat-screen.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import { ApplicationStyles, Metrics, Colors } from '../../shared/themes'; 4 | 5 | export default StyleSheet.create({ 6 | ...ApplicationStyles.screen, 7 | row: { 8 | marginVertical: 1, 9 | justifyContent: 'center', 10 | }, 11 | boldLabel: { 12 | fontWeight: 'bold', 13 | alignSelf: 'center', 14 | textAlign: 'center', 15 | marginBottom: Metrics.smallMargin, 16 | }, 17 | messageInput: { 18 | flex: 1, 19 | padding: 10, 20 | backgroundColor: Colors.white, 21 | }, 22 | inputContainer: { 23 | flexDirection: 'row', 24 | paddingBottom: 20, 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/setup.js.ejs: -------------------------------------------------------------------------------- 1 | import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock'; 2 | 3 | // Mock your external modules here if needed 4 | jest 5 | .mock('@react-native-async-storage/async-storage', () => mockAsyncStorage) 6 | // related to https://github.com/rt2zz/redux-persist/issues/1243 7 | .mock("redux-persist/lib/createPersistoid", () => 8 | jest.fn(() => ({ 9 | update: jest.fn(), 10 | flush: jest.fn(), 11 | })) 12 | ) 13 | .mock('@storybook/react-native', () => { 14 | return { getStorybookUI: jest.fn(), configure: jest.fn() } 15 | }) 16 | // https://github.com/expo/expo/issues/23591#issuecomment-1652548059 17 | .mock('expo-font') 18 | .mock('expo-asset') 19 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/modules/account/password-reset/forgot-password.sagas.js.ejs: -------------------------------------------------------------------------------- 1 | import { call, put } from 'redux-saga/effects' 2 | 3 | import ForgotPasswordActions from './forgot-password.reducer' 4 | 5 | // attempts to request a password reset 6 | export function * forgotPassword (api, { email }) { 7 | const response = yield call(api.forgotPassword, email) 8 | // success? 9 | if (response.ok) { 10 | console.log('ForgotPasswordRequest - OK') 11 | yield put(ForgotPasswordActions.forgotPasswordSuccess(response.data)) 12 | } else { 13 | console.log('ForgotPassword - FAIL') 14 | yield put(ForgotPasswordActions.forgotPasswordFailure((response.data && response.data.title) || 'Something when wrong resetting your password')) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/components/alert-message/alert-message.styles.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | 3 | import { Colors, Metrics, Fonts } from '../../themes' 4 | 5 | export default StyleSheet.create({ 6 | container: { 7 | justifyContent: 'center', 8 | marginVertical: Metrics.section 9 | }, 10 | contentContainer: { 11 | alignSelf: 'center', 12 | alignItems: 'center' 13 | }, 14 | message: { 15 | marginTop: Metrics.baseMargin, 16 | marginHorizontal: Metrics.baseMargin, 17 | textAlign: 'center', 18 | fontFamily: Fonts.type.base, 19 | fontSize: Fonts.size.regular, 20 | fontWeight: 'bold', 21 | color: Colors.black 22 | }, 23 | icon: { 24 | color: Colors.black 25 | } 26 | }) 27 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/sagas/startup.saga.js.ejs: -------------------------------------------------------------------------------- 1 | import { put } from 'redux-saga/effects' 2 | import AppStateActions from '../reducers/app-state.reducer' 3 | import LoginActions from '../../modules/login/login.reducer' 4 | import AccountActions from '../reducers/account.reducer' 5 | <%_ if (authenticationType === 'oauth2') { _%> 6 | import AuthInfoActions from '../reducers/auth-info.reducer'; 7 | <%_ } _%> 8 | 9 | // process STARTUP actions 10 | export function * startup (_action) { 11 | yield put(LoginActions.loginLoad()) 12 | yield put(AccountActions.accountRequest()) 13 | yield put(AppStateActions.setRehydrationComplete()) 14 | <%_ if (authenticationType === 'oauth2') { _%> 15 | yield put(AuthInfoActions.authInfoRequest()); 16 | <%_ } _%> 17 | } 18 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/components/alert-message/alert-message.js.ejs: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text } from 'react-native'; 3 | 4 | import styles from './alert-message.styles'; 5 | 6 | // static propTypes = { 7 | // title: PropTypes.string, 8 | // icon: PropTypes.string, 9 | // style: PropTypes.object, 10 | // show: PropTypes.bool, 11 | // }; 12 | 13 | export default function AlertMessage({ title, style, show = true }) { 14 | return show ? ( 15 | 16 | 17 | 18 | {title && title.toUpperCase()} 19 | 20 | 21 | 22 | ) : null; 23 | } 24 | -------------------------------------------------------------------------------- /test/scripts/generate-react-native-app.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | echo "Using JDL for Generation" 5 | 6 | if [ -d "../backend" ]; then 7 | echo "Using React Native for Generation using ../backend folder" 8 | rm -rf ../client && mkdir ../client && cd ../client 9 | rnhipster --force 10 | else 11 | echo "Using JHipster for Generation. Both backend and frontend will be generated." 12 | mkdir ../backend && cd ../backend 13 | rnhipster jdl ../${JHI_REACT_NATIVE_APP_NAME}.jdl \ 14 | --defaults --no-insight --skip-git 15 | # list backend files 16 | echo "Listing files in directory: ../backend" 17 | ls -al 18 | fi 19 | 20 | # list client files 21 | cd ../client 22 | npm install 23 | echo "Listing files in directory: ../client" 24 | ls -al 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | --- 5 | 6 | **Describe the bug** 7 | 8 | 9 | 10 | **Instructions To reproduce** 11 | 12 | 13 | 14 | **JHipster app's `.yo-rc.json`** 15 | 16 | 17 | 18 | **Entity JDL or JSON files** 19 | 20 | 21 | 22 | **Versions (please complete the following information):** 23 | 24 | - JHipster React Native Version: 25 | - `jhipster info` output: 26 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/util/date-transforms.js.ejs: -------------------------------------------------------------------------------- 1 | export const convertLocalDateToString = (date) => { 2 | return !date || !date.getYear 3 | ? '' 4 | : ('0' + (date.getMonth() + 1).toString()).substr(-2) + 5 | '/' + 6 | ('0' + date.getDate().toString()).substr(-2) + 7 | '/' + 8 | date.getFullYear().toString().substr(2); 9 | }; 10 | 11 | export const convertDateTimeFromServer = (date) => { 12 | if (date) { 13 | return new Date(date); 14 | } else { 15 | return null; 16 | } 17 | }; 18 | 19 | export const convertLocalDateFromServer = (date) => { 20 | if (date) { 21 | var dateString = date.split('-'); 22 | return new Date(dateString[0], dateString[1] - 1, dateString[2]); 23 | } 24 | return null; 25 | }; 26 | -------------------------------------------------------------------------------- /docs/websockets.md: -------------------------------------------------------------------------------- 1 | ## WebSockets 2 | 3 | A websockets example is present under "Chat" in the Drawer Menu. JHipster React Native uses the existing `/websocket/tracker` endpoint to connect. It sends and receives chat messages using the `/topic/chat` message mapping. 4 | 5 | **Note:** The default JHipster websockets configuration requires users to authenticate before connecting. 6 | 7 | For a more advanced websockets example, see the [tracker.service.ts][1] and [ActivityService.java][2] in the generated JHipster webapp. 8 | 9 | [1]: https://github.com/jhipster/jhipster-sample-app-websocket/blob/main/src/main/webapp/app/core/tracker/tracker.service.ts 10 | [2]: https://github.com/jhipster/jhipster-sample-app-websocket/blob/main/src/main/java/io/github/jhipster/sample/web/websocket/ActivityService.java 11 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/modules/account/register/register.reducer.spec.js.ejs: -------------------------------------------------------------------------------- 1 | import Actions, { reducer, INITIAL_STATE } from '../../../../../app/modules/account/register/register.reducer' 2 | 3 | test('request', () => { 4 | const state = reducer(INITIAL_STATE, Actions.registerRequest()) 5 | 6 | expect(state.fetching).toBe(true) 7 | }) 8 | 9 | test('success', () => { 10 | const state = reducer(INITIAL_STATE, Actions.registerSuccess()) 11 | 12 | expect(state.fetching).toBe(false) 13 | expect(state.error).toBe(null) 14 | }) 15 | 16 | test('failure', () => { 17 | const state = reducer(INITIAL_STATE, Actions.registerFailure({ error: 'Duplicate Email' })) 18 | 19 | expect(state.fetching).toBe(false) 20 | expect(state.error).toEqual({ error: 'Duplicate Email' }) 21 | }) 22 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/shared/sagas/startup.saga.spec.js.ejs: -------------------------------------------------------------------------------- 1 | import { put } from 'redux-saga/effects' 2 | 3 | import { startup } from '../../../../app/shared/sagas/startup.saga' 4 | import LoginActions from '../../../../app/modules/login/login.reducer' 5 | import AccountActions from '../../../../app/shared/reducers/account.reducer' 6 | import AppStateActions from '../../../../app/shared/reducers/app-state.reducer' 7 | 8 | const stepper = (fn) => (mock) => fn.next(mock).value 9 | 10 | test('calls the right actions on startup', () => { 11 | const step = stepper(startup()) 12 | expect(step()).toEqual(put(LoginActions.loginLoad())) 13 | expect(step()).toEqual(put(AccountActions.accountRequest())) 14 | expect(step()).toEqual(put(AppStateActions.setRehydrationComplete())) 15 | }) 16 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/navigation/oauth-redirect-screen.tsx.ejs: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { StyleSheet, View, ActivityIndicator } from "react-native"; 3 | 4 | const OAuthRedirectScreen = () => { 5 | const urlSearchParams = new URLSearchParams(window.location.search); 6 | const params = Object.fromEntries(urlSearchParams.entries()); 7 | window.location.href = params.authUrl; 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default OAuthRedirectScreen; 16 | 17 | const styles = StyleSheet.create({ 18 | title: { 19 | fontSize: 36, 20 | }, 21 | container: { 22 | flex: 1, 23 | justifyContent: 'center', 24 | alignItems: 'center', 25 | padding: 8, 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/sagas/auth-info.saga.js.ejs: -------------------------------------------------------------------------------- 1 | import { call, put } from 'redux-saga/effects'; 2 | import AuthInfoActions from '../reducers/auth-info.reducer'; 3 | 4 | // get the oauth issuer information from the backend 5 | export function* getAuthInfo(api) { 6 | const authInfo = yield call(api.getOauthInfo); 7 | if (authInfo.ok) { 8 | if (authInfo.data.issuer && authInfo.data.issuer.endsWith('/')) { 9 | authInfo.data.issuer = authInfo.data.issuer.substring(0, authInfo.data.issuer.length - 1); 10 | } 11 | yield put(AuthInfoActions.authInfoSuccess(authInfo.data)); 12 | } else { 13 | let errorMessage = authInfo.data && authInfo.data.detail ? authInfo.data.detail : 'Failed to reach backend API'; 14 | yield put(AuthInfoActions.authInfoFailure(errorMessage)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/config/redux-persist.js.ejs: -------------------------------------------------------------------------------- 1 | import AsyncStorage from '@react-native-async-storage/async-storage'; 2 | 3 | import immutablePersistenceTransform from '../shared/util/immutable-persistence-transform' 4 | 5 | const REDUX_PERSIST = { 6 | active: true, 7 | reducerVersion: '1.0', 8 | storeConfig: { 9 | key: 'primary', 10 | storage: AsyncStorage, 11 | blacklist: ['appState'<%_ if (authenticationType === 'oauth2') { _%>, 'authInfo'<%_ } _%>], // reducer keys that you do NOT want stored to persistence here 12 | // whitelist: [], Optionally, just specify the keys you DO want stored to 13 | // persistence. An empty array means 'don't store any reducers' -> infinitered/ignite#409 14 | transforms: [immutablePersistenceTransform] 15 | } 16 | } 17 | 18 | export default REDUX_PERSIST 19 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/websockets/websocket.sagas.js.ejs: -------------------------------------------------------------------------------- 1 | import { put, select } from 'redux-saga/effects' 2 | 3 | import ChatActions from '../../modules/chat/chat.reducer' 4 | 5 | export const selectState = (state, key, subKey) => state[key][subKey] 6 | 7 | // processes the websocket message 8 | export function * processWebsocketMessage ({ subscription, msg }) { 9 | console.log(`WS-Saga: ${subscription}`) 10 | switch (subscription) { 11 | case 'chat': { 12 | const state = yield select(selectState, 'chat', 'chat') 13 | const chat = [].concat(state) 14 | chat.push(msg) 15 | yield put(ChatActions.chatSuccess(chat)) 16 | break 17 | } 18 | default: 19 | console.log(`Uncaught subscription: ${subscription}`) 20 | console.log(`Uncaught message: ${msg}`) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/jdl/entities-flickr2.jdl: -------------------------------------------------------------------------------- 1 | /* 2 | * This is the application and entity model for the Flickr app (https://github.com/mraible/mobile-jhipster/) application from Matt Raible 3 | */ 4 | 5 | entity Album { 6 | title String required 7 | description TextBlob 8 | created Instant 9 | } 10 | 11 | entity Photo { 12 | title String required 13 | description TextBlob 14 | image ImageBlob required 15 | height Integer 16 | width Integer 17 | taken Instant 18 | uploaded Instant 19 | } 20 | 21 | entity Tag { 22 | name String required minlength(2) 23 | } 24 | 25 | relationship ManyToOne { 26 | Album{user(login)} to User with builtInEntity 27 | Photo{album(title)} to Album 28 | } 29 | 30 | relationship ManyToMany { 31 | Photo{tag(name)} to Tag{photo} 32 | } 33 | 34 | paginate Album with pagination 35 | paginate Photo, Tag with infinite-scroll 36 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/shared/components/alert-message/alert-message.story.js.ejs: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import AlertMessage from './alert-message'; 4 | 5 | const styles = StyleSheet.create({ 6 | container: { backgroundColor: 'red' }, 7 | }); 8 | 9 | const meta = { 10 | title: 'AlertMessage', 11 | component: AlertMessage, 12 | parameters: { 13 | componentSubtitle: 'A component for displaying alert messages', 14 | }, 15 | }; 16 | 17 | export default meta; 18 | 19 | export const Default = { 20 | args: { 21 | title: 'ALERT ALERT', 22 | }, 23 | }; 24 | 25 | export const Hidden = { 26 | args: { 27 | title: 'ALERT ALERT', 28 | show: false, 29 | }, 30 | }; 31 | 32 | export const CustomStyle = { 33 | args: { 34 | title: 'ALERT ALERT', 35 | style: styles.container, 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /generators/react-native/templates/test/spec/shared/navigation/drawer/drawer-button.spec.js.ejs: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | import 'react-native'; 5 | import React from 'react'; 6 | import { fireEvent, render, screen } from '@testing-library/react-native'; 7 | import renderer from 'react-test-renderer'; 8 | 9 | import DrawerButton from '../../../../../app/navigation/drawer/drawer-button' 10 | 11 | test('DrawerButton component renders correctly', () => { 12 | const tree = renderer.create( {}} text="hi" />).toJSON(); 13 | expect(tree).toMatchSnapshot(); 14 | }); 15 | 16 | test('onPress', () => { 17 | let i = 0; 18 | const onPress = () => i++; 19 | render(); 20 | 21 | expect(i).toBe(0); 22 | fireEvent.press(screen.getByText('HI')); 23 | expect(i).toBe(1); 24 | }); 25 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/config/app-config.js.ejs: -------------------------------------------------------------------------------- 1 | <%_ if (authenticationType === 'oauth2') { _%> 2 | import { Platform } from 'react-native'; 3 | <%_ } _%> 4 | import Constants from 'expo-constants'; 5 | 6 | // load extra config from the app.json file 7 | const extra = Constants.manifest?.extra ?? {}; 8 | 9 | export default { 10 | // use 10.0.2.2 for Android to connect to host machine 11 | apiUrl: 'http://localhost:8080/', 12 | <%_ if (authenticationType === 'oauth2') { _%> 13 | // leave blank if using Keycloak 14 | nativeClientId: '', 15 | // use expo auth proxy with login, disable to enable logout completely from oauth provider 16 | useExpoAuthProxy: Platform.select({ web: false, default: true }), 17 | <%_ } _%> 18 | // use fixtures instead of real API requests 19 | useFixtures: false, 20 | // debug mode 21 | debugMode: __DEV__, 22 | extra, 23 | }; 24 | -------------------------------------------------------------------------------- /generators/react-native/templates/app/navigation/not-found-screen.tsx.ejs: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { StyleSheet, Text, View, Button } from 'react-native'; 3 | import type { StackScreenProps } from '@react-navigation/stack'; 4 | 5 | const NotFoundScreen = ({ navigation }: StackScreenProps<{ Home: undefined }>) => { 6 | return ( 7 | 8 | 404 Not Found 9 |