Skip to content

Commit 4acbfe3

Browse files
authored
Update the build command to use tsc directly, pick targets based off package.json, and integrate codegen (#3926)
* add helper utilities for build command * move codegen helpers to utils folder * autodetect build outputs and integrate codegen native calls * change glob dep back to devDep in scripts * use node directly to execute to avoid slowdowns in cases where office yarn is enabled * update dynamic extensions with better logic * fix script execution using node * fix error handling in build command * fix align-deps error
1 parent 54087dc commit 4acbfe3

File tree

13 files changed

+660
-385
lines changed

13 files changed

+660
-385
lines changed

packages/framework/eslint-config-rules/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"license": "MIT",
1616
"dependencies": {
1717
"@microsoft/eslint-plugin-sdl": "^1.1.0",
18-
"@rnx-kit/eslint-plugin": "^0.4.0"
18+
"@rnx-kit/eslint-plugin": "^0.8.6"
1919
},
2020
"devDependencies": {
2121
"@types/eslint": "^9.0.0",

packages/utils/test-tools/package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
"version": "0.1.1",
44
"description": "Tools and mocks for testing components using jest",
55
"main": "lib-commonjs/index.js",
6-
"module": "src/index.ts",
6+
"module": "lib/index.js",
77
"typings": "lib/index.d.ts",
8+
"exports": {
9+
".": {
10+
"import": "./lib/index.js",
11+
"require": "./lib-commonjs/index.js"
12+
}
13+
},
814
"private": true,
915
"scripts": {
1016
"build": "fluentui-scripts build",

scripts/babel.config.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,2 @@
1-
module.exports = {
2-
presets: [
3-
['@babel/preset-env', { targets: { node: 'current' } }],
4-
'@babel/preset-react',
5-
'@babel/preset-typescript',
6-
['module:@react-native/babel-preset', { runtime: 'classic' }],
7-
],
8-
plugins: [
9-
['@babel/plugin-proposal-private-property-in-object', { loose: false }],
10-
['@babel/plugin-proposal-class-properties', { loose: false }],
11-
['@babel/plugin-transform-private-methods', { loose: false }],
12-
],
13-
};
1+
const { configureBabel } = require('./src/configs/configureBabel');
2+
module.exports = configureBabel();

scripts/dynamic.extensions.mjs

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,79 @@
1+
// @ts-check
2+
13
import fs from 'fs';
24
import path from 'path';
35
import { fileURLToPath } from 'url';
46

57
/**
6-
* @param {Object} workspace The package currently being processed
7-
* @param {string} workspace.cwd Path of the current package
8-
* @param {Object} workspace.manifest The content of `package.json`
9-
* @returns {{
10-
* dependencies?: Record<string, string>;
11-
* peerDependencies?: Record<string, string>;
12-
* peerDependenciesMeta?: Record<string, { optional?: boolean }>;
13-
* }}
8+
* @typedef {() => boolean} ConditionalCheck
149
*/
1510

1611
/**
17-
* These are the dependencies we want to ensure exist in each folder. They will not override
18-
* the dependencies in the package.json if already present.
12+
* Get the package.json manifest for a given folder.
13+
* @param {string} folder
14+
* @returns {import('@rnx-kit/tools-packages').PackageInfo['manifest']}
1915
*/
20-
const scriptDependencies = getScriptFolderDependencies(['typescript', 'eslint', 'just-scripts']);
16+
function getPackageManifest(folder) {
17+
const manifestPath = path.join(folder, 'package.json');
18+
return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
19+
}
20+
21+
// Get the versions once, so we don't query again on each package
22+
const scriptFolder = path.dirname(fileURLToPath(import.meta.url));
23+
const scriptManifest = getPackageManifest(scriptFolder);
24+
const rootManifest = getPackageManifest(path.dirname(scriptFolder));
25+
// all merged versions from the root and script manifests, scripts having precedence
26+
const baseVersions = {
27+
...rootManifest?.devDependencies,
28+
...rootManifest?.dependencies,
29+
...scriptManifest?.devDependencies,
30+
...scriptManifest?.dependencies,
31+
};
2132

2233
/**
23-
* Get the dependencies for the script folder, both `devDependencies` and `dependencies`
24-
* @param {string[]} keys - The keys of the dependencies to include
25-
* @returns {Record<string, string>} A map of dependencies for the script folder
34+
* Conditionally add a dependency to the given dependencies object if it is not already present
35+
* @param {string[]} depsToAdd
36+
* @param {import('@rnx-kit/tools-packages').PackageInfo['manifest']} manifest
37+
* @param {ConditionalCheck | boolean | undefined} condition
38+
* @returns {Record<string, string>}
2639
*/
27-
function getScriptFolderDependencies(keys) {
28-
const pkgJsonName = path.join(path.dirname(fileURLToPath(import.meta.url)), './package.json');
29-
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonName, 'utf-8'));
30-
const mergedDeps = { ...pkgJson.devDependencies, ...pkgJson.dependencies };
31-
return Object.fromEntries(Object.entries(mergedDeps).filter(([key]) => keys.includes(key)));
40+
function conditionallyAdd(depsToAdd, manifest, condition) {
41+
/** @type {Record<string, string>} */
42+
const newDeps = {};
43+
if (!condition || (typeof condition === 'function' ? condition() : condition)) {
44+
for (const dep of depsToAdd) {
45+
if (!manifest.dependencies?.[dep] && !manifest.devDependencies?.[dep]) {
46+
if (baseVersions[dep]) {
47+
// If the dependency is not already present, and the extra condition is met, add it
48+
newDeps[dep] = baseVersions[dep];
49+
} else {
50+
// If the dependency is not found in the base versions, log a warning
51+
console.warn(`Dependency ${dep} not found in base versions. Skipping dynamic add.`);
52+
}
53+
}
54+
}
55+
}
56+
return newDeps;
57+
}
58+
59+
function addPrettier(manifest) {
60+
return manifest && manifest.scripts && (manifest.scripts.prettier || manifest.scripts['prettier-fix']);
3261
}
3362

63+
/**
64+
* Get the dynamic dependencies for the given package given the package root directory and its manifest.
65+
* @param {{cwd: string, manifest: import('@rnx-kit/tools-packages').PackageInfo['manifest']}} param0
66+
* @returns { { dependencies: Record<string, string> } }
67+
*/
3468
export default function ({ cwd, manifest }) {
3569
const dependenciesToAdd = {};
36-
Object.keys(scriptDependencies).forEach((key) => {
37-
if ((manifest?.dependencies && manifest.dependencies[key]) || (manifest?.devDependencies && manifest.devDependencies[key])) {
38-
// If the dependency already exists in the package.json, skip it
39-
return;
40-
}
41-
dependenciesToAdd[key] = scriptDependencies[key];
42-
});
70+
const enableLinting = Boolean(manifest.scripts && manifest.scripts.lint);
71+
4372
return {
44-
dependencies: dependenciesToAdd,
73+
dependencies: {
74+
...conditionallyAdd(['typescript'], manifest, () => fs.existsSync(path.join(cwd, 'tsconfig.json'))),
75+
...conditionallyAdd(['eslint'], manifest, enableLinting),
76+
...conditionallyAdd(['prettier'], manifest, () => addPrettier(manifest)),
77+
},
4578
};
4679
}

scripts/package.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@
1818
"url": "https://github.com/microsoft/fluentui-react-native.git",
1919
"directory": "scripts"
2020
},
21-
"peerDependencies": {
22-
"just-scripts": "^2.3.2",
23-
"react": "18.2.0",
24-
"react-native": "^0.73.0 || ^0.74.0",
25-
"react-native-svg": "^15.0.0 || ^15.4.0"
26-
},
2721
"devDependencies": {
22+
"@babel/core": "^7.22.5",
23+
"@babel/plugin-proposal-class-properties": "^7.18.6",
24+
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
25+
"@babel/plugin-transform-private-methods": "^7.27.1",
2826
"@react-native-community/cli": "^13.6.4",
2927
"@react-native-community/cli-platform-android": "^13.6.4",
3028
"@react-native-community/cli-platform-ios": "^13.6.4",
3129
"@react-native/metro-babel-transformer": "^0.74.0",
3230
"@react-native/metro-config": "^0.74.0",
3331
"@rnx-kit/jest-preset": "^0.2.0",
32+
"@rnx-kit/tools-packages": "^0.1.1",
33+
"@rnx-kit/tools-typescript": "^0.1.1",
3434
"@types/es6-collections": "^0.5.29",
3535
"@types/es6-promise": "0.0.32",
3636
"@types/jest": "^29.0.0",
@@ -40,6 +40,7 @@
4040
"depcheck": "^1.0.0",
4141
"find-up": "^5.0.0",
4242
"fs-extra": "^7.0.1",
43+
"glob": "^10.0.0",
4344
"jest": "^29.2.1",
4445
"jest-diff": "^27.0.0",
4546
"jsdom": "^25.0.0",
@@ -94,5 +95,10 @@
9495
"svg"
9596
]
9697
}
98+
},
99+
"peerDependencies": {
100+
"react": "18.2.0",
101+
"react-native": "^0.73.0 || ^0.74.0",
102+
"react-native-svg": "^15.0.0 || ^15.4.0"
97103
}
98104
}

