diff --git a/.github/workflows/ci-requiring-tokens.yml b/.github/workflows/ci-requiring-tokens.yml index 66aee435b..fb5ebd4ef 100644 --- a/.github/workflows/ci-requiring-tokens.yml +++ b/.github/workflows/ci-requiring-tokens.yml @@ -113,4 +113,17 @@ jobs: MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }} MAPBOX_DOWNLOAD_TOKEN: ${{ secrets.MAPBOX_DOWNLOAD_TOKEN }} ENV_MAPBOX_ACCESS_TOKEN: ${{ secrets.ENV_MAPBOX_ACCESS_TOKEN }} - ENV_MAPBOX_DOWNLOAD_TOKEN: ${{ secrets.ENV_MAPBOX_DOWNLOAD_TOKEN }} \ No newline at end of file + ENV_MAPBOX_DOWNLOAD_TOKEN: ${{ secrets.ENV_MAPBOX_DOWNLOAD_TOKEN }} + + call_web_workflow: + name: "Web/Mapbox" + uses: ./.github/workflows/web-actions.yml + with: + env_name: ${{ inputs.env_name }} + ref: ${{ inputs.ref }} + NVMRC: ${{ inputs.NVMRC }} + secrets: + MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }} + MAPBOX_DOWNLOAD_TOKEN: ${{ secrets.MAPBOX_DOWNLOAD_TOKEN }} + ENV_MAPBOX_ACCESS_TOKEN: ${{ secrets.ENV_MAPBOX_ACCESS_TOKEN }} + ENV_MAPBOX_DOWNLOAD_TOKEN: ${{ secrets.ENV_MAPBOX_DOWNLOAD_TOKEN }} diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index cf3126964..fe109b55d 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -41,6 +41,15 @@ jobs: run: node scripts/doc-generate.mjs - name: Generate example docs into maps-docs repo run: bun scripts/example-docs.ts + - name: Generate example app into maps-docs repo + run: | + cd example + echo $MAPBOX_WEB_ACCESS_TOKEN > accesstoken + yarn install + npx expo export -p web --outpub-dir ../../maps-docs/example-app + working-directory: maps + env: + MAPBOX_WEB_ACCESS_TOKEN: ${{ secrets.MAPBOX_WEB_ACCESS_TOKEN }} - name: Setup deploy key for github deploy uses: webfactory/ssh-agent@v0.5.0 with: diff --git a/.github/workflows/web-actions.yml b/.github/workflows/web-actions.yml new file mode 100644 index 000000000..15a3a0c3e --- /dev/null +++ b/.github/workflows/web-actions.yml @@ -0,0 +1,59 @@ +name: Web Build + +on: + workflow_call: + inputs: + env_name: + required: true + default: default + type: string + ref: + required: false + type: string + NVMRC: + required: true + type: string + secrets: + MAPBOX_ACCESS_TOKEN: + required: true + MAPBOX_DOWNLOAD_TOKEN: + required: true + ENV_MAPBOX_ACCESS_TOKEN: + required: false + ENV_MAPBOX_DOWNLOAD_TOKEN: + required: false + +jobs: + build_example: + name: Example Build for Web + runs-on: ubuntu-latest + environment: ${{ inputs.env_name }} + steps: + - name: Checkout + uses: actions/checkout@v4 + if: ${{ inputs.ref == '' }} + + - name: Checkout fork + uses: actions/checkout@v4 + if: ${{ inputs.ref != '' }} + with: + ref: ${{ inputs.ref }} + + - name: Setup node ${{ inputs.NVMRC }} + uses: actions/setup-node@v3.5.1 + with: + node-version: ${{ inputs.NVMRC }} + + - run: echo $MAPBOX_ACCESS_TOKEN > ./accesstoken + working-directory: example + env: + MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN || secrets.ENV_MAPBOX_ACCESS_TOKEN }} + + - run: yarn install --network-timeout 1000000 + working-directory: example + + - run: yarn postinstall + working-directory: example + + - run: npx expo export --platform web + working-directory: example \ No newline at end of file diff --git a/example/App.js b/example/App.js new file mode 100644 index 000000000..8642fae62 --- /dev/null +++ b/example/App.js @@ -0,0 +1,3 @@ +import App from './src/App'; + +export default App; diff --git a/example/app.json b/example/app.json index f0d3595a1..6d537da8b 100644 --- a/example/app.json +++ b/example/app.json @@ -5,6 +5,9 @@ "web": { "bundler": "metro", "output": "single" + }, + "experiments": { + "baseUrl": "/example-app" } } } diff --git a/example/metro.config.js b/example/metro.config.js index e24fe408c..a454e9be4 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -1,6 +1,7 @@ +// https://github.com/callstack/react-native-builder-bob/blob/main/packages/create-react-native-library/templates/expo-library/example/metro.config.js const path = require('path'); -const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); +const { getDefaultConfig } = require('expo/metro-config'); const exclusionList = require('metro-config/src/defaults/exclusionList'); const escape = require('escape-string-regexp'); @@ -9,9 +10,16 @@ const root = path.resolve(__dirname, '..'); const libPackageJson = require('../package.json'); const libPeerDependencies = Object.keys(libPackageJson.peerDependencies) - .concat(['@babel/runtime']) + .concat([ + '@babel/runtime', + 'react-native-web', + '@react-native/assets-registry', + ]) .concat(Object.keys(libPackageJson.dependencies)); +const modules = libPeerDependencies; + +/** @type {import('expo/metro-config').MetroConfig} */ const defaultConfig = getDefaultConfig(__dirname); /** @@ -21,18 +29,22 @@ const defaultConfig = getDefaultConfig(__dirname); * @type {import('metro-config').MetroConfig} */ const config = { + ...defaultConfig, + projectRoot: __dirname, watchFolders: [root], resolver: { + ...defaultConfig.resolver, + blacklistRE: exclusionList( - libPeerDependencies.map( + modules.map( (m) => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`), ), ), - extraNodeModules: libPeerDependencies.reduce((acc, name) => { + extraNodeModules: modules.reduce((acc, name) => { acc[name] = path.join(__dirname, 'node_modules', name); return acc; }, {}), @@ -41,6 +53,8 @@ const config = { }, transformer: { + ...defaultConfig.transformer, + getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, @@ -50,4 +64,38 @@ const config = { }, }; -module.exports = mergeConfig(defaultConfig, config); +const fixWebExportToUseWebSuffixForRNMBX = true; +if (fixWebExportToUseWebSuffixForRNMBX) { + config.resolver.resolveRequest = (context, moduleName, platform) => { + let result = null; + if (platform === 'web' && moduleName === path.join(root, 'src', 'index')) { + result = context.resolveRequest(context, moduleName + '.web', platform); + } else { + result = context.resolveRequest(context, moduleName, platform); + } + return result; + }; +} + +const debugModuleResolution = false; +if (debugModuleResolution) { + config.maxWorkers = 1; + config.resolver.resolveRequest = (context, moduleName, platform) => { + let result = null; + if (platform === 'web' && moduleName === path.join(root, 'src', 'index')) { + result = context.resolveRequest(context, moduleName + '.web', platform); + } else { + result = context.resolveRequest(context, moduleName, platform); + } + console.log( + ' => resolveRequest', + context.originModulePath, + moduleName, + platform, + result, + ); + return result; + }; +} + +module.exports = config; diff --git a/example/src/App.js b/example/src/App.js index 19d097095..967e107b8 100755 --- a/example/src/App.js +++ b/example/src/App.js @@ -3,6 +3,7 @@ import Mapbox from '@rnmapbox/maps'; import { StyleSheet, Text, View, LogBox, SafeAreaView } from 'react-native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { NavigationContainer } from '@react-navigation/native'; +import { SafeAreaProvider } from 'react-native-safe-area-context'; import sheet from './styles/sheet'; import colors from './styles/colors'; @@ -41,9 +42,11 @@ function AppStackNavigator() { } const AppContainer = () => ( - - - + + + + + ); class App extends React.Component { constructor(props) {