Skip to content
Open

Next #552

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/neat-bugs-see.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'rn-new': patch
'create-expo-stack': patch
---

simplify version specification for nativewind v5 and react-native-css
6 changes: 6 additions & 0 deletions .changeset/yummy-wombats-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'rn-new': minor
'create-expo-stack': minor
---

add support for nativewind v5 preview
62 changes: 62 additions & 0 deletions .github/workflows/next-release-pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Next Release PR
on:
push:
branches:
- next

permissions:
contents: write
issues: write
pull-requests: write
packages: write

jobs:
release:
if: ${{ github.repository_owner == 'roninoss' }}
name: Next Release PR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Setup Bun
uses: oven-sh/setup-bun@v2

## Unfortunately, bun doesn't support publishing to NPM registry yet
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18

- name: Cache node_modules
id: cache-bun
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-build-${{ env.cache-name }}\
-${{ hashFiles('**/bun.lockb') }}
restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-

- name: Install dependencies
run: bun install

- name: Build create-expo-stack
run: bun run build:cli

- name: Create Next Release Pull Request
id: changeset
uses: changesets/[email protected]
with:
commit: 'chore(next-release): version packages'
title: 'chore(next-release): version packages'
publish: npx changeset publish --tag next
env:
GITHUB_TOKEN: ${{ secrets.CES_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_ENV: 'production'
15 changes: 12 additions & 3 deletions .github/workflows/next-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Release Next
on:
push:
branches:
- main
- next

permissions:
id-token: write
Expand Down Expand Up @@ -89,17 +89,26 @@ jobs:
- name: Bump next version
run: bun run ./scripts/next-release.ts

- name: Build rn-new
run: bun run build:rn-new

## Unfortunately, bun doesn't support publishing to NPM registry yet
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: latest

- name: Authenticate to npm and publish
- name: Authenticate to npm and publish both packages
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
bun run build:cli
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc

# Publish create-expo-stack@next
cd ./cli
npm publish --provenance --access public --ignore-scripts --tag next
cd ..

# Publish rn-new@next
cd ./packages/rn-new
npm publish --provenance --access public --ignore-scripts --tag next
3 changes: 3 additions & 0 deletions .github/workflows/run-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v5
with:
node-version: 22

- run: bun install
- run: bun run build
Expand Down
5 changes: 3 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
.gitignore
.husky/pre-commit
.prettierignore
bun.lockb
LICENSE
cli/__tests__/__snapshots__/*
README.md
README.md
bun.lock
cli/__tests__/cli-integration.test.mts.snapshot
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"*.ejs": "ejs",
"*.h": "objective-c",
"*.m": "objective-c"
}
},
"typescript.tsdk": "node_modules/typescript/lib"
}
5,014 changes: 5,014 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

Binary file removed bun.lockb
Binary file not shown.
16 changes: 14 additions & 2 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# create-expo-stack

## 2.19.0

### Minor Changes

- 9578d52: expo54 support

### Patch Changes

- e230be0: fix: actually fix types for authentication selection
- 9e33b9c: fixes eas setup
- bd64fca: fix: resolve TypeScript error in authentication select options
- 5dbc6f2: fix: types for authentication selection
- bd64fca: feat: add React import and white background to ScreenContent templates

## 2.18.10

### Patch Changes
Expand Down Expand Up @@ -184,7 +198,6 @@
### Minor Changes

- [#280](https://github.com/roninoss/create-expo-stack/pull/280) [`08c09d915dc6f6579446913a51994eb1898ed88d`](https://github.com/roninoss/create-expo-stack/commit/08c09d915dc6f6579446913a51994eb1898ed88d) Thanks [@theblondealex](https://github.com/theblondealex)! - Added a StateManagement Question with zustand to start and potentially more to follow

- setup with a question prompt just before the internationalization prompt
- --zustand flag to skip the prompt
- Adds a StateManagement folder to the project with a zustandStore.ts file to start with
Expand Down Expand Up @@ -798,7 +811,6 @@
### Patch Changes

- [`026b97e`](https://github.com/roninoss/create-expo-stack/commit/026b97ee02f370ee1ee10dad9877b540a3c623d7) Thanks [@danstepanov](https://github.com/danstepanov)! - - symlink README

- add shortlink for discord
- update contributors
- add header labels and descriptor to README
Expand Down
204 changes: 204 additions & 0 deletions cli/__tests__/cli-integration.test.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import * as assert from 'node:assert';
import { execSync, spawnSync } from 'node:child_process';
import { readFile } from 'node:fs/promises';
import * as path from 'node:path';
import { test } from 'node:test';
import pkgJson from '../package.json' with { type: 'json' };

const version = pkgJson.version;

type InputFlag = `--${string}`;

const cli = (inputs: string[]) => {
const pathToFile = `${path.join(import.meta.dirname, '../', 'bin', 'create-expo-stack.js')}`;

console.log('running', `node ${pathToFile} ${inputs.join(' ')}`);

const { stdout, error, status, stderr } = spawnSync('node', [pathToFile, ...inputs], {
shell: true,
stdio: 'pipe'
});

if (error || status !== 0) {
const stdoutStr = stdout?.toString?.();
console.log('failed command', `node ${pathToFile} ${inputs.join(' ')}`);
console.log('stderr: ', stderr?.toString?.());
console.log('stdout: ', stdoutStr);
throw new Error(stderr?.toString?.());
}

return stdout?.toString?.();
};

// we can generate combinations soon.
const generateProject = ({
projectName = 'myTestProject',
flags
}: {
projectName?: string;
flags: Array<InputFlag>;
}) => {
return cli([projectName, ...flags]);
};

const skipSnapshots = process.env.SKIP_SNAPSHOTS === '1';

await test(`outputs version`, async () => {
const output = await cli([`--version`]);

assert.ok(output.includes(version));
});

await test(`outputs help`, async () => {
const output = await cli([`--help`]);

assert.ok(output.includes(`Info`));
});

// React Navigation combinations - covering all styling packages and navigation types
// to test color scheme support and Navigation component naming
const reactNavigationCombinations = [
['--react-navigation', '--tabs', '--stylesheet'],
['--react-navigation', '--tabs', '--nativewind'],
['--react-navigation', '--tabs', '--tamagui'],
['--react-navigation', '--tabs', '--restyle'],
['--react-navigation', '--tabs', '--unistyles'],

['--react-navigation', '--drawer+tabs', '--stylesheet'],
['--react-navigation', '--drawer+tabs', '--nativewind'],
['--react-navigation', '--drawer+tabs', '--tamagui'],
['--react-navigation', '--drawer+tabs', '--restyle'],
['--react-navigation', '--drawer+tabs', '--unistyles'],

['--react-navigation', '--stack', '--stylesheet'],
['--react-navigation', '--stack', '--nativewind'],
['--react-navigation', '--stack', '--tamagui'],
['--react-navigation', '--stack', '--restyle'],
['--react-navigation', '--stack', '--unistyles']
] as const;

// Core combinations that run by default
const coreCombinations = [
['--expo-router', '--nativewind'],
['--expo-router', '--stylesheet'],
['--expo-router', '--tabs', '--nativewind'],
['--expo-router', '--tabs', '--stylesheet'],
['--expo-router', '--drawer+tabs', '--nativewind'],
['--expo-router', '--drawer+tabs', '--stylesheet'],
// nativewindui selections
[
'--expo-router',
'--drawer+tabs',
'--nativewindui',
'--selected-components=date-picker,picker,text',
'--expo-router'
],
// nativewindui no selections
['--expo-router', '--drawer+tabs', '--nativewindui', '--expo-router'],
// no install is important for the website cli that generates a project zip file
['--nativewindui', '--no-install'],
// nativewindui blank
['--expo-router', '--drawer+tabs', '--nativewindui', '--blank', '--expo-router']
] as const;

// Combine all combinations based on environment variables
const popularCombinations = process.env.INCLUDE_REACT_NAVIGATION_TESTS
? [...coreCombinations, ...reactNavigationCombinations]
: coreCombinations;

const projectName = `myTestProject`;
const pathToProject = `./${projectName}`;

const packageManager = 'npm';

const packageManagerFlag = `--${packageManager}` as const;
for (const flags of popularCombinations) {
const finalFlags = [...flags, packageManagerFlag, '--overwrite' as const, '--no-git' as const];

await test(`generates a project with ${finalFlags.join(' ')}`, async (context) => {
const output = generateProject({
projectName: projectName,
flags: finalFlags
});

assert.ok(output.includes(packageManager));

if (!finalFlags.includes('--no-install')) {
assert.ok(output.includes('Installing dependencies'));
}

const pkgjson = await import(path.resolve(pathToProject, 'package.json'), { with: { type: 'json' } });

const pkgJsonWithoutVersions = {
...pkgjson.default,
dependencies: Object.keys(pkgjson.default.dependencies).reduce((acc, key) => {
return {
...acc,
[key]: ''
};
}, {}),
devDependencies: Object.keys(pkgjson.default.devDependencies).reduce((acc, key) => {
return {
...acc,
[key]: ''
};
}, {})
};

if (!skipSnapshots) {
context.assert.snapshot(pkgJsonWithoutVersions);
}

const cesconfigRaw = await readFile(`${pathToProject}/cesconfig.jsonc`);
const cesconfigText = cesconfigRaw.toString();
// Strip single-line comments from JSONC
const cleanedText = cesconfigText.replace(/^\s*\/\/.*$/gm, '');
const cesconfig = JSON.parse(cleanedText);

const cesconfigWithoutOS = {
...cesconfig,
cesVersion: undefined,
os: {},
packageManager: { ...cesconfig.packageManager, version: undefined },
flags: {
...cesconfig.flags,
publish: false
}
};

if (!skipSnapshots) {
context.assert.snapshot(cesconfigWithoutOS);
}

const fileList = execSync(
`find ./${projectName} -not -path "./${projectName}/node_modules*" -not -path "./${projectName}/.git*"`
);

// sort the file list for consistent snapshotting
const sortedFileList = fileList
.toString()
.split('\n')
.filter(Boolean)
.toSorted((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }));

if (!skipSnapshots) {
context.assert.snapshot(sortedFileList);
}

// typecheck only works if we have packages installed
if (!finalFlags.includes('--no-install')) {
// throws if it fails
execSync(`cd ${projectName} && bun run tsc --noEmit`);
}
});
}

// i18next;
await test(`generates a default project with i18n`, async () => {
const output = await generateProject({
projectName: 'myTestProject',
flags: ['--default', `--i18next`, `--bun`, '--overwrite', '--no-git']
});

assert.ok(output.includes('--i18next'));
});
Loading
Loading