Skip to content
Draft
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
2 changes: 0 additions & 2 deletions build-tools/packages/build-tools/bin/fluid-build

This file was deleted.

2 changes: 2 additions & 0 deletions build-tools/packages/build-tools/bin/fluid-build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
import "../dist/fluidBuild/fluidBuild.js";
2 changes: 0 additions & 2 deletions build-tools/packages/build-tools/bin/fluid-doc-stats

This file was deleted.

2 changes: 2 additions & 0 deletions build-tools/packages/build-tools/bin/fluid-doc-stats.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
import "../dist/docStats/docStats.js";
2 changes: 0 additions & 2 deletions build-tools/packages/build-tools/bin/fluid-tsc

This file was deleted.

2 changes: 2 additions & 0 deletions build-tools/packages/build-tools/bin/fluid-tsc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
import "../dist/fluidBuild/fluidTsc/fluidTsc.js";
19 changes: 16 additions & 3 deletions build-tools/packages/build-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,25 @@
},
"license": "MIT",
"author": "Microsoft and contributors",
"type": "module",
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/common/typeCompatibility.d.cts",
"default": "./dist/common/typeCompatibility.cjs"
}
}
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"bin": {
"fluid-build": "bin/fluid-build",
"fluid-doc-stats": "bin/fluid-doc-stats",
"fluid-tsc": "bin/fluid-tsc"
"fluid-build": "bin/fluid-build.mjs",
"fluid-doc-stats": "bin/fluid-doc-stats.mjs",
"fluid-tsc": "bin/fluid-tsc.mjs"
},
"scripts": {
"build": "fluid-build --task build",
Expand Down
6 changes: 3 additions & 3 deletions build-tools/packages/build-tools/src/common/biome2Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import multimatch from "multimatch";
import { merge } from "ts-deepmerge";
import type { Opaque } from "type-fest";

import type { Configuration as Biome2ConfigRaw } from "./biome2ConfigTypes";
import { getClosestBiomeConfigPath, loadRawBiomeConfigFile } from "./biomeConfigUtils";
import type { GitRepo } from "./gitRepo";
import type { Configuration as Biome2ConfigRaw } from "./biome2ConfigTypes.js";
import { getClosestBiomeConfigPath, loadRawBiomeConfigFile } from "./biomeConfigUtils.js";
import type { GitRepo } from "./gitRepo.js";

/**
* Convenience type to represent a Biome 2.x config that has been loaded while following and merging the
Expand Down
6 changes: 3 additions & 3 deletions build-tools/packages/build-tools/src/common/biomeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { merge } from "ts-deepmerge";
// Opaque is deprecated in newer type-fest versions (replaced by Tagged); we pin type-fest 2.x for current CommonJS
import type { Opaque } from "type-fest";

import type { Configuration as BiomeConfigRaw } from "./biomeConfigTypes";
import { getClosestBiomeConfigPath, loadRawBiomeConfigFile } from "./biomeConfigUtils";
import type { GitRepo } from "./gitRepo";
import type { Configuration as BiomeConfigRaw } from "./biomeConfigTypes.js";
import { getClosestBiomeConfigPath, loadRawBiomeConfigFile } from "./biomeConfigUtils.js";
import type { GitRepo } from "./gitRepo.js";

/**
* Convenience type to represent a Biome config that has been loaded while following and merging the
Expand Down
23 changes: 8 additions & 15 deletions build-tools/packages/build-tools/src/common/biomeConfigUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@
*/

import { readFile } from "node:fs/promises";
import * as JSON5 from "json5";
import { findUp } from "find-up";
import JSON5 from "json5";

import type { GitRepo } from "./gitRepo";

// find-up is an ESM-only package and we're still building CJS, so this import form is required
// so that TypeScript won't transpile it to require(). Once this package is switched to ESM, then
// this can be a standard import.
const findUp = import("find-up");
import type { GitRepo } from "./gitRepo.js";

/**
* Minimal interface for a Biome configuration that includes the extends field.
Expand Down Expand Up @@ -53,14 +49,11 @@ export async function getClosestBiomeConfigPath(
cwd: string,
stopAt?: string,
): Promise<string> {
return (await findUp)
.findUp(["biome.json", "biome.jsonc"], { cwd, stopAt })
.then((config) => {
if (config === undefined) {
throw new Error(`Can't find biome config file`);
}
return config;
});
const config = await findUp(["biome.json", "biome.jsonc"], { cwd, stopAt });
if (config === undefined) {
throw new Error(`Can't find biome config file`);
}
return config;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion build-tools/packages/build-tools/src/common/gitRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { parseISO } from "date-fns";
import registerDebug from "debug";
import { exec, execNoError } from "./utils";
import { exec, execNoError } from "./utils.js";

const traceGitRepo = registerDebug("fluid-build:gitRepo");

Expand Down
2 changes: 1 addition & 1 deletion build-tools/packages/build-tools/src/common/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import chalk from "picocolors";

import { commonOptions } from "../fluidBuild/commonOptions";
import { commonOptions } from "../fluidBuild/commonOptions.js";

/**
* A function that logs an Error or error message.
Expand Down
13 changes: 8 additions & 5 deletions build-tools/packages/build-tools/src/common/monoRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
import { existsSync } from "node:fs";
import * as path from "node:path";
import { getPackagesSync } from "@manypkg/get-packages";
import { readFileSync, readJsonSync } from "fs-extra";
import fsExtra from "fs-extra";
import YAML from "yaml";

import type { IFluidBuildDir } from "../fluidBuild/fluidBuildConfig";
import { type Logger, defaultLogger } from "./logging";
import { Package } from "./npmPackage";
import { execWithErrorAsync, rimrafWithErrorAsync } from "./utils";
// fs-extra doesn't provide named exports for ESM, so we destructure from default
const { readFileSync, readJsonSync } = fsExtra;

import type { IFluidBuildDir } from "../fluidBuild/fluidBuildConfig.js";
import { type Logger, defaultLogger } from "./logging.js";
import { Package } from "./npmPackage.js";
import { execWithErrorAsync, rimrafWithErrorAsync } from "./utils.js";

import registerDebug from "debug";
const traceInit = registerDebug("fluid-build:init");
Expand Down
17 changes: 10 additions & 7 deletions build-tools/packages/build-tools/src/common/npmPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,27 @@ import { existsSync, readFileSync, readdirSync } from "node:fs";
import * as path from "node:path";
import { queue } from "async";
import detectIndent from "detect-indent";
import { readJsonSync, writeJsonSync } from "fs-extra";
import fsExtra from "fs-extra";
import chalk from "picocolors";
import sortPackageJson from "sort-package-json";

// fs-extra doesn't provide named exports for ESM, so we destructure from default
const { readJsonSync, writeJsonSync } = fsExtra;

import type { SetRequired, PackageJson as StandardPackageJson } from "type-fest";

import type { IFluidBuildConfig } from "../fluidBuild/fluidBuildConfig";
import type { IFluidCompatibilityMetadata } from "../fluidBuild/fluidCompatMetadata";
import { options } from "../fluidBuild/options";
import { defaultLogger } from "./logging";
import type { MonoRepo, PackageManager } from "./monoRepo";
import type { IFluidBuildConfig } from "../fluidBuild/fluidBuildConfig.js";
import type { IFluidCompatibilityMetadata } from "../fluidBuild/fluidCompatMetadata.js";
import { options } from "../fluidBuild/options.js";
import { defaultLogger } from "./logging.js";
import type { MonoRepo, PackageManager } from "./monoRepo.js";
import {
type ExecAsyncResult,
execWithErrorAsync,
isSameFileOrDir,
lookUpDirSync,
rimrafWithErrorAsync,
} from "./utils";
} from "./utils.js";

import registerDebug from "debug";
const traceInit = registerDebug("fluid-build:init");
Expand Down
2 changes: 1 addition & 1 deletion build-tools/packages/build-tools/src/common/timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License.
*/

import { defaultLogger } from "./logging";
import { defaultLogger } from "./logging.js";

const { log } = defaultLogger;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,67 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

/**
* The types defined here cannot be in build-cli because it is an ESM-only package, and these types are imported in
* packages that are dual-emit or CJS-only. Long term these types should move to a shared library between build-cli and
* build-tools.
* Type compatibility utilities for generated type tests.
*
* ## Why this file is .cts (CommonJS TypeScript)
*
* This file uses the `.cts` extension to produce CommonJS output (`.cjs` and `.d.cts`) even though
* the `@fluidframework/build-tools` package is ESM-only (`"type": "module"` in package.json).
*
* ### The Problem
*
* The generated type test files (e.g., `validateFooPrevious.generated.ts`) import these type utilities:
*
* ```ts
* import type { TypeOnly, MinimalType, FullType, requireAssignableTo } from "@fluidframework/build-tools";
* ```
*
* These test files are compiled twice: once as ESM (to `lib/`) and once as CJS (to `dist/`).
* When TypeScript compiles them as CJS, it validates that `require()` calls would succeed at runtime.
* Since `@fluidframework/build-tools` is ESM-only, TypeScript throws TS1479:
*
* > "The current file is a CommonJS module whose imports will produce 'require' calls;
* > however, the referenced file is an ECMAScript module and cannot be imported with 'require'."
*
* ### The Solution
*
* By placing these types in a `.cts` file, TypeScript compiles them to:
* - `typeCompatibility.cjs` - CommonJS JavaScript output
* - `typeCompatibility.d.cts` - CommonJS type declarations
*
* The package.json exports are configured with conditional exports:
*
* ```json
* "exports": {
* ".": {
* "import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
* "require": { "types": "./dist/common/typeCompatibility.d.cts", "default": "./dist/common/typeCompatibility.cjs" }
* }
* }
* ```
*
* ### Why This Works (Type-Only Imports)
*
* This workaround ONLY works because the consuming code uses `import type`:
*
* ```ts
* import type { TypeOnly, ... } from "@fluidframework/build-tools";
* ```
*
* Type-only imports are erased during compilation - they produce NO runtime code. This means:
*
* 1. TypeScript sees the `require` condition in exports and finds valid CJS types (`.d.cts`)
* 2. TypeScript is satisfied that the import COULD work at runtime (even though it won't be called)
* 3. The compiled output contains no actual `require("@fluidframework/build-tools")` call
*
* If any consuming code tried to use a VALUE export (not just types) from the CJS entry point,
* it would fail at runtime because the `.cjs` file doesn't actually export the full package API.
*
* ### Important Constraints
*
* - Only TYPE exports are available via the CJS entry point
* - Runtime/value exports are only available via ESM (`import` from ESM contexts)
* - Consumers must use `import type` (not `import`) when importing from CJS contexts
*/

/**
Expand Down
2 changes: 1 addition & 1 deletion build-tools/packages/build-tools/src/common/typeTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import path from "node:path";
import type { Package } from "./npmPackage";
import type { Package } from "./npmPackage.js";

/**
* Given a package, returns the name that should be used for the previous version of the package to generate type tests.
Expand Down
4 changes: 4 additions & 0 deletions build-tools/packages/build-tools/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

import * as child_process from "child_process";
import * as fs from "fs";
import { fileURLToPath } from "node:url";
import * as path from "path";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import isEqual from "lodash.isequal";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* Licensed under the MIT License.
*/

import type { GitRepo } from "../common/gitRepo";
import type { IFluidBuildConfig } from "./fluidBuildConfig";
import type { GitRepo } from "../common/gitRepo.js";
import type { IFluidBuildConfig } from "./fluidBuildConfig.js";

/**
* A context object that is passed to fluid-build tasks. It is used to provide easy access to commonly-needed metadata
Expand Down
26 changes: 13 additions & 13 deletions build-tools/packages/build-tools/src/fluidBuild/buildGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import * as semver from "semver";

import * as assert from "assert";
import registerDebug from "debug";
import type { GitRepo } from "../common/gitRepo";
import { defaultLogger } from "../common/logging";
import type { Package } from "../common/npmPackage";
import type { Timer } from "../common/timer";
import type { BuildContext } from "./buildContext";
import { BuildResult, summarizeBuildResult } from "./buildResult";
import { FileHashCache } from "./fileHashCache";
import type { IFluidBuildConfig } from "./fluidBuildConfig";
import type { GitRepo } from "../common/gitRepo.js";
import { defaultLogger } from "../common/logging.js";
import type { Package } from "../common/npmPackage.js";
import type { Timer } from "../common/timer.js";
import type { BuildContext } from "./buildContext.js";
import { BuildResult, summarizeBuildResult } from "./buildResult.js";
import { FileHashCache } from "./fileHashCache.js";
import type { IFluidBuildConfig } from "./fluidBuildConfig.js";
import {
type TaskDefinition,
type TaskDefinitions,
Expand All @@ -26,11 +26,11 @@ import {
getDefaultTaskDefinition,
getTaskDefinitions,
normalizeGlobalTaskDefinitions,
} from "./fluidTaskDefinitions";
import { options } from "./options";
import { Task, type TaskExec } from "./tasks/task";
import { TaskFactory } from "./tasks/taskFactory";
import { WorkerPool } from "./tasks/workers/workerPool";
} from "./fluidTaskDefinitions.js";
import { options } from "./options.js";
import { Task, type TaskExec } from "./tasks/task.js";
import { TaskFactory } from "./tasks/taskFactory.js";
import { WorkerPool } from "./tasks/workers/workerPool.js";

const traceTaskDef = registerDebug("fluid-build:task:definition");
const traceTaskDepTask = registerDebug("fluid-build:task:init:dep:task");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { readFile } from "fs/promises";
import { sha256 } from "./hash";
import { sha256 } from "./hash.js";

type hashFn = (buffer: Buffer) => string;
export class FileHashCache {
Expand Down
20 changes: 10 additions & 10 deletions build-tools/packages/build-tools/src/fluidBuild/fluidBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
import chalk from "picocolors";
import { Spinner } from "picospinner";

import { GitRepo } from "../common/gitRepo";
import { defaultLogger } from "../common/logging";
import { Timer } from "../common/timer";
import { type BuildGraph } from "./buildGraph";
import { BuildResult } from "./buildResult";
import { commonOptions } from "./commonOptions";
import { DEFAULT_FLUIDBUILD_CONFIG } from "./fluidBuildConfig";
import { FluidRepoBuild } from "./fluidRepoBuild";
import { getFluidBuildConfig, getResolvedFluidRoot } from "./fluidUtils";
import { options, parseOptions } from "./options";
import { GitRepo } from "../common/gitRepo.js";
import { defaultLogger } from "../common/logging.js";
import { Timer } from "../common/timer.js";
import { type BuildGraph } from "./buildGraph.js";
import { BuildResult } from "./buildResult.js";
import { commonOptions } from "./commonOptions.js";
import { DEFAULT_FLUIDBUILD_CONFIG } from "./fluidBuildConfig.js";
import { FluidRepoBuild } from "./fluidRepoBuild.js";
import { getFluidBuildConfig, getResolvedFluidRoot } from "./fluidUtils.js";
import { options, parseOptions } from "./options.js";

const { log, errorLog: error, warning: warn } = defaultLogger;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import type { InterdependencyRange } from "@fluid-tools/version-tools";
import type { TaskDefinitionsOnDisk, TaskFileDependencies } from "./fluidTaskDefinitions";
import type { TaskDefinitionsOnDisk, TaskFileDependencies } from "./fluidTaskDefinitions.js";

/**
* The version of the fluidBuild configuration currently used.
Expand Down
Loading
Loading