Skip to content

Commit

Permalink
Create App.tsx at end of "createApp" command, since will depend on ot…
Browse files Browse the repository at this point in the history
…her tasks (#25)

When we create a new app using thoughtbelt, we will want to generate an
`App.tsx` that has all of our providers and tools configured, including
React Navigation, global state provider, styling provider, etc. To me,
since this file will be tied to many different commands, it would make
more sense for the creation of this file to be a step at the end of the
`createApp` command, independent of any one command.

If we run `thoughtbelt navigation` independently, we will not want to
create a new `App.tsx` in that case, though it would likely be helpful
to include some output directing the user to wrap their app in a
`NavigationContainer`. What do you think?

We don't yet have a mechanism for detecting if a given command is
running independently as opposed to being a part of the main `createApp`
(or other) command .
  • Loading branch information
Stephen Hanson authored Dec 12, 2023
1 parent 2cdcb65 commit 1a2d6de
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/commands/__tests__/createApp.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { confirm } from '@inquirer/prompts';
import { vol } from 'memfs';
import { Mock, afterEach, test, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { Mock, afterEach, expect, test, vi } from 'vitest';
import print from '../../util/print';
import { createApp } from '../createApp';

Expand All @@ -15,7 +15,7 @@ afterEach(() => {
(print as Mock).mockReset();
});

test("doesn't error", async () => {
test('creates app', async () => {
(confirm as Mock).mockResolvedValueOnce(true);
vi.spyOn(process, 'chdir').mockImplementation(() => {
const json = {
Expand All @@ -29,4 +29,6 @@ test("doesn't error", async () => {
vol.fromJSON(json, './');
});
await createApp('MyApp', { testing: true });

expect(fs.readFileSync('App.tsx', 'utf8')).toMatch('expo-status-bar');
});
4 changes: 4 additions & 0 deletions src/commands/createApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ora from 'ora';
import { globals } from '../constants';
import addDependency from '../util/addDependency';
import addPackageJsonScripts from '../util/addPackageJsonScripts';
import copyTemplateDirectory from '../util/copyTemplateDirectory';
import exec from '../util/exec';
import getUserPackageManager from '../util/getUserPackageManager';
import print from '../util/print';
Expand All @@ -30,6 +31,7 @@ export async function createApp(name: string | undefined, options: Options) {

globals.interactive = interactive;
globals.isTest = isTest;
globals.isCreateApp = true;

const appName = name || (await getAppName());
await printIntro();
Expand Down Expand Up @@ -83,6 +85,8 @@ export async function createApp(name: string | undefined, options: Options) {
await commit('Add jest, Testing Library');
}

await copyTemplateDirectory({ templateDir: 'createApp' });

print(chalk.green(`\n\n👖 ${appName} successfully configured!`));

print(`
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { fileURLToPath } from 'url';
export const globals = {
interactive: true,
isTest: false,
isCreateApp: false,
};

// TSUP builds files without hierarchy to dist/, so the path is ultimately
Expand Down
28 changes: 28 additions & 0 deletions templates/createApp/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import Providers, { Provider } from 'src/components/Providers';

// Add providers to this array
const providers: Provider[] = [
// CODEGEN:BELT:PROVIDERS - do not remove
];

export default function App() {
return (
<Providers providers={providers}>
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
</View>
</Providers>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
14 changes: 14 additions & 0 deletions templates/createApp/src/components/Providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ReactNode } from 'react';

export type Provider = (children: ReactNode) => ReactNode;

type ProvidersProps = {
children: ReactNode;
providers: Provider[];
};

export default function Providers({ children, providers }: ProvidersProps) {
return providers.reverse().reduce((acc, current) => {
return current(acc);
}, children);
}

0 comments on commit 1a2d6de

Please sign in to comment.