Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Map clpx extension to the clipchamp filetype icon",
"packageName": "@fluentui/react-file-type-icons",
"email": "danielhall@microsoft.com",
"dependentChangeType": "patch"
}
6 changes: 6 additions & 0 deletions monosize.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const config = {
'react-dom': 'ReactDOM',
'react/compiler-runtime': 'ReactCompilerRuntime',
};
// ESM-first packages emit bare subpath imports (e.g. `use-sync-external-store/shim`) that lack
// a file extension. Once measured packages are `type: module`, webpack treats their `lib/` as
// ESM and enforces fully-specified imports; disable that so legacy CJS deps still resolve.
config.module = config.module ?? {};
config.module.rules = config.module.rules ?? [];
config.module.rules.push({ test: /\.[cm]?js$/, resolve: { fullySpecified: false } });
return config;
}),
reportResolvers: {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"devDependencies": {
"@actions/core": "1.9.1",
"@actions/github": "5.0.3",
"@arethetypeswrong/cli": "0.18.3",
"@babel/core": "7.29.6",
"@babel/generator": "7.29.1",
"@babel/parser": "7.29.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-file-type-icons/src/FileTypeIconMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const FileTypeIconMap: { [key: string]: { extensions?: string[] } } = {
extensions: ['classifier'],
},
clipchamp: {
extensions: ['clipchamp'],
extensions: ['clipchamp', 'clpx'],
},
cliptemplate: {
extensions: ['cliptemplate'],
Expand Down
34 changes: 19 additions & 15 deletions scripts/monorepo/src/getDependencies.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@ describe(`#getDependencies`, () => {
it(`should return package/s dependency tree array for all,devDeps and production dependencies`, async () => {
const deps = await getDependencies(packageName);

expect(deps.dependencies).toMatchInlineSnapshot(`
// graph traversal order is not deterministic across machines; sort by name for a stable snapshot
/** @type {(a: { name: string }, b: { name: string }) => number} */
const byName = (a, b) => a.name.localeCompare(b.name);

expect([...deps.dependencies].sort(byName)).toMatchInlineSnapshot(`
Array [
Object {
"dependencyType": "dependencies",
"isTopLevel": false,
"name": "keyboard-keys",
},
Object {
"dependencyType": "dependencies",
"isTopLevel": true,
Expand All @@ -37,35 +46,30 @@ describe(`#getDependencies`, () => {
"isTopLevel": false,
"name": "tokens",
},
Object {
"dependencyType": "dependencies",
"isTopLevel": false,
"name": "keyboard-keys",
},
]
`);

expect(deps.devDependencies).toMatchInlineSnapshot(`
expect([...deps.devDependencies].sort(byName)).toMatchInlineSnapshot(`
Array [
Object {
"dependencyType": "devDependencies",
"isTopLevel": true,
"name": "react-conformance",
"isTopLevel": false,
"name": "eslint-plugin",
},
Object {
"dependencyType": "devDependencies",
"isTopLevel": true,
"name": "react-conformance-griffel",
"isTopLevel": false,
"name": "eslint-plugin-react-components",
},
Object {
"dependencyType": "devDependencies",
"isTopLevel": false,
"name": "eslint-plugin",
"isTopLevel": true,
"name": "react-conformance",
},
Object {
"dependencyType": "devDependencies",
"isTopLevel": false,
"name": "eslint-plugin-react-components",
"isTopLevel": true,
"name": "react-conformance-griffel",
},
Object {
"dependencyType": "devDependencies",
Expand Down
35 changes: 35 additions & 0 deletions tools/workspace-plugin/src/plugins/workspace-plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,41 @@ describe(`workspace-plugin`, () => {
expect(getTargetsNames(results)).toEqual(['clean', 'format', 'type-check']);
});

it('should add the test target when a jest.config.cjs (type:module) exists', async () => {
await tempFs.createFiles({
'proj/project.json': serializeJson({}),
'proj/package.json': serializeJson({ type: 'module' }),
'proj/jest.config.cjs': 'module.exports = {}',
});
const results = await createNodesFunction(['proj/project.json'], options, context);

expect(getTargetsNames(results)).toContain('test');
});

it('should add an optional attw target only when package.json declares exports and is not private', async () => {
await tempFs.createFiles({
'with-exports/project.json': serializeJson({ projectType: 'library', tags: ['vNext'] }),
'with-exports/package.json': serializeJson({ exports: { '.': './lib/index.js' } }),
'no-exports/project.json': serializeJson({ projectType: 'library', tags: ['vNext'] }),
'no-exports/package.json': serializeJson({}),
'private-with-exports/project.json': serializeJson({ projectType: 'library', tags: ['vNext'] }),
'private-with-exports/package.json': serializeJson({ private: true, exports: { '.': './lib/index.js' } }),
});

const withExports = await createNodesFunction(['with-exports/project.json'], options, context);
const noExports = await createNodesFunction(['no-exports/project.json'], options, context);
const privateWithExports = await createNodesFunction(['private-with-exports/project.json'], options, context);

expect(getTargetsNames(withExports, 'with-exports')).toContain('attw');
expect(getTargets(withExports, 'with-exports')?.attw).toMatchObject({
executor: 'nx:run-commands',
dependsOn: ['build'],
options: { cwd: 'with-exports', command: expect.stringContaining('attw --pack --profile node16') },
});
expect(getTargetsNames(noExports, 'no-exports')).not.toContain('attw');
expect(getTargetsNames(privateWithExports, 'private-with-exports')).not.toContain('attw');
});

it('should add lint,test task only if configuration exists', async () => {
await tempFs.createFiles({
'proj/project.json': serializeJson({}),
Expand Down
47 changes: 42 additions & 5 deletions tools/workspace-plugin/src/plugins/workspace-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ function buildWorkspaceProjectConfiguration(
targets[options.verifyPackaging.targetName] = verifyPackagingTarget;
}

const attwTarget = buildAttwTarget(projectRoot, config);
if (attwTarget) {
targets.attw = attwTarget;
}

let metadata: WorkspaceTargets['metadata'];

if (isReactProject) {
Expand Down Expand Up @@ -412,7 +417,11 @@ function buildTestTarget(
context: CreateNodesContextV2,
config: TaskBuilderConfig,
): TargetConfiguration<JestConfig.InitialOptions & Pick<RunCommandsOptions, 'cwd'>> | null {
if (!existsSync(join(projectRoot, 'jest.config.js')) && !existsSync(join(projectRoot, 'jest.config.ts'))) {
if (
!existsSync(join(projectRoot, 'jest.config.js')) &&
!existsSync(join(projectRoot, 'jest.config.cjs')) &&
!existsSync(join(projectRoot, 'jest.config.ts'))
) {
return null;
}

Expand All @@ -437,6 +446,28 @@ function buildTestTarget(
};
}

function buildAttwTarget(projectRoot: string, config: TaskBuilderConfig): TargetConfiguration | null {
// optional, published-library-only types/exports validation. Not part of `build` or CI gates.
if (config.packageJSON.private || !config.packageJSON.exports) {
return null;
}

return {
executor: 'nx:run-commands',
cache: true,
dependsOn: ['build'],
options: {
cwd: projectRoot,
command: `${config.pmc.exec} attw --pack --profile node16`,
},
inputs: ['default', { externalDependencies: ['@arethetypeswrong/cli'] }],
metadata: {
description: 'Validate package types & export map with @arethetypeswrong/cli (optional)',
technologies: ['typescript'],
},
};
}

function buildLintTarget(
projectRoot: string,
options: Required<WorkspacePluginOptions>,
Expand Down Expand Up @@ -875,16 +906,22 @@ function buildReactIntegrationTesterProjectConfiguration(
hasTypeCheck: storybookAdjacent || libraryWithStoriesAdj,
hasE2E: existsSync(join(projectRootPath, 'cypress.config.ts')) && !storybookAdjacent,
hasTest:
(existsSync(join(projectRootPath, 'jest.config.js')) || existsSync(join(projectRootPath, 'jest.config.ts'))) &&
(existsSync(join(projectRootPath, 'jest.config.js')) ||
existsSync(join(projectRootPath, 'jest.config.cjs')) ||
existsSync(join(projectRootPath, 'jest.config.ts'))) &&
!storybookAdjacent,
};

const ritConfigPathLocal = join(projectRootPath, 'rit.config.js');
// web packages ship as `type: module`, so their CommonJS rit config uses `.cjs`; fall back to `.js`
const ritConfigPathLocal = [
resolve(projectRootPath, 'rit.config.cjs'),
resolve(projectRootPath, 'rit.config.js'),
].find(candidate => existsSync(candidate));

if (existsSync(ritConfigPathLocal)) {
if (ritConfigPathLocal) {
try {
type RITConfig = { react: Record<string, { runConfig?: Record<string, { configPath: string }> }> };
const loaded = require(resolve(projectRootPath, 'rit.config.js'));
const loaded = require(ritConfigPathLocal);
const rit: RITConfig = loaded?.default ?? loaded;

if (rit && typeof rit === 'object' && rit.react && rit.react[reactVersion]) {
Expand Down
Loading
Loading