scripts/src/configs/configureBabel.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/** @typedef {{ esmodule?: boolean, estarget?: string, jsxRuntime?: boolean }} BabelConfigOptions */
2+
3+
/**
4+
* @param {BabelConfigOptions} options
5+
* @param {import('@babel/core').TransformOptions} [mixin] - Additional Babel configuration options to mix in.
6+
* @returns {import('@babel/core').TransformOptions} - The complete Babel configuration object.
7+
*/
8+
module.exports.configureBabel = function (/** @type {BabelConfigOptions} */ options = {}, mixin = {}) {
9+
const { esmodule, estarget, jsxRuntime } = options;
10+
return {
11+
presets: [
12+
[
13+
'@babel/preset-env',
14+
{
15+
modules: esmodule ? false : 'auto',
16+
targets: { node: 'current' },
17+
},
18+
],
19+
'@babel/preset-react',
20+
'@babel/preset-typescript',
21+
['module:@react-native/babel-preset', { runtime: jsxRuntime ? 'automatic' : 'classic' }],
22+
],
23+
plugins: [
24+
['@babel/plugin-proposal-private-property-in-object', { loose: false }],
25+
['@babel/plugin-proposal-class-properties', { loose: false }],
26+
['@babel/plugin-transform-private-methods', { loose: false }],
27+
],
28+
...mixin,
29+
};
30+
};

