diff --git a/packages/infrastructure/lens-link/src/check-for-missing-package-jsons.injectable.ts b/packages/infrastructure/lens-link/src/check-for-missing-package-jsons.injectable.ts new file mode 100644 index 0000000000..cf96c13571 --- /dev/null +++ b/packages/infrastructure/lens-link/src/check-for-missing-package-jsons.injectable.ts @@ -0,0 +1,22 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { getMissingPackageJsonsInjectable } from "./get-missing-package-jsons.injectable"; + +export const checkForMissingPackageJsonsInjectable = getInjectable({ + id: "check-for-missing-package-jsons", + + instantiate: (di) => { + const getMissingPackageJsons = di.inject(getMissingPackageJsonsInjectable); + + return async (packageJsonPaths: string[]) => { + const missingPackageJsons = await getMissingPackageJsons(packageJsonPaths); + + if (missingPackageJsons.length) { + throw new Error( + `Tried to install Lens links, but configured package.jsons were not found: "${missingPackageJsons.join( + '", "', + )}".`, + ); + } + }; + }, +}); diff --git a/packages/infrastructure/lens-link/src/create-sym-links.injectable.ts b/packages/infrastructure/lens-link/src/create-sym-links.injectable.ts new file mode 100644 index 0000000000..6c86958934 --- /dev/null +++ b/packages/infrastructure/lens-link/src/create-sym-links.injectable.ts @@ -0,0 +1,21 @@ +import { map } from "lodash/fp"; +import { awaitAll } from "./await-all"; +import { getInjectable } from "@ogre-tools/injectable"; +import { pipeline } from "@ogre-tools/fp"; +import { createSymlinkInjectable } from "./fs/create-symlink.injectable"; + +export const createSymLinksInjectable = getInjectable({ + id: "create-sym-links", + + instantiate: (di) => { + const createSymlink = di.inject(createSymlinkInjectable); + + return async (symlinkPaths: { target: string; source: string; type: "file" | "dir" }[]) => { + await pipeline( + symlinkPaths, + map(({ target, source, type }) => createSymlink(target, source, type)), + awaitAll, + ); + }; + }, +}); diff --git a/packages/infrastructure/lens-link/src/get-symlink-paths.injectable.ts b/packages/infrastructure/lens-link/src/get-symlink-paths.injectable.ts new file mode 100644 index 0000000000..8184b078e0 --- /dev/null +++ b/packages/infrastructure/lens-link/src/get-symlink-paths.injectable.ts @@ -0,0 +1,69 @@ +import type { PackageJsonAndPath } from "./package-json-and-path"; +import { globInjectable } from "./fs/glob.injectable"; +import { resolvePathInjectable } from "./path/resolve-path.injectable"; +import { awaitAll } from "./await-all"; +import { flatten, map, partition } from "lodash/fp"; +import { getInjectable } from "@ogre-tools/injectable"; +import { pipeline } from "@ogre-tools/fp"; +import { getLensLinkDirectoryInjectable } from "./get-lens-link-directory.injectable"; +import path from "path"; + +const shouldBeGlobbed = (possibleGlobString: string) => possibleGlobString.includes("*"); +const simplifyGlobbing = new RegExp("(\\/\\*\\/\\*\\*|\\/\\*\\*|\\/\\*\\*\\/\\*|\\/\\*)$"); +const toAvoidableGlobStrings = (reference: string) => reference.replace(simplifyGlobbing, ""); + +export const getSymlinkPathsInjectable = getInjectable({ + id: "get-symlink-paths", + + instantiate: (di) => { + const glob = di.inject(globInjectable); + const resolvePath = di.inject(resolvePathInjectable); + const getLensLinkDirectory = di.inject(getLensLinkDirectoryInjectable); + + return async (packageJsons: PackageJsonAndPath[]) => { + return pipeline( + packageJsons, + + map(async ({ packageJsonPath, content }) => { + const lensLinkDirectory = getLensLinkDirectory(content.name); + + const fileStrings = content.files.map(toAvoidableGlobStrings); + + const [toBeGlobbed, toNotBeGlobbed] = partition(shouldBeGlobbed)(fileStrings); + + const moduleDirectory = path.dirname(packageJsonPath); + + let globbeds: string[] = []; + + if (toBeGlobbed.length) { + globbeds = await glob(toBeGlobbed, { cwd: moduleDirectory }); + } + + return [ + { + target: packageJsonPath, + source: resolvePath(lensLinkDirectory, "package.json"), + type: "file" as const, + }, + + ...globbeds.map((fileString) => ({ + target: resolvePath(moduleDirectory, fileString), + source: resolvePath(lensLinkDirectory, fileString), + type: "file" as const, + })), + + ...toNotBeGlobbed.map((fileOrDirectory) => ({ + target: resolvePath(moduleDirectory, fileOrDirectory), + source: resolvePath(lensLinkDirectory, fileOrDirectory), + type: "dir" as const, + })), + ]; + }), + + awaitAll, + + flatten, + ); + }; + }, +}); diff --git a/packages/infrastructure/lens-link/src/lens-link.injectable.ts b/packages/infrastructure/lens-link/src/lens-link.injectable.ts index ac50127b5e..27fdd1da10 100644 --- a/packages/infrastructure/lens-link/src/lens-link.injectable.ts +++ b/packages/infrastructure/lens-link/src/lens-link.injectable.ts @@ -1,45 +1,33 @@ -import { partition } from "lodash/fp"; -import { dirname } from "path"; -import { pipeline } from "@ogre-tools/fp"; -import { flatten, map } from "lodash/fp"; import { removeExistingLensLinkDirectoriesInjectable } from "./remove-existing-lens-link-directories.injectable"; import { createLensLinkDirectoriesInjectable } from "./create-lens-link-directories.injectable"; -import { getMissingPackageJsonsInjectable } from "./get-missing-package-jsons.injectable"; import { getPackageJsonsInjectable } from "./get-package-jsons.injectable"; import { getPackageJsonPathsInjectable } from "./get-package-json-paths.injectable"; import { getInjectable } from "@ogre-tools/injectable"; -import { getLensLinkDirectoryInjectable } from "./get-lens-link-directory.injectable"; import { resolvePathInjectable } from "./path/resolve-path.injectable"; import { existsInjectable } from "./fs/exists.injectable"; import { writeJsonFileInjectable } from "./fs/write-json-file.injectable"; -import { createSymlinkInjectable } from "./fs/create-symlink.injectable"; import { workingDirectoryInjectable } from "./working-directory.injectable"; -import { globInjectable } from "./fs/glob.injectable"; -import { awaitAll } from "./await-all"; +import { getSymlinkPathsInjectable } from "./get-symlink-paths.injectable"; +import { createSymLinksInjectable } from "./create-sym-links.injectable"; +import { checkForMissingPackageJsonsInjectable } from "./check-for-missing-package-jsons.injectable"; export type LensLink = () => Promise; -const shouldBeGlobbed = (possibleGlobString: string) => possibleGlobString.includes("*"); - -const simplifyGlobbing = new RegExp("(\\/\\*\\/\\*\\*|\\/\\*\\*|\\/\\*\\*\\/\\*|\\/\\*)$"); -const toAvoidableGlobStrings = (reference: string) => reference.replace(simplifyGlobbing, ""); - const lensLinkInjectable = getInjectable({ id: "lens-link", instantiate: (di): LensLink => { const getPackageJsons = di.inject(getPackageJsonsInjectable); - const getLensLinkDirectory = di.inject(getLensLinkDirectoryInjectable); - const getMissingPackageJsons = di.inject(getMissingPackageJsonsInjectable); const removeExistingLensLinkDirectories = di.inject(removeExistingLensLinkDirectoriesInjectable); const createLensLinkDirectories = di.inject(createLensLinkDirectoriesInjectable); const getPackageJsonPaths = di.inject(getPackageJsonPathsInjectable); const resolvePath = di.inject(resolvePathInjectable); const exists = di.inject(existsInjectable); const writeJsonFile = di.inject(writeJsonFileInjectable); - const createSymlink = di.inject(createSymlinkInjectable); const workingDirectory = di.inject(workingDirectoryInjectable); - const glob = di.inject(globInjectable); + const getSymlinkPaths = di.inject(getSymlinkPathsInjectable); + const createSymLinks = di.inject(createSymLinksInjectable); + const checkForMissingPackageJsons = di.inject(checkForMissingPackageJsonsInjectable); return async () => { const configFilePath = resolvePath(workingDirectory, ".lens-links.json"); @@ -54,15 +42,7 @@ const lensLinkInjectable = getInjectable({ const packageJsonPaths = await getPackageJsonPaths(configFilePath); - const missingPackageJsons = await getMissingPackageJsons(packageJsonPaths); - - if (missingPackageJsons.length) { - throw new Error( - `Tried to install Lens links, but configured package.jsons were not found: "${missingPackageJsons.join( - '", "', - )}".`, - ); - } + await checkForMissingPackageJsons(packageJsonPaths); const packageJsons = await getPackageJsons(packageJsonPaths); @@ -70,53 +50,9 @@ const lensLinkInjectable = getInjectable({ await createLensLinkDirectories(packageJsons); - await pipeline( - packageJsons, + const symlinkPaths = await getSymlinkPaths(packageJsons); - map(async ({ packageJsonPath, content }) => { - const lensLinkDirectory = getLensLinkDirectory(content.name); - - const fileStrings = content.files.map(toAvoidableGlobStrings); - - const [toBeGlobbed, toNotBeGlobbed] = partition(shouldBeGlobbed)(fileStrings); - - const moduleDirectory = dirname(packageJsonPath); - - let globbeds: string[] = []; - - if (toBeGlobbed.length) { - globbeds = await glob(toBeGlobbed, { cwd: moduleDirectory }); - } - - return [ - { - target: packageJsonPath, - source: resolvePath(lensLinkDirectory, "package.json"), - type: "file" as const, - }, - - ...globbeds.map((fileString) => ({ - target: resolvePath(moduleDirectory, fileString), - source: resolvePath(lensLinkDirectory, fileString), - type: "file" as const, - })), - - ...toNotBeGlobbed.map((fileOrDirectory) => ({ - target: resolvePath(moduleDirectory, fileOrDirectory), - source: resolvePath(lensLinkDirectory, fileOrDirectory), - type: "dir" as const, - })), - ]; - }), - - awaitAll, - - flatten, - - map(({ target, source, type }) => createSymlink(target, source, type)), - - awaitAll, - ); + await createSymLinks(symlinkPaths); }; }, });