keycloak_theme/src/bin/tools/listInstalledModules.ts
Joseph Garrone de4490cf0f Update tsafe
2024-11-18 21:38:27 +01:00

131 lines
3.9 KiB
TypeScript

import { assert, type Equals, is } from "tsafe/assert";
import { id } from "tsafe/id";
import { z } from "zod";
import { join as pathJoin, dirname as pathDirname } from "path";
import * as fsPr from "fs/promises";
import { getInstalledModuleDirPath } from "../tools/getInstalledModuleDirPath";
import { exclude } from "tsafe/exclude";
export async function listInstalledModules(params: {
packageJsonFilePath: string;
projectDirPath: string;
filter: (params: { moduleName: string }) => boolean;
}): Promise<
{
moduleName: string;
version: string;
dirPath: string;
peerDependencies: Record<string, string>;
}[]
> {
const { packageJsonFilePath, projectDirPath, filter } = params;
const parsedPackageJson = await readPackageJsonDependencies({
packageJsonFilePath
});
const uiModuleNames = (
[parsedPackageJson.dependencies, parsedPackageJson.devDependencies] as const
)
.filter(exclude(undefined))
.map(obj => Object.keys(obj))
.flat()
.filter(moduleName => filter({ moduleName }));
const result = await Promise.all(
uiModuleNames.map(async moduleName => {
const dirPath = await getInstalledModuleDirPath({
moduleName,
packageJsonDirPath: pathDirname(packageJsonFilePath),
projectDirPath
});
const { version, peerDependencies } =
await readPackageJsonVersionAndPeerDependencies({
packageJsonFilePath: pathJoin(dirPath, "package.json")
});
return { moduleName, version, peerDependencies, dirPath } as const;
})
);
return result;
}
const { readPackageJsonDependencies } = (() => {
type ParsedPackageJson = {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
};
const zParsedPackageJson = (() => {
type TargetType = ParsedPackageJson;
const zTargetType = z.object({
dependencies: z.record(z.string()).optional(),
devDependencies: z.record(z.string()).optional()
});
assert<Equals<z.infer<typeof zTargetType>, TargetType>>();
return id<z.ZodType<TargetType>>(zTargetType);
})();
async function readPackageJsonDependencies(params: { packageJsonFilePath: string }) {
const { packageJsonFilePath } = params;
const parsedPackageJson = JSON.parse(
(await fsPr.readFile(packageJsonFilePath)).toString("utf8")
);
zParsedPackageJson.parse(parsedPackageJson);
assert(is<ParsedPackageJson>(parsedPackageJson));
return parsedPackageJson;
}
return { readPackageJsonDependencies };
})();
const { readPackageJsonVersionAndPeerDependencies } = (() => {
type ParsedPackageJson = {
version: string;
peerDependencies?: Record<string, string>;
};
const zParsedPackageJson = (() => {
type TargetType = ParsedPackageJson;
const zTargetType = z.object({
version: z.string(),
peerDependencies: z.record(z.string()).optional()
});
assert<Equals<z.infer<typeof zTargetType>, TargetType>>();
return id<z.ZodType<TargetType>>(zTargetType);
})();
async function readPackageJsonVersionAndPeerDependencies(params: {
packageJsonFilePath: string;
}): Promise<{ version: string; peerDependencies: Record<string, string> }> {
const { packageJsonFilePath } = params;
const parsedPackageJson = JSON.parse(
(await fsPr.readFile(packageJsonFilePath)).toString("utf8")
);
zParsedPackageJson.parse(parsedPackageJson);
assert(is<ParsedPackageJson>(parsedPackageJson));
return {
version: parsedPackageJson.version,
peerDependencies: parsedPackageJson.peerDependencies ?? {}
};
}
return { readPackageJsonVersionAndPeerDependencies };
})();