scripts/src/justPreset.ts

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ const fs = require('fs');
88
const { clean } = require('./tasks/clean');
99
const { copy } = require('./tasks/copy');
1010
const { jest } = require('./tasks/jest');
11-
const { ts } = require('./tasks/ts');
12-
const { codegenNativeComponents } = require('./tasks/codegenNativeComponents')
11+
const { build } = require('./tasks/build');
1312
const { eslint } = require('./tasks/eslint');
1413
const { depcheckTask } = require('./tasks/depcheck');
1514
const { checkForModifiedFiles } = require('./tasks/checkForModifiedFilesTask');
@@ -33,25 +32,14 @@ export function preset() {
3332
task('clean', clean);
3433
task('copy', copy);
3534
task('jest', jest);
36-
task('codegenNativeComponents', codegenNativeComponents);
37-
task('ts:commonjs', ts.commonjs);
38-
task('ts:esm', ts.esm);
35+
task('ts', build);
3936
task('eslint', eslint);
40-
task('ts:commonjs-only', ts.commonjsOnly);
4137
task('prettier', () =>
4238
argv().fix
4339
? prettierTask({ files: ['src/.'], ignorePath: path.join(findGitRoot(process.cwd()), '.prettierignore') })
4440
: prettierCheckTask({ files: ['src/.'], ignorePath: path.join(findGitRoot(process.cwd()), '.prettierignore') }),
4541
);
4642
task('checkForModifiedFiles', checkForModifiedFiles);
47-
task('tsall', parallel('ts:commonjs', 'ts:esm'));
48-
task(
49-
'ts',
50-
series(
51-
condition('ts:commonjs-only', () => !!argv().commonjs),
52-
condition('tsall', () => !argv().commonjs),
53-
),
54-
);
5543

5644
task(
5745
'validate',
@@ -61,19 +49,7 @@ export function preset() {
6149
),
6250
);
6351

64-
task(
65-
'build:node-lib',
66-
series(
67-
'clean',
68-
'copy',
69-
series(
70-
condition('validate', () => !argv().min),
71-
'ts:commonjs-only',
72-
),
73-
),
74-
);
75-
76-
task('build', series('clean', 'copy', 'ts', 'codegenNativeComponents'));
52+
task('build', series('clean', 'copy', 'ts'));
7753

7854
task('depcheck', depcheckTask);
7955

0 commit comments

Comments
 (0)