diff --git a/.changeset/nine-papayas-wish.md b/.changeset/nine-papayas-wish.md new file mode 100644 index 0000000..ee82119 --- /dev/null +++ b/.changeset/nine-papayas-wish.md @@ -0,0 +1,5 @@ +--- +"@effect/build-utils": patch +--- + +Added pack-v5 diff --git a/src/PackV5.ts b/src/PackV5.ts new file mode 100644 index 0000000..f37ef6b --- /dev/null +++ b/src/PackV5.ts @@ -0,0 +1,158 @@ +import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem" +import * as NodePath from "@effect/platform-node/NodePath" +import { FileSystem } from "@effect/platform/FileSystem" +import { Path } from "@effect/platform/Path" +import * as Effect from "effect/Effect" +import * as Layer from "effect/Layer" +import * as Record from "effect/Record" +import { FsUtils, FsUtilsLive } from "./FsUtils" +import type { PackageJson } from "./PackageContext" +import { PackageContext, PackageContextLive } from "./PackageContext" + +export const run = Effect.gen(function*() { + const fsUtils = yield* FsUtils + const fs = yield* FileSystem + const path = yield* Path + const ctx = yield* PackageContext + + const templates = yield* fsUtils.glob("src/**/.index.ts") + const entrypoints: Record = {} + yield* Effect.forEach( + templates, + Effect.fnUntraced(function*(template) { + const directory = path.dirname(template) + const files = (yield* fs.readDirectory(directory)).map((_) => + path.basename(_) + ) + .filter((path) => path.endsWith(".ts") && !path.startsWith(".")).sort(( + a, + b + ) => a.localeCompare(b)).map((file) => + path.relative( + "src", + path.join(directory, file) + ).replace(/\.ts$/, "") + ) + + for (const file of files) { + const isIndex = file.endsWith("index") + const stripped = isIndex ? file.slice(0, -6) : file + const withDot = stripped === "" ? "." : `./${stripped}` + entrypoints[withDot] = file + } + }), + { concurrency: "inherit", discard: true } + ) + + const buildPackageJson = Effect.sync(() => { + const out: Record = { + name: ctx.packageJson.name, + version: ctx.packageJson.version, + description: ctx.packageJson.description, + license: ctx.packageJson.license, + repository: ctx.packageJson.repository, + sideEffects: ctx.packageJson.sideEffects.map((_) => + _.replace(".ts", ".js").replace(".tsx", ".js").replace( + "/src/", + "/dist/" + ) + ) + } + + const addOptional = (key: keyof PackageJson) => { + if (ctx.packageJson[key]) { + out[key as string] = ctx.packageJson[key] + } + } + + addOptional("author") + addOptional("homepage") + addOptional("dependencies") + addOptional("peerDependencies") + addOptional("peerDependenciesMeta") + addOptional("optionalDependencies") + addOptional("gitHead") + addOptional("bin") + + if (ctx.packageJson.publishConfig?.provenance === true) { + out.publishConfig = { provenance: true } + } + + if ( + ctx.packageJson.publishConfig?.executableFiles !== undefined + && ctx.packageJson.publishConfig.executableFiles.length > 0 + ) { + out.publishConfig = { + ...out.publishConfig, + executableFiles: ctx.packageJson.publishConfig.executableFiles + } + } + + if (Object.keys(entrypoints).length > 0) { + const main = "." in entrypoints ? entrypoints["."] : undefined + + if (main !== undefined) { + out.main = `./dist/${main}.js` + out.types = `./dist/${main}.d.ts` + } + + out.exports = Record.fromEntries( + Object.entries(entrypoints).map(([entry, module]) => { + return [entry, { + types: `./dist/${module}.d.ts`, + default: `./dist/${module}.js` + }] + }) + ) + } + + return out + }) + + const writePackageJson = buildPackageJson.pipe( + Effect.map((_) => JSON.stringify(_, null, 2)), + Effect.flatMap((_) => fs.writeFileString("dist/package.json", _)), + Effect.withSpan("Pack-v5/buildPackageJson") + ) + + const mkDist = fsUtils.rmAndMkdir("dist") + const copyReadme = fs.copy("README.md", "dist/README.md") + const copyLicense = fs.copy("LICENSE", "dist/LICENSE") + + const copyDist = fsUtils.rmAndCopy("build", "dist/dist") + const copySrc = ctx.hasSrc + ? fsUtils.rmAndCopy("src", "dist/src").pipe( + Effect.zipRight( + fsUtils.glob("dist/src/**/.index.ts").pipe( + Effect.flatMap(Effect.forEach((_) => fs.remove(_))) + ) + ) + ) + : Effect.void + + const copySources = Effect.all([ + copyDist, + copySrc + ], { concurrency: "inherit", discard: true }).pipe( + Effect.withSpan("Pack-v5/copySources") + ) + + yield* mkDist + yield* Effect.all([ + writePackageJson, + copyReadme, + copyLicense, + copySources + ], { concurrency: "inherit", discard: true }).pipe( + Effect.withConcurrency(10) + ) +}).pipe( + Effect.provide( + Layer.mergeAll( + NodeFileSystem.layer, + NodePath.layerPosix, + FsUtilsLive, + PackageContextLive + ) + ) +) diff --git a/src/main.ts b/src/main.ts index fdc737d..81e6124 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,7 @@ import * as PackV1 from "./PackV1" import * as PackV2 from "./PackV2" import * as PackV3 from "./PackV3" import * as PackV4 from "./PackV4" +import * as PackV5 from "./PackV5" import * as PrepareV1 from "./PrepareV1" import * as PrepareV2 from "./PrepareV2" import * as PrepareV3 from "./PrepareV3" @@ -19,6 +20,7 @@ const run = Command.make("build-utils").pipe( Command.make("pack-v2", {}, () => PackV2.run), Command.make("pack-v3", {}, () => PackV3.run), Command.make("pack-v4", {}, () => PackV4.run), + Command.make("pack-v5", {}, () => PackV5.run), Command.make("prepare-v1", {}, () => PrepareV1.run), Command.make("prepare-v2", {}, () => PrepareV2.run), Command.make("prepare-v3", {}, () => PrepareV3.run),