Checkpoint
This commit is contained in:
parent
a60a0d0696
commit
a73281d46d
@ -115,7 +115,7 @@ import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
||||
}
|
||||
|
||||
run(
|
||||
`npx ncc build ${join("dist", "vite-plugin", "index.js")} -o ${join(
|
||||
`npx ncc build ${join("dist", "vite-plugin", "index.js")} --external prettier -o ${join(
|
||||
"dist",
|
||||
"ncc_out"
|
||||
)}`
|
||||
|
@ -14,7 +14,7 @@ import { kebabCaseToCamelCase } from "./tools/kebabCaseToSnakeCase";
|
||||
import { assert, Equals } from "tsafe/assert";
|
||||
import type { BuildContext } from "./shared/buildContext";
|
||||
import chalk from "chalk";
|
||||
import { runFormat } from "./tools/runFormat";
|
||||
import { runPrettier, getIsPrettierAvailable } from "./tools/runPrettier";
|
||||
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
|
||||
|
||||
export async function command(params: { buildContext: BuildContext }) {
|
||||
@ -119,7 +119,7 @@ export async function command(params: { buildContext: BuildContext }) {
|
||||
process.exit(-1);
|
||||
}
|
||||
|
||||
const componentCode = fs
|
||||
let sourceCode = fs
|
||||
.readFileSync(
|
||||
pathJoin(
|
||||
getThisCodebaseRootDirPath(),
|
||||
@ -133,6 +133,17 @@ export async function command(params: { buildContext: BuildContext }) {
|
||||
.replace('import React from "react";\n', "")
|
||||
.replace(/from "[./]+dist\//, 'from "keycloakify/');
|
||||
|
||||
run_prettier: {
|
||||
if (!(await getIsPrettierAvailable())) {
|
||||
break run_prettier;
|
||||
}
|
||||
|
||||
sourceCode = await runPrettier({
|
||||
filePath: targetFilePath,
|
||||
sourceCode: sourceCode
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const targetDirPath = pathDirname(targetFilePath);
|
||||
|
||||
@ -141,11 +152,7 @@ export async function command(params: { buildContext: BuildContext }) {
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(targetFilePath, Buffer.from(componentCode, "utf8"));
|
||||
|
||||
runFormat({
|
||||
packageJsonFilePath: buildContext.packageJsonFilePath
|
||||
});
|
||||
fs.writeFileSync(targetFilePath, Buffer.from(sourceCode, "utf8"));
|
||||
|
||||
console.log(
|
||||
[
|
||||
|
@ -22,7 +22,7 @@ import { assert, Equals } from "tsafe/assert";
|
||||
import type { BuildContext } from "./shared/buildContext";
|
||||
import chalk from "chalk";
|
||||
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
|
||||
import { runFormat } from "./tools/runFormat";
|
||||
import { runPrettier, getIsPrettierAvailable } from "./tools/runPrettier";
|
||||
|
||||
export async function command(params: { buildContext: BuildContext }) {
|
||||
const { buildContext } = params;
|
||||
@ -217,7 +217,7 @@ export async function command(params: { buildContext: BuildContext }) {
|
||||
process.exit(-1);
|
||||
}
|
||||
|
||||
const componentCode = fs
|
||||
let componentCode = fs
|
||||
.readFileSync(
|
||||
pathJoin(
|
||||
getThisCodebaseRootDirPath(),
|
||||
@ -229,6 +229,17 @@ export async function command(params: { buildContext: BuildContext }) {
|
||||
)
|
||||
.toString("utf8");
|
||||
|
||||
run_prettier: {
|
||||
if (!(await getIsPrettierAvailable())) {
|
||||
break run_prettier;
|
||||
}
|
||||
|
||||
componentCode = await runPrettier({
|
||||
filePath: targetFilePath,
|
||||
sourceCode: componentCode
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const targetDirPath = pathDirname(targetFilePath);
|
||||
|
||||
@ -239,10 +250,6 @@ export async function command(params: { buildContext: BuildContext }) {
|
||||
|
||||
fs.writeFileSync(targetFilePath, Buffer.from(componentCode, "utf8"));
|
||||
|
||||
runFormat({
|
||||
packageJsonFilePath: buildContext.packageJsonFilePath
|
||||
});
|
||||
|
||||
console.log(
|
||||
`${chalk.green("✓")} ${chalk.bold(
|
||||
pathJoin(".", pathRelative(process.cwd(), targetFilePath))
|
||||
|
@ -197,20 +197,6 @@ program
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command({
|
||||
name: "initialize-admin-theme",
|
||||
description: "Initialize the admin theme."
|
||||
})
|
||||
.task({
|
||||
skip,
|
||||
handler: async ({ projectDirPath }) => {
|
||||
const { command } = await import("./initialize-admin-theme");
|
||||
|
||||
await command({ buildContext: getBuildContext({ projectDirPath }) });
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command({
|
||||
name: "copy-keycloak-resources-to-public",
|
||||
@ -241,6 +227,20 @@ program
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command({
|
||||
name: "postinstall",
|
||||
description: "Initialize all the Keycloakify UI modules installed in the project."
|
||||
})
|
||||
.task({
|
||||
skip,
|
||||
handler: async ({ projectDirPath }) => {
|
||||
const { command } = await import("./postinstall");
|
||||
|
||||
await command({ buildContext: getBuildContext({ projectDirPath }) });
|
||||
}
|
||||
});
|
||||
|
||||
// Fallback to build command if no command is provided
|
||||
{
|
||||
const [, , ...rest] = process.argv;
|
||||
|
@ -3,6 +3,7 @@ import * as fsPr from "fs/promises";
|
||||
import { join as pathJoin, sep as pathSep } from "path";
|
||||
import { assert } from "tsafe/assert";
|
||||
import type { BuildContext } from "../shared/buildContext";
|
||||
import { KEYCLOAK_THEME } from "../shared/constants";
|
||||
|
||||
export type BuildContextLike = {
|
||||
themeSrcDirPath: string;
|
||||
@ -10,27 +11,32 @@ export type BuildContextLike = {
|
||||
|
||||
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||
|
||||
export async function getSourceCodeToCopyInUserCodebase(params: {
|
||||
export async function getUiModuleFileSourceCodeReadyToBeCopied(params: {
|
||||
buildContext: BuildContextLike;
|
||||
relativeFromDirPath: string;
|
||||
fileRelativePath: string;
|
||||
commentData: {
|
||||
isForEjection: boolean;
|
||||
uiModuleDirPath: string;
|
||||
uiModuleName: string;
|
||||
uiModuleVersion: string;
|
||||
};
|
||||
}): Promise<string> {
|
||||
const { buildContext, relativeFromDirPath, fileRelativePath, commentData } = params;
|
||||
}): Promise<Buffer> {
|
||||
const {
|
||||
buildContext,
|
||||
uiModuleDirPath,
|
||||
fileRelativePath,
|
||||
isForEjection,
|
||||
uiModuleName,
|
||||
uiModuleVersion
|
||||
} = params;
|
||||
|
||||
let sourceCode = (
|
||||
await fsPr.readFile(pathJoin(relativeFromDirPath, fileRelativePath))
|
||||
await fsPr.readFile(pathJoin(uiModuleDirPath, KEYCLOAK_THEME, fileRelativePath))
|
||||
).toString("utf8");
|
||||
|
||||
const comment = (() => {
|
||||
if (commentData.isForEjection) {
|
||||
if (isForEjection) {
|
||||
return [
|
||||
`/*`,
|
||||
` This file was ejected from ${commentData.uiModuleName} version ${commentData.uiModuleVersion}.`,
|
||||
` This file was ejected from ${uiModuleName} version ${uiModuleVersion}.`,
|
||||
`*/`
|
||||
].join("\n");
|
||||
} else {
|
||||
@ -39,7 +45,7 @@ export async function getSourceCodeToCopyInUserCodebase(params: {
|
||||
` WARNING: Before modifying this file run the following command:`,
|
||||
` \`npx keycloakify eject-file ${fileRelativePath.split(pathSep).join("/")}\``,
|
||||
` `,
|
||||
` This file comes from ${commentData.uiModuleName} version ${commentData.uiModuleVersion}.`,
|
||||
` This file comes from ${uiModuleName} version ${uiModuleVersion}.`,
|
||||
`*/`
|
||||
];
|
||||
}
|
||||
@ -47,16 +53,18 @@ export async function getSourceCodeToCopyInUserCodebase(params: {
|
||||
|
||||
sourceCode = [comment, ``, sourceCode].join("\n");
|
||||
|
||||
const destFilePath = pathJoin(buildContext.themeSrcDirPath, fileRelativePath);
|
||||
|
||||
format: {
|
||||
if (!(await getIsPrettierAvailable())) {
|
||||
break format;
|
||||
}
|
||||
|
||||
sourceCode = await runPrettier({
|
||||
filePath: pathJoin(buildContext.themeSrcDirPath, fileRelativePath),
|
||||
filePath: destFilePath,
|
||||
sourceCode
|
||||
});
|
||||
}
|
||||
|
||||
return sourceCode;
|
||||
return Buffer.from(sourceCode, "utf8");
|
||||
}
|
1
src/bin/postinstall/index.ts
Normal file
1
src/bin/postinstall/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./postinstall";
|
79
src/bin/postinstall/postinstall.ts
Normal file
79
src/bin/postinstall/postinstall.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import type { BuildContext } from "../shared/buildContext";
|
||||
import { getUiModuleMetas, computeHash } from "./uiModuleMeta";
|
||||
import { installUiModulesPeerDependencies } from "./installUiModulesPeerDependencies";
|
||||
import {
|
||||
readManagedGitignoreFile,
|
||||
writeManagedGitignoreFile
|
||||
} from "./managedGitignoreFile";
|
||||
import { dirname as pathDirname } from "path";
|
||||
import { join as pathJoin } from "path";
|
||||
import { existsAsync } from "../tools/fs.existsAsync";
|
||||
import * as fsPr from "fs/promises";
|
||||
|
||||
export async function command(params: { buildContext: BuildContext }) {
|
||||
const { buildContext } = params;
|
||||
|
||||
const uiModuleMetas = await getUiModuleMetas({ buildContext });
|
||||
|
||||
await installUiModulesPeerDependencies({
|
||||
buildContext,
|
||||
uiModuleMetas
|
||||
});
|
||||
|
||||
const { ejectedFilesRelativePaths } = await readManagedGitignoreFile({
|
||||
buildContext
|
||||
});
|
||||
|
||||
await writeManagedGitignoreFile({
|
||||
buildContext,
|
||||
ejectedFilesRelativePaths,
|
||||
uiModuleMetas
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
uiModuleMetas
|
||||
.map(uiModuleMeta =>
|
||||
Promise.all(
|
||||
uiModuleMeta.files.map(
|
||||
async ({ fileRelativePath, copyableFilePath, hash }) => {
|
||||
if (ejectedFilesRelativePaths.includes(fileRelativePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destFilePath = pathJoin(
|
||||
buildContext.themeSrcDirPath,
|
||||
fileRelativePath
|
||||
);
|
||||
|
||||
skip_condition: {
|
||||
if (!(await existsAsync(destFilePath))) {
|
||||
break skip_condition;
|
||||
}
|
||||
|
||||
const destFileHash = computeHash(
|
||||
await fsPr.readFile(destFilePath)
|
||||
);
|
||||
|
||||
if (destFileHash !== hash) {
|
||||
break skip_condition;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const dirName = pathDirname(copyableFilePath);
|
||||
|
||||
if (!(await existsAsync(dirName))) {
|
||||
await fsPr.mkdir(dirName, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
await fsPr.copyFile(copyableFilePath, destFilePath);
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { assert, type Equals } from "tsafe/assert";
|
||||
import { id } from "tsafe/id";
|
||||
import { z } from "zod";
|
||||
import { join as pathJoin, sep as pathSep, dirname as pathDirname } from "path";
|
||||
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||
import * as fsPr from "fs/promises";
|
||||
import type { BuildContext } from "../shared/buildContext";
|
||||
import { is } from "tsafe/is";
|
||||
@ -11,10 +11,11 @@ import { crawlAsync } from "../tools/crawlAsync";
|
||||
import { getIsPrettierAvailable, getPrettierAndConfig } from "../tools/runPrettier";
|
||||
import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
|
||||
import {
|
||||
getSourceCodeToCopyInUserCodebase,
|
||||
type BuildContextLike as BuildContextLike_getSourceCodeToCopyInUserCodebase
|
||||
} from "./getSourceCodeToCopyInUserCodebase";
|
||||
getUiModuleFileSourceCodeReadyToBeCopied,
|
||||
type BuildContextLike as BuildContextLike_getUiModuleFileSourceCodeReadyToBeCopied
|
||||
} from "./getUiModuleFileSourceCodeReadyToBeCopied";
|
||||
import * as crypto from "crypto";
|
||||
import { KEYCLOAK_THEME } from "../shared/constants";
|
||||
|
||||
export type UiModuleMeta = {
|
||||
moduleName: string;
|
||||
@ -22,6 +23,7 @@ export type UiModuleMeta = {
|
||||
files: {
|
||||
fileRelativePath: string;
|
||||
hash: string;
|
||||
copyableFilePath: string;
|
||||
}[];
|
||||
peerDependencies: Record<string, string>;
|
||||
};
|
||||
@ -35,7 +37,8 @@ const zUiModuleMeta = (() => {
|
||||
files: z.array(
|
||||
z.object({
|
||||
fileRelativePath: z.string(),
|
||||
hash: z.string()
|
||||
hash: z.string(),
|
||||
copyableFilePath: z.string()
|
||||
})
|
||||
),
|
||||
peerDependencies: z.record(z.string())
|
||||
@ -51,7 +54,7 @@ const zUiModuleMeta = (() => {
|
||||
type ParsedCacheFile = {
|
||||
keycloakifyVersion: string;
|
||||
prettierConfigHash: string | null;
|
||||
pathSep: string;
|
||||
thisFilePath: string;
|
||||
uiModuleMetas: UiModuleMeta[];
|
||||
};
|
||||
|
||||
@ -61,7 +64,7 @@ const zParsedCacheFile = (() => {
|
||||
const zTargetType = z.object({
|
||||
keycloakifyVersion: z.string(),
|
||||
prettierConfigHash: z.union([z.string(), z.null()]),
|
||||
pathSep: z.string(),
|
||||
thisFilePath: z.string(),
|
||||
uiModuleMetas: z.array(zUiModuleMeta)
|
||||
});
|
||||
|
||||
@ -72,9 +75,10 @@ const zParsedCacheFile = (() => {
|
||||
return id<z.ZodType<ExpectedType>>(zTargetType);
|
||||
})();
|
||||
|
||||
const CACHE_FILE_BASENAME = "uiModulesMeta.json";
|
||||
const CACHE_FILE_RELATIVE_PATH = pathJoin("ui-modules", "cache.json");
|
||||
|
||||
export type BuildContextLike = BuildContextLike_getSourceCodeToCopyInUserCodebase & {
|
||||
export type BuildContextLike =
|
||||
BuildContextLike_getUiModuleFileSourceCodeReadyToBeCopied & {
|
||||
cacheDirPath: string;
|
||||
packageJsonFilePath: string;
|
||||
projectDirPath: string;
|
||||
@ -87,7 +91,7 @@ export async function getUiModuleMetas(params: {
|
||||
}): Promise<UiModuleMeta[]> {
|
||||
const { buildContext } = params;
|
||||
|
||||
const cacheFilePath = pathJoin(buildContext.cacheDirPath, CACHE_FILE_BASENAME);
|
||||
const cacheFilePath = pathJoin(buildContext.cacheDirPath, CACHE_FILE_RELATIVE_PATH);
|
||||
|
||||
const keycloakifyVersion = readThisNpmPackageVersion();
|
||||
|
||||
@ -101,13 +105,21 @@ export async function getUiModuleMetas(params: {
|
||||
return crypto.createHash("sha256").update(JSON.stringify(config)).digest("hex");
|
||||
})();
|
||||
|
||||
const installedUiModules = await listInstalledModules({
|
||||
const installedUiModules = await (async () => {
|
||||
const installedModulesWithKeycloakifyInTheName = await listInstalledModules({
|
||||
packageJsonFilePath: buildContext.packageJsonFilePath,
|
||||
projectDirPath: buildContext.packageJsonFilePath,
|
||||
filter: ({ moduleName }) =>
|
||||
moduleName.includes("keycloakify") && moduleName.endsWith("-ui")
|
||||
moduleName.includes("keycloakify") && moduleName !== "keycloakify"
|
||||
});
|
||||
|
||||
return Promise.all(
|
||||
installedModulesWithKeycloakifyInTheName.filter(async ({ dirPath }) =>
|
||||
existsAsync(pathJoin(dirPath, KEYCLOAK_THEME))
|
||||
)
|
||||
);
|
||||
})();
|
||||
|
||||
const cacheContent = await (async () => {
|
||||
if (!(await existsAsync(cacheFilePath))) {
|
||||
return undefined;
|
||||
@ -155,7 +167,7 @@ export async function getUiModuleMetas(params: {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (parsedCacheFile.pathSep !== pathSep) {
|
||||
if (parsedCacheFile.thisFilePath !== cacheFilePath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -200,31 +212,44 @@ export async function getUiModuleMetas(params: {
|
||||
const files: UiModuleMeta["files"] = [];
|
||||
|
||||
{
|
||||
const srcDirPath = pathJoin(dirPath, "src");
|
||||
const srcDirPath = pathJoin(dirPath, KEYCLOAK_THEME);
|
||||
|
||||
await crawlAsync({
|
||||
dirPath: srcDirPath,
|
||||
returnedPathsType: "relative to dirPath",
|
||||
onFileFound: async fileRelativePath => {
|
||||
const sourceCode = await getSourceCodeToCopyInUserCodebase({
|
||||
const sourceCode =
|
||||
await getUiModuleFileSourceCodeReadyToBeCopied({
|
||||
buildContext,
|
||||
relativeFromDirPath: srcDirPath,
|
||||
fileRelativePath,
|
||||
commentData: {
|
||||
isForEjection: false,
|
||||
uiModuleDirPath: dirPath,
|
||||
uiModuleName: moduleName,
|
||||
uiModuleVersion: version
|
||||
}
|
||||
});
|
||||
|
||||
const hash = crypto
|
||||
.createHash("sha256")
|
||||
.update(sourceCode)
|
||||
.digest("hex");
|
||||
const hash = computeHash(sourceCode);
|
||||
|
||||
const copyableFilePath = pathJoin(
|
||||
pathDirname(cacheFilePath),
|
||||
KEYCLOAK_THEME,
|
||||
fileRelativePath
|
||||
);
|
||||
|
||||
{
|
||||
const dirPath = pathDirname(copyableFilePath);
|
||||
|
||||
if (!(await existsAsync(dirPath))) {
|
||||
await fsPr.mkdir(dirPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
fsPr.writeFile(copyableFilePath, sourceCode);
|
||||
|
||||
files.push({
|
||||
fileRelativePath,
|
||||
hash
|
||||
hash,
|
||||
copyableFilePath
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -244,7 +269,7 @@ export async function getUiModuleMetas(params: {
|
||||
const parsedCacheFile = id<ParsedCacheFile>({
|
||||
keycloakifyVersion,
|
||||
prettierConfigHash,
|
||||
pathSep,
|
||||
thisFilePath: cacheFilePath,
|
||||
uiModuleMetas
|
||||
});
|
||||
|
||||
@ -272,3 +297,7 @@ export async function getUiModuleMetas(params: {
|
||||
|
||||
return uiModuleMetas;
|
||||
}
|
||||
|
||||
export function computeHash(data: Buffer) {
|
||||
return crypto.createHash("sha256").update(data).digest("hex");
|
||||
}
|
@ -18,9 +18,8 @@ import {
|
||||
import type { KeycloakVersionRange } from "./KeycloakVersionRange";
|
||||
import { exclude } from "tsafe";
|
||||
import { crawl } from "../tools/crawl";
|
||||
import { THEME_TYPES } from "./constants";
|
||||
import { THEME_TYPES, KEYCLOAK_THEME, type ThemeType } from "./constants";
|
||||
import { objectEntries } from "tsafe/objectEntries";
|
||||
import { type ThemeType } from "./constants";
|
||||
import { id } from "tsafe/id";
|
||||
import chalk from "chalk";
|
||||
import { getProxyFetchOptions, type FetchOptionsLike } from "../tools/fetchProxyOptions";
|
||||
@ -147,7 +146,10 @@ export function getBuildContext(params: {
|
||||
returnedPathsType: "relative to dirPath"
|
||||
})
|
||||
.map(fileRelativePath => {
|
||||
for (const themeSrcDirBasename of ["keycloak-theme", "keycloak_theme"]) {
|
||||
for (const themeSrcDirBasename of [
|
||||
KEYCLOAK_THEME,
|
||||
KEYCLOAK_THEME.replace(/-/g, "_")
|
||||
]) {
|
||||
const split = fileRelativePath.split(themeSrcDirBasename);
|
||||
if (split.length === 2) {
|
||||
return pathJoin(srcDirPath, split[0] + themeSrcDirBasename);
|
||||
@ -173,7 +175,7 @@ export function getBuildContext(params: {
|
||||
[
|
||||
`Can't locate your Keycloak theme source directory in .${pathSep}${pathRelative(process.cwd(), srcDirPath)}`,
|
||||
`Make sure to either use the Keycloakify CLI in the root of your Keycloakify project or use the --project CLI option`,
|
||||
`If you are collocating your Keycloak theme with your app you must have a directory named 'keycloak-theme' or 'keycloak_theme' in your 'src' directory`
|
||||
`If you are collocating your Keycloak theme with your app you must have a directory named '${KEYCLOAK_THEME}' or '${KEYCLOAK_THEME.replace(/-/g, "_")}' in your 'src' directory`
|
||||
].join("\n")
|
||||
)
|
||||
);
|
||||
|
@ -76,3 +76,5 @@ export const CUSTOM_HANDLER_ENV_NAMES = {
|
||||
COMMAND_NAME: "KEYCLOAKIFY_COMMAND_NAME",
|
||||
BUILD_CONTEXT: "KEYCLOAKIFY_BUILD_CONTEXT"
|
||||
};
|
||||
|
||||
export const KEYCLOAK_THEME = "keycloak-theme";
|
||||
|
@ -1 +0,0 @@
|
||||
export * from "./sync-ui-modules";
|
@ -1,13 +0,0 @@
|
||||
import type { BuildContext } from "./shared/buildContext";
|
||||
import { assert, type Equals } from "tsafe/assert";
|
||||
import { id } from "tsafe/id";
|
||||
import { is } from "tsafe/is";
|
||||
import { z } from "zod";
|
||||
import { join as pathJoin } from "path";
|
||||
import { existsAsync } from "./tools/fs.existsAsync";
|
||||
|
||||
import * as fsPr from "fs/promises";
|
||||
|
||||
export async function command(params: { buildContext: BuildContext }) {
|
||||
const { buildContext } = params;
|
||||
}
|
@ -1,16 +1,14 @@
|
||||
import { dirname as pathDirname, join as pathJoin } from "path";
|
||||
import { join as pathJoin } from "path";
|
||||
import { existsAsync } from "./fs.existsAsync";
|
||||
import * as child_process from "child_process";
|
||||
import { assert } from "tsafe/assert";
|
||||
|
||||
export async function getInstalledModuleDirPath(params: {
|
||||
moduleName: string;
|
||||
packageJsonFilePath: string;
|
||||
packageJsonDirPath: string;
|
||||
projectDirPath: string;
|
||||
}) {
|
||||
const { moduleName, packageJsonFilePath, projectDirPath } = params;
|
||||
|
||||
const packageJsonDirPath = pathDirname(packageJsonFilePath);
|
||||
const { moduleName, packageJsonDirPath, projectDirPath } = params;
|
||||
|
||||
common_case: {
|
||||
const dirPath = pathJoin(
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { assert, type Equals } from "tsafe/assert";
|
||||
import { id } from "tsafe/id";
|
||||
import { z } from "zod";
|
||||
import { join as pathJoin } from "path";
|
||||
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||
import * as fsPr from "fs/promises";
|
||||
import { is } from "tsafe/is";
|
||||
import { getInstalledModuleDirPath } from "../tools/getInstalledModuleDirPath";
|
||||
import { exclude } from "tsafe/exclude";
|
||||
|
||||
export async function listInstalledModules(params: {
|
||||
packageJsonFilePath: string;
|
||||
@ -27,7 +28,7 @@ export async function listInstalledModules(params: {
|
||||
const uiModuleNames = (
|
||||
[parsedPackageJson.dependencies, parsedPackageJson.devDependencies] as const
|
||||
)
|
||||
.filter(obj => obj !== undefined)
|
||||
.filter(exclude(undefined))
|
||||
.map(obj => Object.keys(obj))
|
||||
.flat()
|
||||
.filter(moduleName => filter({ moduleName }));
|
||||
@ -36,7 +37,7 @@ export async function listInstalledModules(params: {
|
||||
uiModuleNames.map(async moduleName => {
|
||||
const dirPath = await getInstalledModuleDirPath({
|
||||
moduleName,
|
||||
packageJsonFilePath,
|
||||
packageJsonDirPath: pathDirname(packageJsonFilePath),
|
||||
projectDirPath
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user