From f8f45f330ba54aa278b39a8420ba3e6aa3915b8e Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 21 Jan 2026 15:09:59 +0100 Subject: [PATCH 1/2] feat: re-enable microsoft test app --- .../create-react-native-library/src/prompt.ts | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/packages/create-react-native-library/src/prompt.ts b/packages/create-react-native-library/src/prompt.ts index 1d6bbcd5b..ae20ac414 100644 --- a/packages/create-react-native-library/src/prompt.ts +++ b/packages/create-react-native-library/src/prompt.ts @@ -74,30 +74,25 @@ const LANGUAGE_CHOICES: { }, ]; -const EXAMPLE_CHOICES = ( - [ - { - title: 'App with Community CLI', - value: 'vanilla', - description: "Provides access to app's native code", - disabled: false, - }, - { - title: 'Test App by Microsoft', - value: 'test-app', - description: "App's native code is abstracted away", - // Test App currently doesn't work with React Native 0.79.2 - // due to missing `Gemfile` in the template - disabled: !process.env.CRNL_ENABLE_TEST_APP, - }, - { - title: 'App with Expo CLI', - value: 'expo', - description: 'Managed expo app with web support', - disabled: false, - }, - ] as const -).filter((choice) => !choice.disabled); +const EXAMPLE_CHOICES = [ + { + title: 'App with Community CLI', + value: 'vanilla', + description: "Provides access to app's native code", + disabled: false, + }, + { + title: 'Test App by Microsoft', + value: 'test-app', + description: "App's native code is abstracted away", + }, + { + title: 'App with Expo CLI', + value: 'expo', + description: 'Managed expo app with web support', + disabled: false, + }, +] as const; const validateDirectory = (input: string) => { if (!input) { From 4ac88b572e6de9f1f5a4128ffaaedabdb515f014 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 21 Jan 2026 15:09:59 +0100 Subject: [PATCH 2/2] feat: re-enable microsoft test app --- .../src/exampleApp/generateExampleApp.ts | 42 ++++++++++++++++--- .../create-react-native-library/src/prompt.ts | 22 ++++------ .../src/template.ts | 8 +++- .../example/babel.config.js | 0 .../example/index.js | 0 .../example/tsconfig.json | 0 .../example/react-native.config.js | 2 +- 7 files changed, 52 insertions(+), 22 deletions(-) rename packages/create-react-native-library/templates/{expo-library => example-expo}/example/babel.config.js (100%) rename packages/create-react-native-library/templates/{expo-library => example-expo}/example/index.js (100%) rename packages/create-react-native-library/templates/{expo-library => example-expo}/example/tsconfig.json (100%) diff --git a/packages/create-react-native-library/src/exampleApp/generateExampleApp.ts b/packages/create-react-native-library/src/exampleApp/generateExampleApp.ts index 9f0cdd1ee..e027c7475 100644 --- a/packages/create-react-native-library/src/exampleApp/generateExampleApp.ts +++ b/packages/create-react-native-library/src/exampleApp/generateExampleApp.ts @@ -5,6 +5,7 @@ import path from 'path'; import type { TemplateConfiguration } from '../template'; import sortObjectKeys from '../utils/sortObjectKeys'; import { spawn } from '../utils/spawn'; +import dedent from 'dedent'; const FILES_TO_DELETE = [ '__tests__', @@ -37,12 +38,16 @@ const PACKAGES_TO_REMOVE = [ 'react-native-safe-area-context', ]; -const PACKAGES_TO_ADD_WEB = { +const PACKAGES_TO_ADD_EXPO_WEB = { '@expo/metro-runtime': '~5.0.4', 'react-dom': '19.1.0', 'react-native-web': '~0.21.1', }; +const PACKAGES_TO_ADD_DEV_EXPO_NATIVE = { + 'expo-dev-client': '~5.0.3', +}; + export default async function generateExampleApp({ config, root, @@ -50,7 +55,7 @@ export default async function generateExampleApp({ }: { config: TemplateConfiguration; root: string; - reactNativeVersion?: string; + reactNativeVersion: string | undefined; }) { const directory = path.join(root, 'example'); @@ -252,14 +257,39 @@ export default async function generateExampleApp({ bundledNativeModules = {}; } - Object.entries(PACKAGES_TO_ADD_WEB).forEach(([name, version]) => { - dependencies[name] = bundledNativeModules[name] || version; - }); + if (config.project.native) { + Object.entries(PACKAGES_TO_ADD_DEV_EXPO_NATIVE).forEach( + ([name, version]) => { + devDependencies[name] = bundledNativeModules[name] || version; + } + ); + + scripts.start = 'expo start --dev-client'; + scripts.android = 'expo run:android'; + scripts.ios = 'expo run:ios'; - scripts.web = 'expo start --web'; + delete scripts.web; + + await fs.writeFile( + path.join(directory, '.gitignore'), + dedent` + # These folders are generated with prebuild (CNG) + android/ + ios/ + ` + ); + } else { + Object.entries(PACKAGES_TO_ADD_EXPO_WEB).forEach(([name, version]) => { + dependencies[name] = bundledNativeModules[name] || version; + }); + + scripts.web = 'expo start --web'; + } const app = await fs.readJSON(path.join(directory, 'app.json')); + app.expo.name = `${config.project.name} Example`; + app.expo.slug = `${config.project.slug}-example`; app.expo.android = app.expo.android || {}; app.expo.android.package = `${config.project.package}.example`; app.expo.ios = app.expo.ios || {}; diff --git a/packages/create-react-native-library/src/prompt.ts b/packages/create-react-native-library/src/prompt.ts index ae20ac414..ccaf5e523 100644 --- a/packages/create-react-native-library/src/prompt.ts +++ b/packages/create-react-native-library/src/prompt.ts @@ -78,19 +78,17 @@ const EXAMPLE_CHOICES = [ { title: 'App with Community CLI', value: 'vanilla', - description: "Provides access to app's native code", - disabled: false, - }, - { - title: 'Test App by Microsoft', - value: 'test-app', - description: "App's native code is abstracted away", + description: 'Classic React Native app with native code access', }, { title: 'App with Expo CLI', value: 'expo', - description: 'Managed expo app with web support', - disabled: false, + description: 'Managed Expo app for easier upgrades', + }, + { + title: 'Test App by Microsoft', + value: 'test-app', + description: "Test app with app's native code abstracted", }, ] as const; @@ -324,10 +322,8 @@ export const prompt = create(['[name]'], { skip: (): boolean => { const answers = prompt.read(); - if (typeof answers.type === 'string') { - return answers.type === 'library' - ? choice.value !== 'expo' - : choice.value === 'expo'; + if (answers.type === 'library') { + return choice.value !== 'expo'; } return false; diff --git a/packages/create-react-native-library/src/template.ts b/packages/create-react-native-library/src/template.ts index 087aed51a..a7e9c45e2 100644 --- a/packages/create-react-native-library/src/template.ts +++ b/packages/create-react-native-library/src/template.ts @@ -61,9 +61,9 @@ const EXAMPLE_MODULE_NEW_FILES = path.resolve( '../templates/example-module-new' ); const EXAMPLE_VIEW_FILES = path.resolve(__dirname, '../templates/example-view'); +const EXAMPLE_EXPO_FILES = path.resolve(__dirname, '../templates/example-expo'); const JS_FILES = path.resolve(__dirname, '../templates/js-library'); -const EXPO_FILES = path.resolve(__dirname, '../templates/expo-library'); const NATIVE_COMMON_FILES = path.resolve( __dirname, '../templates/native-common' @@ -203,7 +203,7 @@ export async function applyTemplates( if (answers.languages === 'js') { await applyTemplate(config, JS_FILES, folder); - await applyTemplate(config, EXPO_FILES, folder); + await applyTemplate(config, EXAMPLE_EXPO_FILES, folder); } else { await applyTemplate(config, NATIVE_COMMON_FILES, folder); @@ -211,6 +211,10 @@ export async function applyTemplates( await applyTemplate(config, NATIVE_COMMON_EXAMPLE_FILES, folder); } + if (config.example === 'expo') { + await applyTemplate(config, EXAMPLE_EXPO_FILES, folder); + } + if (config.project.moduleConfig === 'nitro-modules') { await applyTemplate(config, NITRO_COMMON_FILES, folder); await applyTemplate(config, NATIVE_FILES['module_nitro'], folder); diff --git a/packages/create-react-native-library/templates/expo-library/example/babel.config.js b/packages/create-react-native-library/templates/example-expo/example/babel.config.js similarity index 100% rename from packages/create-react-native-library/templates/expo-library/example/babel.config.js rename to packages/create-react-native-library/templates/example-expo/example/babel.config.js diff --git a/packages/create-react-native-library/templates/expo-library/example/index.js b/packages/create-react-native-library/templates/example-expo/example/index.js similarity index 100% rename from packages/create-react-native-library/templates/expo-library/example/index.js rename to packages/create-react-native-library/templates/example-expo/example/index.js diff --git a/packages/create-react-native-library/templates/expo-library/example/tsconfig.json b/packages/create-react-native-library/templates/example-expo/example/tsconfig.json similarity index 100% rename from packages/create-react-native-library/templates/expo-library/example/tsconfig.json rename to packages/create-react-native-library/templates/example-expo/example/tsconfig.json diff --git a/packages/create-react-native-library/templates/native-common-example/example/react-native.config.js b/packages/create-react-native-library/templates/native-common-example/example/react-native.config.js index ae95bd0a4..00c6117c6 100644 --- a/packages/create-react-native-library/templates/native-common-example/example/react-native.config.js +++ b/packages/create-react-native-library/templates/native-common-example/example/react-native.config.js @@ -15,7 +15,7 @@ module.exports = { automaticPodsInstallation: true, }, }), -<% } else { -%> +<% } else if (example === 'vanilla') { -%> project: { ios: { automaticPodsInstallation: true,