checkpoint
This commit is contained in:
parent
93fcf96cde
commit
a60a0d0696
@ -1,19 +0,0 @@
|
|||||||
import * as fs from "fs";
|
|
||||||
import { join as pathJoin } from "path";
|
|
||||||
import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath";
|
|
||||||
|
|
||||||
export function copyBoilerplate(params: { adminThemeSrcDirPath: string }) {
|
|
||||||
const { adminThemeSrcDirPath } = params;
|
|
||||||
|
|
||||||
fs.cpSync(
|
|
||||||
pathJoin(
|
|
||||||
getThisCodebaseRootDirPath(),
|
|
||||||
"src",
|
|
||||||
"bin",
|
|
||||||
"initialize-admin-theme",
|
|
||||||
"src"
|
|
||||||
),
|
|
||||||
adminThemeSrcDirPath,
|
|
||||||
{ recursive: true }
|
|
||||||
);
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from "./initialize-admin-theme";
|
|
@ -1,60 +0,0 @@
|
|||||||
import type { BuildContext } from "../shared/buildContext";
|
|
||||||
import chalk from "chalk";
|
|
||||||
import { join as pathJoin, relative as pathRelative } from "path";
|
|
||||||
import * as fs from "fs";
|
|
||||||
import { command as updateKcGenCommand } from "../update-kc-gen";
|
|
||||||
import { maybeDelegateCommandToCustomHandler } from "../shared/customHandler_delegate";
|
|
||||||
import { exitIfUncommittedChanges } from "../shared/exitIfUncommittedChanges";
|
|
||||||
import { initializeAdminTheme } from "./initializeAdminTheme";
|
|
||||||
|
|
||||||
export async function command(params: { buildContext: BuildContext }) {
|
|
||||||
const { buildContext } = params;
|
|
||||||
|
|
||||||
const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
|
|
||||||
commandName: "initialize-admin-theme",
|
|
||||||
buildContext
|
|
||||||
});
|
|
||||||
|
|
||||||
if (hasBeenHandled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const adminThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "admin");
|
|
||||||
|
|
||||||
if (
|
|
||||||
fs.existsSync(adminThemeSrcDirPath) &&
|
|
||||||
fs.readdirSync(adminThemeSrcDirPath).length > 0
|
|
||||||
) {
|
|
||||||
console.warn(
|
|
||||||
chalk.red(
|
|
||||||
`There is already a ${pathRelative(
|
|
||||||
process.cwd(),
|
|
||||||
adminThemeSrcDirPath
|
|
||||||
)} directory in your project. Aborting.`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
exitIfUncommittedChanges({
|
|
||||||
projectDirPath: buildContext.projectDirPath
|
|
||||||
});
|
|
||||||
|
|
||||||
await initializeAdminTheme({
|
|
||||||
adminThemeSrcDirPath,
|
|
||||||
buildContext
|
|
||||||
});
|
|
||||||
|
|
||||||
await updateKcGenCommand({
|
|
||||||
buildContext: {
|
|
||||||
...buildContext,
|
|
||||||
implementedThemeTypes: {
|
|
||||||
...buildContext.implementedThemeTypes,
|
|
||||||
admin: {
|
|
||||||
isImplemented: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
import { join as pathJoin, relative as pathRelative, dirname as pathDirname } from "path";
|
|
||||||
import type { BuildContext } from "../shared/buildContext";
|
|
||||||
import * as fs from "fs";
|
|
||||||
import chalk from "chalk";
|
|
||||||
import {
|
|
||||||
getLatestsSemVersionedTag,
|
|
||||||
type BuildContextLike as BuildContextLike_getLatestsSemVersionedTag
|
|
||||||
} from "../shared/getLatestsSemVersionedTag";
|
|
||||||
import { SemVer } from "../tools/SemVer";
|
|
||||||
import fetch from "make-fetch-happen";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
|
||||||
import { is } from "tsafe/is";
|
|
||||||
import { id } from "tsafe/id";
|
|
||||||
import { npmInstall } from "../tools/npmInstall";
|
|
||||||
import { copyBoilerplate } from "./copyBoilerplate";
|
|
||||||
import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath";
|
|
||||||
|
|
||||||
type BuildContextLike = BuildContextLike_getLatestsSemVersionedTag & {
|
|
||||||
fetchOptions: BuildContext["fetchOptions"];
|
|
||||||
packageJsonFilePath: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
assert<BuildContext extends BuildContextLike ? true : false>();
|
|
||||||
|
|
||||||
export async function initializeAdminTheme(params: {
|
|
||||||
adminThemeSrcDirPath: string;
|
|
||||||
buildContext: BuildContextLike;
|
|
||||||
}) {
|
|
||||||
const { adminThemeSrcDirPath, buildContext } = params;
|
|
||||||
|
|
||||||
const OWNER = "keycloakify";
|
|
||||||
const REPO = "keycloak-admin-ui";
|
|
||||||
|
|
||||||
const [semVersionedTag] = await getLatestsSemVersionedTag({
|
|
||||||
owner: OWNER,
|
|
||||||
repo: REPO,
|
|
||||||
count: 1,
|
|
||||||
doIgnoreReleaseCandidates: false,
|
|
||||||
buildContext
|
|
||||||
});
|
|
||||||
|
|
||||||
const dependencies = await fetch(
|
|
||||||
`https://raw.githubusercontent.com/${OWNER}/${REPO}/${semVersionedTag.tag}/dependencies.gen.json`,
|
|
||||||
buildContext.fetchOptions
|
|
||||||
)
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(
|
|
||||||
(() => {
|
|
||||||
type Dependencies = {
|
|
||||||
dependencies: Record<string, string>;
|
|
||||||
devDependencies?: Record<string, string>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const zDependencies = (() => {
|
|
||||||
type TargetType = Dependencies;
|
|
||||||
|
|
||||||
const zTargetType = z.object({
|
|
||||||
dependencies: z.record(z.string()),
|
|
||||||
devDependencies: z.record(z.string()).optional()
|
|
||||||
});
|
|
||||||
|
|
||||||
assert<Equals<z.infer<typeof zTargetType>, TargetType>>();
|
|
||||||
|
|
||||||
return id<z.ZodType<TargetType>>(zTargetType);
|
|
||||||
})();
|
|
||||||
|
|
||||||
return o => zDependencies.parse(o);
|
|
||||||
})()
|
|
||||||
);
|
|
||||||
|
|
||||||
dependencies.dependencies["@keycloakify/keycloak-admin-ui"] = SemVer.stringify(
|
|
||||||
semVersionedTag.version
|
|
||||||
);
|
|
||||||
|
|
||||||
const parsedPackageJson = (() => {
|
|
||||||
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);
|
|
||||||
})();
|
|
||||||
const parsedPackageJson = JSON.parse(
|
|
||||||
fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8")
|
|
||||||
);
|
|
||||||
|
|
||||||
zParsedPackageJson.parse(parsedPackageJson);
|
|
||||||
|
|
||||||
assert(is<ParsedPackageJson>(parsedPackageJson));
|
|
||||||
|
|
||||||
return parsedPackageJson;
|
|
||||||
})();
|
|
||||||
|
|
||||||
parsedPackageJson.dependencies = {
|
|
||||||
...parsedPackageJson.dependencies,
|
|
||||||
...dependencies.dependencies
|
|
||||||
};
|
|
||||||
|
|
||||||
parsedPackageJson.devDependencies = {
|
|
||||||
...parsedPackageJson.devDependencies,
|
|
||||||
...dependencies.devDependencies
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Object.keys(parsedPackageJson.devDependencies).length === 0) {
|
|
||||||
delete parsedPackageJson.devDependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
buildContext.packageJsonFilePath,
|
|
||||||
JSON.stringify(parsedPackageJson, undefined, 4)
|
|
||||||
);
|
|
||||||
|
|
||||||
run_npm_install: {
|
|
||||||
if (
|
|
||||||
JSON.parse(
|
|
||||||
fs
|
|
||||||
.readFileSync(pathJoin(getThisCodebaseRootDirPath(), "package.json"))
|
|
||||||
.toString("utf8")
|
|
||||||
)["version"] === "0.0.0"
|
|
||||||
) {
|
|
||||||
//NOTE: Linked version
|
|
||||||
break run_npm_install;
|
|
||||||
}
|
|
||||||
|
|
||||||
npmInstall({ packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath) });
|
|
||||||
}
|
|
||||||
|
|
||||||
copyBoilerplate({ adminThemeSrcDirPath });
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
[
|
|
||||||
chalk.green("The Admin theme has been successfully initialized."),
|
|
||||||
`Using Admin UI of Keycloak version: ${chalk.bold(semVersionedTag.tag.split("-")[0])}`,
|
|
||||||
`Directory created: ${chalk.bold(pathRelative(process.cwd(), adminThemeSrcDirPath))}`,
|
|
||||||
`Dependencies added to your project's package.json: `,
|
|
||||||
chalk.bold(JSON.stringify(dependencies, null, 2))
|
|
||||||
].join("\n")
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import type { KcContextLike } from "@keycloakify/keycloak-admin-ui";
|
|
||||||
import type { KcEnvName } from "../kc.gen";
|
|
||||||
|
|
||||||
export type KcContext = KcContextLike & {
|
|
||||||
themeType: "admin";
|
|
||||||
properties: Record<KcEnvName, string>;
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
import { lazy } from "react";
|
|
||||||
import { KcAdminUiLoader } from "@keycloakify/keycloak-admin-ui";
|
|
||||||
import type { KcContext } from "./KcContext";
|
|
||||||
|
|
||||||
const KcAdminUi = lazy(() => import("@keycloakify/keycloak-admin-ui/KcAdminUi"));
|
|
||||||
|
|
||||||
export default function KcPage(props: { kcContext: KcContext }) {
|
|
||||||
const { kcContext } = props;
|
|
||||||
|
|
||||||
return <KcAdminUiLoader kcContext={kcContext} KcAdminUi={KcAdminUi} />;
|
|
||||||
}
|
|
157
src/bin/sync-ui-modules/installUiModulesPeerDependencies.ts
Normal file
157
src/bin/sync-ui-modules/installUiModulesPeerDependencies.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
|
import { is } from "tsafe/is";
|
||||||
|
import type { BuildContext } from "../shared/buildContext";
|
||||||
|
import type { UiModuleMeta } from "./uiModuleMeta";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { id } from "tsafe/id";
|
||||||
|
import * as fsPr from "fs/promises";
|
||||||
|
import { SemVer } from "../tools/SemVer";
|
||||||
|
import { same } from "evt/tools/inDepth/same";
|
||||||
|
import { runPrettier, getIsPrettierAvailable } from "../tools/runPrettier";
|
||||||
|
import { npmInstall } from "../tools/npmInstall";
|
||||||
|
|
||||||
|
export type BuildContextLike = {
|
||||||
|
packageJsonFilePath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||||
|
|
||||||
|
export type UiModuleMetaLike = {
|
||||||
|
moduleName: string;
|
||||||
|
peerDependencies: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<UiModuleMeta extends UiModuleMetaLike ? true : false>();
|
||||||
|
|
||||||
|
export async function installUiModulesPeerDependencies(params: {
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
uiModuleMetas: UiModuleMetaLike[];
|
||||||
|
}): Promise<void | never> {
|
||||||
|
const { buildContext, uiModuleMetas } = params;
|
||||||
|
|
||||||
|
const { uiModulesPerDependencies } = (() => {
|
||||||
|
const uiModulesPerDependencies: Record<string, string> = {};
|
||||||
|
|
||||||
|
for (const { peerDependencies } of uiModuleMetas) {
|
||||||
|
for (const [peerDependencyName, versionRange_candidate] of Object.entries(
|
||||||
|
peerDependencies
|
||||||
|
)) {
|
||||||
|
const versionRange = (() => {
|
||||||
|
const versionRange_current =
|
||||||
|
uiModulesPerDependencies[peerDependencyName];
|
||||||
|
|
||||||
|
if (versionRange_current === undefined) {
|
||||||
|
return versionRange_candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versionRange_current === "*") {
|
||||||
|
return versionRange_candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versionRange_candidate === "*") {
|
||||||
|
return versionRange_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { versionRange } = [
|
||||||
|
versionRange_current,
|
||||||
|
versionRange_candidate
|
||||||
|
]
|
||||||
|
.map(versionRange => ({
|
||||||
|
versionRange,
|
||||||
|
semVer: SemVer.parse(
|
||||||
|
(() => {
|
||||||
|
if (
|
||||||
|
versionRange.startsWith("^") ||
|
||||||
|
versionRange.startsWith("~")
|
||||||
|
) {
|
||||||
|
return versionRange.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionRange;
|
||||||
|
})()
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
.sort((a, b) => SemVer.compare(b.semVer, a.semVer))[0];
|
||||||
|
|
||||||
|
return versionRange;
|
||||||
|
})();
|
||||||
|
|
||||||
|
uiModulesPerDependencies[peerDependencyName] = versionRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { uiModulesPerDependencies };
|
||||||
|
})();
|
||||||
|
|
||||||
|
const parsedPackageJson = await (async () => {
|
||||||
|
type ParsedPackageJson = {
|
||||||
|
dependencies?: Record<string, string>;
|
||||||
|
devDependencies?: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const zParsedPackageJson = (() => {
|
||||||
|
type TargetType = ParsedPackageJson;
|
||||||
|
|
||||||
|
const zParsedPackageJson = z.object({
|
||||||
|
dependencies: z.record(z.string()).optional(),
|
||||||
|
devDependencies: z.record(z.string()).optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
type InferredType = z.infer<typeof zParsedPackageJson>;
|
||||||
|
|
||||||
|
assert<Equals<InferredType, TargetType>>();
|
||||||
|
|
||||||
|
return id<z.ZodType<TargetType>>(zParsedPackageJson);
|
||||||
|
})();
|
||||||
|
|
||||||
|
const parsedPackageJson = JSON.parse(
|
||||||
|
(await fsPr.readFile(buildContext.packageJsonFilePath)).toString("utf8")
|
||||||
|
);
|
||||||
|
|
||||||
|
zParsedPackageJson.parse(parsedPackageJson);
|
||||||
|
|
||||||
|
assert(is<ParsedPackageJson>(parsedPackageJson));
|
||||||
|
|
||||||
|
return parsedPackageJson;
|
||||||
|
})();
|
||||||
|
|
||||||
|
const parsedPackageJson_before = JSON.parse(JSON.stringify(parsedPackageJson));
|
||||||
|
|
||||||
|
for (const [moduleName, versionRange] of Object.entries(uiModulesPerDependencies)) {
|
||||||
|
if (moduleName.startsWith("@types/")) {
|
||||||
|
(parsedPackageJson.devDependencies ??= {})[moduleName] = versionRange;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedPackageJson.devDependencies !== undefined) {
|
||||||
|
delete parsedPackageJson.devDependencies[moduleName];
|
||||||
|
}
|
||||||
|
|
||||||
|
(parsedPackageJson.dependencies ??= {})[moduleName] = versionRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (same(parsedPackageJson, parsedPackageJson_before)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let packageJsonContentStr = JSON.stringify(parsedPackageJson, null, 2);
|
||||||
|
|
||||||
|
format: {
|
||||||
|
if (!(await getIsPrettierAvailable())) {
|
||||||
|
break format;
|
||||||
|
}
|
||||||
|
|
||||||
|
packageJsonContentStr = await runPrettier({
|
||||||
|
sourceCode: packageJsonContentStr,
|
||||||
|
filePath: buildContext.packageJsonFilePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await fsPr.writeFile(buildContext.packageJsonFilePath, packageJsonContentStr);
|
||||||
|
|
||||||
|
npmInstall({
|
||||||
|
packageJsonDirPath: buildContext.packageJsonFilePath
|
||||||
|
});
|
||||||
|
|
||||||
|
process.exit(0);
|
||||||
|
}
|
@ -1,9 +1,15 @@
|
|||||||
import * as fsPr from "fs/promises";
|
import * as fsPr from "fs/promises";
|
||||||
import { join as pathJoin, sep as pathSep, dirname as pathDirname } from "path";
|
import {
|
||||||
|
join as pathJoin,
|
||||||
|
sep as pathSep,
|
||||||
|
dirname as pathDirname,
|
||||||
|
relative as pathRelative
|
||||||
|
} from "path";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import type { BuildContext } from "../shared/buildContext";
|
import type { BuildContext } from "../shared/buildContext";
|
||||||
import type { UiModuleMeta } from "./uiModuleMeta";
|
import type { UiModuleMeta } from "./uiModuleMeta";
|
||||||
import { existsAsync } from "../tools/fs.existsAsync";
|
import { existsAsync } from "../tools/fs.existsAsync";
|
||||||
|
import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
|
||||||
|
|
||||||
export type BuildContextLike = {
|
export type BuildContextLike = {
|
||||||
themeSrcDirPath: string;
|
themeSrcDirPath: string;
|
||||||
@ -82,3 +88,48 @@ export async function writeManagedGitignoreFile(params: {
|
|||||||
|
|
||||||
await fsPr.writeFile(filePath, content_new);
|
await fsPr.writeFile(filePath, content_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function readManagedGitignoreFile(params: {
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
}): Promise<{
|
||||||
|
ejectedFilesRelativePaths: string[];
|
||||||
|
}> {
|
||||||
|
const { buildContext } = params;
|
||||||
|
|
||||||
|
const filePath = pathJoin(buildContext.themeSrcDirPath, ".gitignore");
|
||||||
|
|
||||||
|
if (!(await existsAsync(filePath))) {
|
||||||
|
return { ejectedFilesRelativePaths: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentStr = (await fsPr.readFile(filePath)).toString("utf8");
|
||||||
|
|
||||||
|
const payload = (() => {
|
||||||
|
const index_start = contentStr.indexOf(DELIMITER_START);
|
||||||
|
const index_end = contentStr.indexOf(DELIMITER_END);
|
||||||
|
|
||||||
|
if (index_start === -1 || index_end === -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentStr.slice(index_start + DELIMITER_START.length, index_end).trim();
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (payload === undefined) {
|
||||||
|
return { ejectedFilesRelativePaths: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const ejectedFilesRelativePaths = payload
|
||||||
|
.split("\n")
|
||||||
|
.map(line => line.trim())
|
||||||
|
.filter(line => line !== "")
|
||||||
|
.map(line =>
|
||||||
|
getAbsoluteAndInOsFormatPath({
|
||||||
|
cwd: buildContext.themeSrcDirPath,
|
||||||
|
pathIsh: line
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.map(filePath => pathRelative(buildContext.themeSrcDirPath, filePath));
|
||||||
|
|
||||||
|
return { ejectedFilesRelativePaths };
|
||||||
|
}
|
||||||
|
@ -23,6 +23,10 @@ export function npmInstall(params: { packageJsonDirPath: string }) {
|
|||||||
{
|
{
|
||||||
binName: "bun",
|
binName: "bun",
|
||||||
lockFileBasename: "bun.lockdb"
|
lockFileBasename: "bun.lockdb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
binName: "deno",
|
||||||
|
lockFileBasename: "deno.lock"
|
||||||
}
|
}
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
@ -37,27 +41,23 @@ export function npmInstall(params: { packageJsonDirPath: string }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
throw new Error(
|
||||||
|
"No lock file found, cannot tell which package manager to use for installing dependencies."
|
||||||
|
);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
install_dependencies: {
|
console.log(`Installing the new dependencies...`);
|
||||||
if (packageManagerBinName === undefined) {
|
|
||||||
break install_dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Installing the new dependencies...`);
|
try {
|
||||||
|
child_process.execSync(`${packageManagerBinName} install`, {
|
||||||
try {
|
cwd: packageJsonDirPath,
|
||||||
child_process.execSync(`${packageManagerBinName} install`, {
|
stdio: "inherit"
|
||||||
cwd: packageJsonDirPath,
|
});
|
||||||
stdio: "inherit"
|
} catch {
|
||||||
});
|
console.log(
|
||||||
} catch {
|
chalk.yellow(
|
||||||
console.log(
|
`\`${packageManagerBinName} install\` failed, continuing anyway...`
|
||||||
chalk.yellow(
|
)
|
||||||
`\`${packageManagerBinName} install\` failed, continuing anyway...`
|
);
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user