Skip to content

Commit 9d290d2

Browse files
committed
Merge branch 'main' into szymonrybczak/feat-add-rnta
2 parents 54d13ea + 48b0e9a commit 9d290d2

File tree

22 files changed

+2100
-121
lines changed

22 files changed

+2100
-121
lines changed

.github/workflows/build-templates.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ jobs:
198198
working-directory: ${{ env.work_dir }}
199199
run: |
200200
yarn typecheck
201+
# FIXME: Remove this once we fix the typecheck errors
202+
continue-on-error: true
201203

202204
- name: Test library
203205
working-directory: ${{ env.work_dir }}

.github/workflows/check-project.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,8 @@ jobs:
2626
- name: Typecheck
2727
run: yarn typecheck
2828

29+
- name: Test
30+
run: yarn test
31+
2932
- name: Build packages
3033
run: yarn lerna run prepare

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"lint": "eslint \"**/*.{js,ts,tsx}\"",
1919
"typecheck": "tsc --noEmit",
2020
"watch": "concurrently 'yarn typecheck --watch' 'lerna run --parallel prepare -- --watch'",
21+
"test": "yarn workspace react-native-builder-bob test",
2122
"docs": "yarn workspace docs"
2223
},
2324
"devDependencies": {
@@ -48,7 +49,8 @@
4849
"node_modules/",
4950
"coverage/",
5051
"lib/",
51-
"templates/"
52+
"templates/",
53+
"__fixtures__/"
5254
],
5355
"prettier": {
5456
"singleQuote": true,

packages/create-react-native-library/src/utils/generateExampleApp.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ export default async function generateExampleApp({
145145

146146
const SCRIPTS_TO_ADD = {
147147
'build:android':
148-
'cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a',
149-
'build:ios': `cd ios && xcodebuild -workspace ${projectName}Example.xcworkspace -scheme ${projectName}Example -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO`,
148+
'react-native build-android --extra-params "--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a"',
149+
'build:ios': `react-native build-ios --scheme ${projectName}Example --mode Debug --extra-params "-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO"`,
150150
};
151151

152152
if (type !== 'expo') {

packages/react-native-builder-bob/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@
3434
"registry": "https://registry.npmjs.org/"
3535
},
3636
"scripts": {
37-
"prepare": "babel --extensions .ts,.tsx src --out-dir lib --source-maps --delete-dir-on-start"
37+
"prepare": "babel --extensions .ts,.tsx src --out-dir lib --source-maps --delete-dir-on-start",
38+
"test": "jest"
39+
},
40+
"jest": {
41+
"testPathIgnorePatterns": [
42+
"/lib/"
43+
]
3844
},
3945
"dependencies": {
4046
"@babel/core": "^7.18.5",
@@ -59,6 +65,7 @@
5965
},
6066
"devDependencies": {
6167
"@babel/cli": "^7.17.10",
68+
"@jest/globals": "^29.7.0",
6269
"@types/babel__core": "^7.1.19",
6370
"@types/browserslist": "^4.15.0",
6471
"@types/cross-spawn": "^6.0.2",
@@ -70,6 +77,7 @@
7077
"@types/prompts": "^2.0.14",
7178
"@types/which": "^2.0.1",
7279
"@types/yargs": "^17.0.10",
73-
"concurrently": "^7.2.2"
80+
"concurrently": "^7.2.2",
81+
"jest": "^29.7.0"
7482
}
7583
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import "@";
2+
import f from "@/f";
3+
import "@something";
4+
import "./@";
5+
import "file";
6+
import { something } from "something";
7+
import "something/somefile";
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import "..";
2+
import f from "../f";
3+
import "@something";
4+
import "./@";
5+
import "../f";
6+
import { something } from "another";
7+
import "another/somefile";
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export * as a from "a";
2+
export * as b from "./b";
3+
export * as c from "./c";
4+
export * as d from "./d";
5+
export * as e from "./e.story";
6+
export * as f from "../f";
7+
export * as pac from "..";
8+
export * as pak from "../";
9+
export * as pax from "../index";
10+
11+
export { a as a1 } from "./a";
12+
export * from "./b";
13+
14+
export type { A } from "./a";
15+
16+
export const foo = "foo";
17+
18+
const bar = "bar";
19+
20+
export { bar };
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export * as a from "a";
2+
export * as b from "./b.mjs";
3+
export * as c from "./c.mjs";
4+
export * as d from "./d";
5+
export * as e from "./e.story.mjs";
6+
export * as f from "../f.mjs";
7+
export * as pac from "../index.mjs";
8+
export * as pak from "../index.mjs";
9+
export * as pax from "../index.mjs";
10+
export { a as a1 } from "./a.mjs";
11+
export * from "./b.mjs";
12+
export type { A } from "./a";
13+
export const foo = "foo";
14+
const bar = "bar";
15+
export { bar };
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import "./a";
2+
import a from "a";
3+
import b from "./b";
4+
import c from "./c";
5+
import d from "./d";
6+
import e from "./e.story";
7+
import f from "../f";
8+
import pac from "..";
9+
import pak from "../";
10+
import pax from "../index";
11+
12+
import { a as a1 } from "./a";
13+
import * as b1 from "./b";
14+
import something, { c as c1 } from "./c";
15+
16+
import type { A } from "./a";
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import "./a.mjs";
2+
import a from "a";
3+
import b from "./b.mjs";
4+
import c from "./c.mjs";
5+
import d from "./d";
6+
import e from "./e.story.mjs";
7+
import f from "../f.mjs";
8+
import pac from "../index.mjs";
9+
import pak from "../index.mjs";
10+
import pax from "../index.mjs";
11+
import { a as a1 } from "./a.mjs";
12+
import * as b1 from "./b.mjs";
13+
import something, { c as c1 } from "./c.mjs";
14+
import type { A } from "./a";

packages/react-native-builder-bob/src/__fixtures__/project/code/a.ts

Whitespace-only changes.

packages/react-native-builder-bob/src/__fixtures__/project/code/b.ts

Whitespace-only changes.

packages/react-native-builder-bob/src/__fixtures__/project/code/c.mjs

Whitespace-only changes.

packages/react-native-builder-bob/src/__fixtures__/project/code/d/.gitkeep

Whitespace-only changes.

packages/react-native-builder-bob/src/__fixtures__/project/code/e.story.ts

Whitespace-only changes.

packages/react-native-builder-bob/src/__fixtures__/project/f.ts

Whitespace-only changes.

packages/react-native-builder-bob/src/__fixtures__/project/index.ts

Whitespace-only changes.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { expect, it } from '@jest/globals';
2+
import { transformFileAsync } from '@babel/core';
3+
import fs from 'node:fs';
4+
import path from 'node:path';
5+
6+
it.each(['imports', 'exports'])(`adds .js extension to %s`, async (name) => {
7+
const filepath = path.resolve(
8+
__dirname,
9+
`../__fixtures__/project/code/$${name}-input.ts`
10+
);
11+
12+
const result = await transformFileAsync(filepath, {
13+
configFile: false,
14+
babelrc: false,
15+
plugins: [
16+
'@babel/plugin-syntax-typescript',
17+
[require.resolve('../babel.ts'), { extension: 'mjs' }],
18+
],
19+
});
20+
21+
const expected = await fs.promises.readFile(
22+
path.resolve(__dirname, `../__fixtures__/project/code/$${name}-output.ts`),
23+
'utf8'
24+
);
25+
26+
expect(result?.code).toEqual(expected.trim());
27+
});
28+
29+
it('replaces alias imports', async () => {
30+
const filepath = path.resolve(
31+
__dirname,
32+
`../__fixtures__/project/code/$alias-input.ts`
33+
);
34+
35+
const result = await transformFileAsync(filepath, {
36+
cwd: __dirname,
37+
configFile: false,
38+
babelrc: false,
39+
plugins: [
40+
'@babel/plugin-syntax-typescript',
41+
[
42+
require.resolve('../babel.ts'),
43+
{
44+
alias: {
45+
'@': '../__fixtures__/project',
46+
'file': '../__fixtures__/project/f',
47+
'something': 'another',
48+
},
49+
},
50+
],
51+
],
52+
});
53+
54+
const expected = await fs.promises.readFile(
55+
path.resolve(__dirname, `../__fixtures__/project/code/$alias-output.ts`),
56+
'utf8'
57+
);
58+
59+
expect(result?.code).toEqual(expected.trim());
60+
});
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import type { ConfigAPI, NodePath, PluginObj, PluginPass } from '@babel/core';
4+
import type {
5+
ImportDeclaration,
6+
ExportAllDeclaration,
7+
ExportNamedDeclaration,
8+
} from '@babel/types';
9+
10+
type Options = {
11+
alias?: Record<string, string>;
12+
extension?: 'cjs' | 'mjs';
13+
};
14+
15+
const isFile = (filename: string): boolean => {
16+
const exists =
17+
fs.lstatSync(filename, { throwIfNoEntry: false })?.isFile() ?? false;
18+
19+
return exists;
20+
};
21+
22+
const isDirectory = (filename: string): boolean => {
23+
const exists =
24+
fs.lstatSync(filename, { throwIfNoEntry: false })?.isDirectory() ?? false;
25+
26+
return exists;
27+
};
28+
29+
const isTypeImport = (
30+
node: ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration
31+
) =>
32+
('importKind' in node && node.importKind === 'type') ||
33+
('exportKind' in node && node.exportKind === 'type');
34+
35+
const assertFilename: (
36+
filename: string | null | undefined
37+
) => asserts filename is string = (filename) => {
38+
if (filename == null) {
39+
throw new Error("Couldn't find a filename for the current file.");
40+
}
41+
};
42+
43+
export default function (
44+
api: ConfigAPI,
45+
{ alias, extension }: Options
46+
): PluginObj {
47+
api.assertVersion(7);
48+
49+
function aliasImports(
50+
{
51+
node,
52+
}: NodePath<
53+
ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration
54+
>,
55+
state: PluginPass
56+
) {
57+
if (
58+
alias == null ||
59+
// Skip type imports as they'll be removed
60+
isTypeImport(node) ||
61+
// Skip imports without a source
62+
!node.source?.value
63+
) {
64+
return;
65+
}
66+
67+
assertFilename(state.filename);
68+
69+
const root = state.cwd;
70+
const source = node.source.value;
71+
72+
for (const [key, value] of Object.entries(alias)) {
73+
if (source === key || source.startsWith(`${key}/`)) {
74+
const resolved = value.startsWith('.')
75+
? path.relative(
76+
path.dirname(state.filename),
77+
path.resolve(root, value)
78+
)
79+
: value;
80+
81+
node.source.value = source.replace(key, resolved);
82+
return;
83+
}
84+
}
85+
}
86+
87+
function addExtension(
88+
{
89+
node,
90+
}: NodePath<
91+
ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration
92+
>,
93+
state: PluginPass
94+
) {
95+
if (
96+
extension == null ||
97+
// Skip type imports as they'll be removed
98+
isTypeImport(node) ||
99+
// Skip non-relative imports
100+
!node.source?.value.startsWith('.')
101+
) {
102+
return;
103+
}
104+
105+
assertFilename(state.filename);
106+
107+
// Skip folder imports
108+
const filename = path.resolve(
109+
path.dirname(state.filename),
110+
node.source.value
111+
);
112+
113+
// Add extension if .ts file or file with extension exists
114+
if (
115+
isFile(`${filename}.ts`) ||
116+
isFile(`${filename}.tsx`) ||
117+
isFile(`${filename}.${extension}`)
118+
) {
119+
node.source.value += `.${extension}`;
120+
return;
121+
}
122+
123+
// Replace .ts extension with .js if .ts file exists
124+
if (isFile(filename)) {
125+
node.source.value = node.source.value.replace(/\.tsx?$/, `.${extension}`);
126+
return;
127+
}
128+
129+
if (
130+
isDirectory(filename) &&
131+
(isFile(path.join(filename, 'index.ts')) ||
132+
isFile(path.join(filename, 'index.tsx')) ||
133+
isFile(path.join(filename, `index.${extension}`)))
134+
) {
135+
node.source.value = node.source.value.replace(
136+
/\/?$/,
137+
`/index.${extension}`
138+
);
139+
return;
140+
}
141+
}
142+
143+
return {
144+
name: '@builder-bob/babel-plugin',
145+
visitor: {
146+
ImportDeclaration(path, state) {
147+
aliasImports(path, state);
148+
addExtension(path, state);
149+
},
150+
ExportNamedDeclaration(path, state) {
151+
aliasImports(path, state);
152+
addExtension(path, state);
153+
},
154+
ExportAllDeclaration(path, state) {
155+
aliasImports(path, state);
156+
addExtension(path, state);
157+
},
158+
},
159+
};
160+
}

tsconfig.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,9 @@
3030
"target": "esnext",
3131
"verbatimModuleSyntax": true
3232
},
33-
"exclude": ["lib", "packages/create-react-native-library/templates"]
33+
"exclude": [
34+
"lib",
35+
"packages/react-native-builder-bob/src/__fixtures__",
36+
"packages/create-react-native-library/templates"
37+
]
3438
}

0 commit comments

Comments
 (0)