@wzyjs/cli 0.3.31 → 0.3.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +350 -35
- package/package.json +6 -4
- package/template/web/base/Dockerfile +37 -0
- package/template/web/base/_env +2 -0
- package/template/web/base/eslint.config.js +94 -0
- package/template/web/base/next.config.js +29 -0
- package/template/web/base/package.json +53 -0
- package/template/web/base/postcss.config.js +5 -0
- package/template/web/base/prisma/models/demo/DemoItem.zmodel +8 -0
- package/template/web/base/prisma/schema.prisma +29 -0
- package/template/web/base/prisma/schema.zmodel +1 -0
- package/template/web/base/src/app/api/trpc/[trpc]/route.ts +24 -0
- package/template/web/base/src/app/auth/disabled/page.tsx +29 -0
- package/template/web/base/src/app/auth/error/page.tsx +47 -0
- package/template/web/base/src/app/auth/signin/page.tsx +53 -0
- package/template/web/base/src/app/auth/unauthorized/page.tsx +60 -0
- package/template/web/base/src/app/demo/page.tsx +59 -0
- package/template/web/base/src/app/layout.tsx +32 -0
- package/template/web/base/src/app/not-found.tsx +21 -0
- package/template/web/base/src/app/page.tsx +92 -0
- package/template/web/base/src/components/base/Layout/Header/context.tsx +56 -0
- package/template/web/base/src/components/base/Layout/Header/index.tsx +32 -0
- package/template/web/base/src/components/base/Layout/index.tsx +27 -0
- package/template/web/base/src/components/base/Providers/TRPCReactProvider.tsx +25 -0
- package/template/web/base/src/components/base/Providers/index.tsx +31 -0
- package/template/web/base/src/components/base/display/DisplayProvider.tsx +44 -0
- package/template/web/base/src/components/base/display/consts.ts +10 -0
- package/template/web/base/src/components/base/display/context.ts +6 -0
- package/template/web/base/src/components/base/display/index.ts +4 -0
- package/template/web/base/src/components/base/display/types.ts +12 -0
- package/template/web/base/src/components/base/display/useDisplay.ts +9 -0
- package/template/web/base/src/components/base/display/utils.ts +18 -0
- package/template/web/base/src/components/base/theme/ThemeProvider.tsx +83 -0
- package/template/web/base/src/components/base/theme/ThemeToggle.tsx +26 -0
- package/template/web/base/src/components/base/theme/consts.tsx +59 -0
- package/template/web/base/src/components/base/theme/context.ts +14 -0
- package/template/web/base/src/components/base/theme/useAppTheme.ts +15 -0
- package/template/web/base/src/components/base/theme/utils.ts +17 -0
- package/template/web/base/src/components/index.ts +1 -0
- package/template/web/base/src/consts/index.ts +6 -0
- package/template/web/base/src/enums/index.ts +1 -0
- package/template/web/base/src/env.js +44 -0
- package/template/web/base/src/hooks/index.ts +1 -0
- package/template/web/base/src/server/db/client.ts +19 -0
- package/template/web/base/src/server/routers/index.ts +3 -0
- package/template/web/base/src/server/trpc/context.ts +14 -0
- package/template/web/base/src/server/trpc/index.ts +1 -0
- package/template/web/base/src/server/trpc/init.ts +27 -0
- package/template/web/base/src/server/trpc/procedures.ts +5 -0
- package/template/web/base/src/server/trpc/router.ts +11 -0
- package/template/web/base/src/server/utils/index.ts +1 -0
- package/template/web/base/src/styles/globals.css +3 -0
- package/template/web/base/src/types/index.ts +1 -0
- package/template/web/base/src/utils/index.ts +4 -0
- package/template/web/base/src/utils/query-client/index.ts +31 -0
- package/template/web/base/src/utils/trpc/index.ts +23 -0
- package/template/web/base/src/utils/trpc/utils.ts +61 -0
- package/template/web/base/tailwind.config.cjs +7 -0
- package/template/web/base/tsconfig.json +46 -0
- package/template/web/google/_env +8 -0
- package/template/web/google/package.json +55 -0
- package/template/web/google/prisma/models/auth/Account.zmodel +26 -0
- package/template/web/google/prisma/models/auth/Session.zmodel +17 -0
- package/template/web/google/prisma/models/auth/User.zmodel +22 -0
- package/template/web/google/prisma/schema.zmodel +2 -0
- package/template/web/google/src/app/api/auth/[...nextauth]/route.ts +7 -0
- package/template/web/google/src/app/auth/error/page.tsx +56 -0
- package/template/web/google/src/app/auth/signin/page.tsx +83 -0
- package/template/web/google/src/app/layout.tsx +35 -0
- package/template/web/google/src/components/base/AuthGuard/Loading.tsx +19 -0
- package/template/web/google/src/components/base/AuthGuard/index.tsx +45 -0
- package/template/web/google/src/components/base/Layout/Header/UserAuthStatus.tsx +93 -0
- package/template/web/google/src/components/base/Layout/Header/index.tsx +34 -0
- package/template/web/google/src/components/base/Providers/index.tsx +34 -0
- package/template/web/google/src/env.js +52 -0
- package/template/web/google/src/server/auth/next-auth/adapter.ts +77 -0
- package/template/web/google/src/server/auth/next-auth/options.ts +53 -0
- package/template/web/google/src/server/trpc/context.ts +21 -0
- package/template/web/google/src/server/trpc/procedures.ts +16 -0
- package/template/web/middle/_env +10 -0
- package/template/web/middle/package.json +55 -0
- package/template/web/middle/src/app/api/auth/[...nextauth]/route.ts +7 -0
- package/template/web/middle/src/app/auth/disabled/page.tsx +71 -0
- package/template/web/middle/src/app/auth/error/page.tsx +56 -0
- package/template/web/middle/src/app/auth/signin/page.tsx +91 -0
- package/template/web/middle/src/app/auth/unauthorized/page.tsx +88 -0
- package/template/web/middle/src/app/layout.tsx +35 -0
- package/template/web/middle/src/app/middle/page.tsx +10 -0
- package/template/web/middle/src/app/page.tsx +20 -0
- package/template/web/middle/src/components/base/AuthGuard/Loading.tsx +19 -0
- package/template/web/middle/src/components/base/AuthGuard/index.tsx +45 -0
- package/template/web/middle/src/components/base/Layout/Header/UserAuthStatus.tsx +93 -0
- package/template/web/middle/src/components/base/Layout/Header/index.tsx +34 -0
- package/template/web/middle/src/components/base/Layout/Sidebar/index.tsx +88 -0
- package/template/web/middle/src/components/base/Layout/index.tsx +35 -0
- package/template/web/middle/src/components/base/Providers/MiddleProvider.tsx +33 -0
- package/template/web/middle/src/components/base/Providers/index.tsx +37 -0
- package/template/web/middle/src/env.js +57 -0
- package/template/web/middle/src/server/auth/next-auth/options.ts +26 -0
- package/template/web/middle/src/server/trpc/context.ts +22 -0
- package/template/web/middle/src/server/trpc/procedures.ts +16 -0
- package/template/web/middle/src/server/utils/index.ts +2 -0
- package/template/web/middle/src/server/utils/middle.ts +34 -0
- package/template/web/middle/src/types/index.ts +3 -0
- package/template/web/middle/src/utils/index.ts +5 -0
- package/template/web/middle/src/utils/middle.ts +28 -0
package/dist/index.js
CHANGED
|
@@ -601,6 +601,308 @@ class CAC extends EventEmitter {
|
|
|
601
601
|
var cac = (name = "") => new CAC(name);
|
|
602
602
|
var dist_default = cac;
|
|
603
603
|
|
|
604
|
+
// src/commands/create/script.ts
|
|
605
|
+
import path3 from "path";
|
|
606
|
+
import { existsSync as existsSync2 } from "fs";
|
|
607
|
+
|
|
608
|
+
// src/commands/create/utils.ts
|
|
609
|
+
import { readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
610
|
+
function replaceInFile(filePath, replacements) {
|
|
611
|
+
let content = readFileSync(filePath, "utf8");
|
|
612
|
+
for (const [from, to] of replacements) {
|
|
613
|
+
content = content.split(from).join(to);
|
|
614
|
+
}
|
|
615
|
+
writeFileSync(filePath, content);
|
|
616
|
+
}
|
|
617
|
+
function toPackageName(input) {
|
|
618
|
+
const normalized = input.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
619
|
+
return normalized || "wzyjs-app";
|
|
620
|
+
}
|
|
621
|
+
function toDatabaseName(input) {
|
|
622
|
+
const normalized = input.trim().toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
|
|
623
|
+
return normalized || "app";
|
|
624
|
+
}
|
|
625
|
+
function isDirectoryEmpty(dir) {
|
|
626
|
+
try {
|
|
627
|
+
const stats = statSync(dir);
|
|
628
|
+
if (!stats.isDirectory()) {
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
return readdirSync(dir).length === 0;
|
|
632
|
+
} catch (error) {
|
|
633
|
+
if (error?.code === "ENOENT") {
|
|
634
|
+
return true;
|
|
635
|
+
}
|
|
636
|
+
throw error;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function fail(message) {
|
|
640
|
+
console.error(`\u521B\u5EFA\u5931\u8D25: ${message}`);
|
|
641
|
+
process.exit(1);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// src/commands/create/parse-args.ts
|
|
645
|
+
function parseArgs(inputArgs) {
|
|
646
|
+
if (inputArgs.some((arg) => arg.startsWith("-"))) {
|
|
647
|
+
const unsupportedArg = inputArgs.find((arg) => arg.startsWith("-"));
|
|
648
|
+
fail(`\u4E0D\u652F\u6301\u6760\u6760\u53C2\u6570: ${unsupportedArg}\u3002\u7528\u6CD5: mi create <template-name> <target-dir> <port> [project-name]`);
|
|
649
|
+
}
|
|
650
|
+
if (inputArgs.length < 3) {
|
|
651
|
+
fail("\u81F3\u5C11\u9700\u8981\u6307\u5B9A\u6A21\u677F\u540D\u3001\u76EE\u6807\u76EE\u5F55\u548C\u7AEF\u53E3\u3002\u7528\u6CD5: mi create <template-name> <target-dir> <port> [project-name]");
|
|
652
|
+
}
|
|
653
|
+
if (inputArgs.length > 4) {
|
|
654
|
+
fail("\u6700\u591A\u53EA\u80FD\u6307\u5B9A 4 \u4E2A\u53C2\u6570: <template-name> <target-dir> <port> [project-name]");
|
|
655
|
+
}
|
|
656
|
+
const parsed = {
|
|
657
|
+
templateName: inputArgs[0],
|
|
658
|
+
targetDir: inputArgs[1],
|
|
659
|
+
port: parsePort(inputArgs[2]),
|
|
660
|
+
name: inputArgs[3]
|
|
661
|
+
};
|
|
662
|
+
if (!isSupportedTemplateName(parsed.templateName)) {
|
|
663
|
+
fail(`\u4E0D\u652F\u6301\u7684\u6A21\u677F\u7C7B\u578B: ${parsed.templateName}\uFF0C\u5F53\u524D\u53EF\u9009\u503C: ${getSupportedTemplateNames().join(", ")}`);
|
|
664
|
+
}
|
|
665
|
+
if (parsed.name !== undefined) {
|
|
666
|
+
parsed.name = parsed.name.trim();
|
|
667
|
+
if (!parsed.name) {
|
|
668
|
+
fail("project-name \u4E0D\u80FD\u4E3A\u7A7A");
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return parsed;
|
|
672
|
+
}
|
|
673
|
+
function getSupportedTemplateNames() {
|
|
674
|
+
return ["base", "google", "middle"];
|
|
675
|
+
}
|
|
676
|
+
function isSupportedTemplateName(input) {
|
|
677
|
+
return getSupportedTemplateNames().includes(input);
|
|
678
|
+
}
|
|
679
|
+
function parsePort(input) {
|
|
680
|
+
const port = Number(input);
|
|
681
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
682
|
+
fail(`\u7AEF\u53E3\u53F7\u65E0\u6548: ${input}`);
|
|
683
|
+
}
|
|
684
|
+
return port;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// src/commands/create/customize.ts
|
|
688
|
+
import { randomBytes } from "crypto";
|
|
689
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
690
|
+
import path from "path";
|
|
691
|
+
function customizePackageJson(projectDir, options) {
|
|
692
|
+
const { packageName: nextPackageName, port } = options;
|
|
693
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
694
|
+
const content = readFileSync2(packageJsonPath, "utf8");
|
|
695
|
+
const pkg = JSON.parse(content);
|
|
696
|
+
pkg.name = nextPackageName;
|
|
697
|
+
pkg.scripts.dev = `next dev --turbopack --port ${port}`;
|
|
698
|
+
writeFileSync2(packageJsonPath, `${JSON.stringify(pkg, null, 2)}
|
|
699
|
+
`);
|
|
700
|
+
}
|
|
701
|
+
function customizeProjectFiles(projectDir, options) {
|
|
702
|
+
const {
|
|
703
|
+
databaseName: nextDatabaseName,
|
|
704
|
+
packageName: nextPackageName,
|
|
705
|
+
port,
|
|
706
|
+
projectName: nextProjectName,
|
|
707
|
+
templateName
|
|
708
|
+
} = options;
|
|
709
|
+
if (!nextProjectName) {
|
|
710
|
+
fail2("project-name \u4E0D\u80FD\u4E3A\u7A7A");
|
|
711
|
+
}
|
|
712
|
+
if (!nextDatabaseName) {
|
|
713
|
+
fail2("database-name \u4E0D\u80FD\u4E3A\u7A7A");
|
|
714
|
+
}
|
|
715
|
+
replaceInFile(path.join(projectDir, ".env"), [
|
|
716
|
+
["postgresql://root:password.@localhost:5432/demo", `postgresql://root:password.@localhost:5432/${toDatabaseName(nextDatabaseName)}`],
|
|
717
|
+
["NEXTAUTH_URL=http://localhost:4000", `NEXTAUTH_URL=http://localhost:${port}`],
|
|
718
|
+
["NEXTAUTH_SECRET=", `NEXTAUTH_SECRET=${createNextAuthSecret()}`]
|
|
719
|
+
]);
|
|
720
|
+
replaceInFile(path.join(projectDir, "src/app/layout.tsx"), [
|
|
721
|
+
["'__WZYJS_APP_DISPLAY_NAME__'", JSON.stringify(nextProjectName)]
|
|
722
|
+
]);
|
|
723
|
+
replaceInFile(path.join(projectDir, "src/app/page.tsx"), [
|
|
724
|
+
["'__WZYJS_APP_DISPLAY_NAME__'", JSON.stringify(nextProjectName)],
|
|
725
|
+
["__WZYJS_APP_DISPLAY_NAME__", nextProjectName]
|
|
726
|
+
]);
|
|
727
|
+
replaceInFile(path.join(projectDir, "src/components/base/Layout/Header/index.tsx"), [
|
|
728
|
+
["__WZYJS_APP_DISPLAY_NAME__", nextProjectName]
|
|
729
|
+
]);
|
|
730
|
+
replaceInFile(path.join(projectDir, "src/components/base/theme/ThemeProvider.tsx"), [
|
|
731
|
+
["__WZYJS_APP_PACKAGE_NAME__", nextPackageName]
|
|
732
|
+
]);
|
|
733
|
+
if (templateName === "middle") {
|
|
734
|
+
customizeMiddleProjectFiles(projectDir, {
|
|
735
|
+
packageName: nextPackageName
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
function customizeMiddleProjectFiles(projectDir, options) {
|
|
740
|
+
replaceInFile(path.join(projectDir, "src/server/auth/next-auth/options.ts"), [
|
|
741
|
+
["__WZYJS_APP_PACKAGE_NAME__", options.packageName]
|
|
742
|
+
]);
|
|
743
|
+
}
|
|
744
|
+
function createNextAuthSecret() {
|
|
745
|
+
return randomBytes(32).toString("base64");
|
|
746
|
+
}
|
|
747
|
+
function fail2(message) {
|
|
748
|
+
console.error(`\u521B\u5EFA\u5931\u8D25: ${message}`);
|
|
749
|
+
process.exit(1);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// src/commands/create/generate.ts
|
|
753
|
+
import { spawnSync } from "child_process";
|
|
754
|
+
function runGenerate(projectDir) {
|
|
755
|
+
console.log("");
|
|
756
|
+
console.log("\u6B63\u5728\u751F\u6210 Prisma / ZenStack \u4EE3\u7801...");
|
|
757
|
+
const result = spawnSync("bun", ["run", "generate"], {
|
|
758
|
+
cwd: projectDir,
|
|
759
|
+
stdio: "inherit"
|
|
760
|
+
});
|
|
761
|
+
if (result.error) {
|
|
762
|
+
fail(`\u6267\u884C bun run generate \u5931\u8D25: ${result.error.message}`);
|
|
763
|
+
}
|
|
764
|
+
if (result.status !== 0) {
|
|
765
|
+
fail("\u6267\u884C bun run generate \u5931\u8D25\uFF0C\u8BF7\u6839\u636E\u4E0A\u9762\u7684\u9519\u8BEF\u4FE1\u606F\u5904\u7406");
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// src/commands/create/templates.ts
|
|
770
|
+
import { cpSync, existsSync, mkdirSync, readdirSync as readdirSync2, renameSync } from "fs";
|
|
771
|
+
import path2 from "path";
|
|
772
|
+
function getTemplateLayers(templateName) {
|
|
773
|
+
if (templateName === "base") {
|
|
774
|
+
return ["base"];
|
|
775
|
+
}
|
|
776
|
+
if (templateName === "google") {
|
|
777
|
+
return ["base", "google"];
|
|
778
|
+
}
|
|
779
|
+
if (templateName === "middle") {
|
|
780
|
+
return ["base", "middle"];
|
|
781
|
+
}
|
|
782
|
+
fail(`\u4E0D\u652F\u6301\u7684\u6A21\u677F\u7C7B\u578B: ${templateName}`);
|
|
783
|
+
}
|
|
784
|
+
function validateTemplateLayers(templatesDir, templateLayers) {
|
|
785
|
+
for (const templateLayer of templateLayers) {
|
|
786
|
+
const templateDir = path2.join(templatesDir, templateLayer);
|
|
787
|
+
if (!existsSync(templateDir)) {
|
|
788
|
+
fail(`\u6A21\u677F\u76EE\u5F55\u4E0D\u5B58\u5728: ${templateDir}`);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
function copyTemplateLayers(options) {
|
|
793
|
+
const {
|
|
794
|
+
targetDir,
|
|
795
|
+
templateLayers,
|
|
796
|
+
templatesDir
|
|
797
|
+
} = options;
|
|
798
|
+
mkdirSync(targetDir, { recursive: true });
|
|
799
|
+
for (const templateLayer of templateLayers) {
|
|
800
|
+
const templateDir = path2.join(templatesDir, templateLayer);
|
|
801
|
+
for (const entry of readdirSync2(templateDir)) {
|
|
802
|
+
if (entry === ".DS_Store") {
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
cpSync(path2.join(templateDir, entry), path2.join(targetDir, entry), {
|
|
806
|
+
recursive: true,
|
|
807
|
+
force: true,
|
|
808
|
+
filter: (source) => path2.basename(source) !== ".DS_Store"
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
function restoreSpecialFiles(projectDir) {
|
|
814
|
+
const envPlaceholderPath = path2.join(projectDir, "_env");
|
|
815
|
+
const envPath = path2.join(projectDir, ".env");
|
|
816
|
+
if (existsSync(envPlaceholderPath)) {
|
|
817
|
+
renameSync(envPlaceholderPath, envPath);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// src/commands/create/script.ts
|
|
822
|
+
var __dirname = "/Users/wangzhenyu/Code/work/libs/cli/src/commands/create";
|
|
823
|
+
function createApp(inputArgs, options = {}) {
|
|
824
|
+
const parsedOptions = parseArgs(inputArgs);
|
|
825
|
+
const cwd = options.cwd ?? process.cwd();
|
|
826
|
+
const templatesDir = options.templatesDir ?? getDefaultTemplatesDir();
|
|
827
|
+
const targetDir = path3.resolve(cwd, parsedOptions.targetDir);
|
|
828
|
+
const projectName = parsedOptions.name ?? inferProjectNameFromTargetDir(targetDir, cwd);
|
|
829
|
+
const databaseName = inferDatabaseNameFromTargetDir(targetDir);
|
|
830
|
+
const packageName = toPackageName(projectName);
|
|
831
|
+
const templateLayers = getTemplateLayers(parsedOptions.templateName);
|
|
832
|
+
validateTemplateLayers(templatesDir, templateLayers);
|
|
833
|
+
if (!isDirectoryEmpty(targetDir)) {
|
|
834
|
+
fail3(`\u76EE\u6807\u76EE\u5F55\u4E0D\u4E3A\u7A7A: ${targetDir}`);
|
|
835
|
+
}
|
|
836
|
+
copyTemplateLayers({
|
|
837
|
+
targetDir,
|
|
838
|
+
templateLayers,
|
|
839
|
+
templatesDir
|
|
840
|
+
});
|
|
841
|
+
restoreSpecialFiles(targetDir);
|
|
842
|
+
customizePackageJson(targetDir, {
|
|
843
|
+
packageName,
|
|
844
|
+
port: parsedOptions.port,
|
|
845
|
+
templateName: parsedOptions.templateName
|
|
846
|
+
});
|
|
847
|
+
customizeProjectFiles(targetDir, {
|
|
848
|
+
databaseName,
|
|
849
|
+
packageName,
|
|
850
|
+
projectName,
|
|
851
|
+
port: parsedOptions.port,
|
|
852
|
+
templateName: parsedOptions.templateName
|
|
853
|
+
});
|
|
854
|
+
runGenerate(targetDir);
|
|
855
|
+
printSuccessMessage({
|
|
856
|
+
packageName,
|
|
857
|
+
port: parsedOptions.port,
|
|
858
|
+
projectName,
|
|
859
|
+
targetDir,
|
|
860
|
+
templateName: parsedOptions.templateName
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
function getDefaultTemplatesDir() {
|
|
864
|
+
const candidates = [
|
|
865
|
+
path3.resolve(__dirname, "../template/web"),
|
|
866
|
+
path3.resolve(__dirname, "../../../template/web")
|
|
867
|
+
];
|
|
868
|
+
return candidates.find((candidate) => existsSync2(candidate)) ?? candidates[0];
|
|
869
|
+
}
|
|
870
|
+
function inferProjectNameFromTargetDir(targetDir, cwd) {
|
|
871
|
+
const relativeTargetDir = path3.relative(cwd, targetDir);
|
|
872
|
+
const nameSource = relativeTargetDir && !relativeTargetDir.startsWith("..") && !path3.isAbsolute(relativeTargetDir) ? relativeTargetDir : targetDir;
|
|
873
|
+
const segments = nameSource.split(path3.sep).filter((segment) => segment && segment !== ".");
|
|
874
|
+
const projectSegments = segments.slice(-2);
|
|
875
|
+
return projectSegments.join("-") || path3.basename(targetDir);
|
|
876
|
+
}
|
|
877
|
+
function inferDatabaseNameFromTargetDir(targetDir) {
|
|
878
|
+
const targetName = path3.basename(targetDir);
|
|
879
|
+
const parentName = path3.basename(path3.dirname(targetDir));
|
|
880
|
+
return parentName || targetName;
|
|
881
|
+
}
|
|
882
|
+
function printSuccessMessage(options) {
|
|
883
|
+
console.log("");
|
|
884
|
+
console.log(`\u5DF2\u521B\u5EFA\u9879\u76EE: ${options.targetDir}`);
|
|
885
|
+
console.log(`\u9879\u76EE\u540D: ${options.projectName}`);
|
|
886
|
+
console.log(`\u5305\u540D\u5DF2\u8BBE\u7F6E\u4E3A: ${options.packageName}`);
|
|
887
|
+
console.log(`\u5F00\u53D1\u7AEF\u53E3: ${options.port}`);
|
|
888
|
+
console.log(`\u6A21\u677F\u7C7B\u578B: ${options.templateName}`);
|
|
889
|
+
console.log("");
|
|
890
|
+
console.log("\u63A5\u4E0B\u6765\u9700\u8981\u4F60\u5904\u7406\uFF1A");
|
|
891
|
+
console.log("1. \u5148\u4FEE\u6539 .env \u6587\u4EF6\u91CC\u7684\u73AF\u5883\u53D8\u91CF");
|
|
892
|
+
console.log("2. \u5982\u9700\u540C\u6B65\u6570\u636E\u5E93\uFF0C\u518D\u6267\u884C bun run db:push");
|
|
893
|
+
}
|
|
894
|
+
function fail3(message) {
|
|
895
|
+
console.error(`\u521B\u5EFA\u5931\u8D25: ${message}`);
|
|
896
|
+
process.exit(1);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// src/commands/create/index.ts
|
|
900
|
+
var create_default = (cli) => {
|
|
901
|
+
cli.command("create <templateName> <targetDir> <port> [projectName]", "\u521B\u5EFA\u5E94\u7528\u9879\u76EE\u6A21\u677F").action((templateName, targetDir, port, projectName) => {
|
|
902
|
+
createApp([templateName, targetDir, port, projectName].filter(Boolean));
|
|
903
|
+
});
|
|
904
|
+
};
|
|
905
|
+
|
|
604
906
|
// src/commands/merge/script.ts
|
|
605
907
|
import { exec } from "child_process";
|
|
606
908
|
async function getLatestCommitMsg() {
|
|
@@ -845,7 +1147,7 @@ var isURL = (payload) => payload instanceof URL;
|
|
|
845
1147
|
|
|
846
1148
|
// ../../node_modules/superjson/dist/pathstringifier.js
|
|
847
1149
|
var escapeKey = (key) => key.replace(/\\/g, "\\\\").replace(/\./g, "\\.");
|
|
848
|
-
var stringifyPath = (
|
|
1150
|
+
var stringifyPath = (path4) => path4.map(String).map(escapeKey).join(".");
|
|
849
1151
|
var parsePath = (string, legacyPaths) => {
|
|
850
1152
|
const result = [];
|
|
851
1153
|
let segment = "";
|
|
@@ -1087,26 +1389,26 @@ var getNthKey = (value, n) => {
|
|
|
1087
1389
|
}
|
|
1088
1390
|
return keys.next().value;
|
|
1089
1391
|
};
|
|
1090
|
-
function validatePath(
|
|
1091
|
-
if (includes(
|
|
1392
|
+
function validatePath(path4) {
|
|
1393
|
+
if (includes(path4, "__proto__")) {
|
|
1092
1394
|
throw new Error("__proto__ is not allowed as a property");
|
|
1093
1395
|
}
|
|
1094
|
-
if (includes(
|
|
1396
|
+
if (includes(path4, "prototype")) {
|
|
1095
1397
|
throw new Error("prototype is not allowed as a property");
|
|
1096
1398
|
}
|
|
1097
|
-
if (includes(
|
|
1399
|
+
if (includes(path4, "constructor")) {
|
|
1098
1400
|
throw new Error("constructor is not allowed as a property");
|
|
1099
1401
|
}
|
|
1100
1402
|
}
|
|
1101
|
-
var getDeep = (object,
|
|
1102
|
-
validatePath(
|
|
1103
|
-
for (let i = 0;i <
|
|
1104
|
-
const key =
|
|
1403
|
+
var getDeep = (object, path4) => {
|
|
1404
|
+
validatePath(path4);
|
|
1405
|
+
for (let i = 0;i < path4.length; i++) {
|
|
1406
|
+
const key = path4[i];
|
|
1105
1407
|
if (isSet(object)) {
|
|
1106
1408
|
object = getNthKey(object, +key);
|
|
1107
1409
|
} else if (isMap(object)) {
|
|
1108
1410
|
const row = +key;
|
|
1109
|
-
const type = +
|
|
1411
|
+
const type = +path4[++i] === 0 ? "key" : "value";
|
|
1110
1412
|
const keyOfRow = getNthKey(object, row);
|
|
1111
1413
|
switch (type) {
|
|
1112
1414
|
case "key":
|
|
@@ -1122,14 +1424,14 @@ var getDeep = (object, path) => {
|
|
|
1122
1424
|
}
|
|
1123
1425
|
return object;
|
|
1124
1426
|
};
|
|
1125
|
-
var setDeep = (object,
|
|
1126
|
-
validatePath(
|
|
1127
|
-
if (
|
|
1427
|
+
var setDeep = (object, path4, mapper) => {
|
|
1428
|
+
validatePath(path4);
|
|
1429
|
+
if (path4.length === 0) {
|
|
1128
1430
|
return mapper(object);
|
|
1129
1431
|
}
|
|
1130
1432
|
let parent = object;
|
|
1131
|
-
for (let i = 0;i <
|
|
1132
|
-
const key =
|
|
1433
|
+
for (let i = 0;i < path4.length - 1; i++) {
|
|
1434
|
+
const key = path4[i];
|
|
1133
1435
|
if (isArray(parent)) {
|
|
1134
1436
|
const index = +key;
|
|
1135
1437
|
parent = parent[index];
|
|
@@ -1139,12 +1441,12 @@ var setDeep = (object, path, mapper) => {
|
|
|
1139
1441
|
const row = +key;
|
|
1140
1442
|
parent = getNthKey(parent, row);
|
|
1141
1443
|
} else if (isMap(parent)) {
|
|
1142
|
-
const isEnd = i ===
|
|
1444
|
+
const isEnd = i === path4.length - 2;
|
|
1143
1445
|
if (isEnd) {
|
|
1144
1446
|
break;
|
|
1145
1447
|
}
|
|
1146
1448
|
const row = +key;
|
|
1147
|
-
const type = +
|
|
1449
|
+
const type = +path4[++i] === 0 ? "key" : "value";
|
|
1148
1450
|
const keyOfRow = getNthKey(parent, row);
|
|
1149
1451
|
switch (type) {
|
|
1150
1452
|
case "key":
|
|
@@ -1156,7 +1458,7 @@ var setDeep = (object, path, mapper) => {
|
|
|
1156
1458
|
}
|
|
1157
1459
|
}
|
|
1158
1460
|
}
|
|
1159
|
-
const lastKey =
|
|
1461
|
+
const lastKey = path4[path4.length - 1];
|
|
1160
1462
|
if (isArray(parent)) {
|
|
1161
1463
|
parent[+lastKey] = mapper(parent[+lastKey]);
|
|
1162
1464
|
} else if (isPlainObject(parent)) {
|
|
@@ -1171,7 +1473,7 @@ var setDeep = (object, path, mapper) => {
|
|
|
1171
1473
|
}
|
|
1172
1474
|
}
|
|
1173
1475
|
if (isMap(parent)) {
|
|
1174
|
-
const row = +
|
|
1476
|
+
const row = +path4[path4.length - 2];
|
|
1175
1477
|
const keyToRow = getNthKey(parent, row);
|
|
1176
1478
|
const type = +lastKey === 0 ? "key" : "value";
|
|
1177
1479
|
switch (type) {
|
|
@@ -1218,16 +1520,16 @@ function traverse(tree, walker, version, origin = []) {
|
|
|
1218
1520
|
walker(nodeValue, origin);
|
|
1219
1521
|
}
|
|
1220
1522
|
function applyValueAnnotations(plain, annotations, version, superJson) {
|
|
1221
|
-
traverse(annotations, (type,
|
|
1222
|
-
plain = setDeep(plain,
|
|
1523
|
+
traverse(annotations, (type, path4) => {
|
|
1524
|
+
plain = setDeep(plain, path4, (v) => untransformValue(v, type, superJson));
|
|
1223
1525
|
}, version);
|
|
1224
1526
|
return plain;
|
|
1225
1527
|
}
|
|
1226
1528
|
function applyReferentialEqualityAnnotations(plain, annotations, version) {
|
|
1227
1529
|
const legacyPaths = enableLegacyPaths(version);
|
|
1228
|
-
function apply(identicalPaths,
|
|
1229
|
-
const object = getDeep(plain, parsePath(
|
|
1230
|
-
identicalPaths.map((
|
|
1530
|
+
function apply(identicalPaths, path4) {
|
|
1531
|
+
const object = getDeep(plain, parsePath(path4, legacyPaths));
|
|
1532
|
+
identicalPaths.map((path5) => parsePath(path5, legacyPaths)).forEach((identicalObjectPath) => {
|
|
1231
1533
|
plain = setDeep(plain, identicalObjectPath, () => object);
|
|
1232
1534
|
});
|
|
1233
1535
|
}
|
|
@@ -1245,12 +1547,12 @@ function applyReferentialEqualityAnnotations(plain, annotations, version) {
|
|
|
1245
1547
|
return plain;
|
|
1246
1548
|
}
|
|
1247
1549
|
var isDeep = (object, superJson) => isPlainObject(object) || isArray(object) || isMap(object) || isSet(object) || isError(object) || isInstanceOfRegisteredClass(object, superJson);
|
|
1248
|
-
function addIdentity(object,
|
|
1550
|
+
function addIdentity(object, path4, identities) {
|
|
1249
1551
|
const existingSet = identities.get(object);
|
|
1250
1552
|
if (existingSet) {
|
|
1251
|
-
existingSet.push(
|
|
1553
|
+
existingSet.push(path4);
|
|
1252
1554
|
} else {
|
|
1253
|
-
identities.set(object, [
|
|
1555
|
+
identities.set(object, [path4]);
|
|
1254
1556
|
}
|
|
1255
1557
|
}
|
|
1256
1558
|
function generateReferentialEqualityAnnotations(identitites, dedupe) {
|
|
@@ -1261,7 +1563,7 @@ function generateReferentialEqualityAnnotations(identitites, dedupe) {
|
|
|
1261
1563
|
return;
|
|
1262
1564
|
}
|
|
1263
1565
|
if (!dedupe) {
|
|
1264
|
-
paths = paths.map((
|
|
1566
|
+
paths = paths.map((path4) => path4.map(String)).sort((a, b) => a.length - b.length);
|
|
1265
1567
|
}
|
|
1266
1568
|
const [representativePath, ...identicalPaths] = paths;
|
|
1267
1569
|
if (representativePath.length === 0) {
|
|
@@ -1280,10 +1582,10 @@ function generateReferentialEqualityAnnotations(identitites, dedupe) {
|
|
|
1280
1582
|
return isEmptyObject(result) ? undefined : result;
|
|
1281
1583
|
}
|
|
1282
1584
|
}
|
|
1283
|
-
var walker = (object, identities, superJson, dedupe,
|
|
1585
|
+
var walker = (object, identities, superJson, dedupe, path4 = [], objectsInThisPath = [], seenObjects = new Map) => {
|
|
1284
1586
|
const primitive = isPrimitive(object);
|
|
1285
1587
|
if (!primitive) {
|
|
1286
|
-
addIdentity(object,
|
|
1588
|
+
addIdentity(object, path4, identities);
|
|
1287
1589
|
const seen = seenObjects.get(object);
|
|
1288
1590
|
if (seen) {
|
|
1289
1591
|
return dedupe ? {
|
|
@@ -1317,7 +1619,7 @@ var walker = (object, identities, superJson, dedupe, path = [], objectsInThisPat
|
|
|
1317
1619
|
if (index === "__proto__" || index === "constructor" || index === "prototype") {
|
|
1318
1620
|
throw new Error(`Detected property ${index}. This is a prototype pollution risk, please remove it from your object.`);
|
|
1319
1621
|
}
|
|
1320
|
-
const recursiveResult = walker(value, identities, superJson, dedupe, [...
|
|
1622
|
+
const recursiveResult = walker(value, identities, superJson, dedupe, [...path4, index], [...objectsInThisPath, object], seenObjects);
|
|
1321
1623
|
transformedValue[index] = recursiveResult.transformedValue;
|
|
1322
1624
|
if (isArray(recursiveResult.annotations)) {
|
|
1323
1625
|
innerAnnotations[escapeKey(index)] = recursiveResult.annotations;
|
|
@@ -1638,21 +1940,23 @@ var scrap_default = (cli) => {
|
|
|
1638
1940
|
// package.json
|
|
1639
1941
|
var package_default = {
|
|
1640
1942
|
name: "@wzyjs/cli",
|
|
1641
|
-
version: "0.3.
|
|
1943
|
+
version: "0.3.32",
|
|
1642
1944
|
description: "description",
|
|
1643
1945
|
author: "wzy",
|
|
1644
1946
|
main: "dist/index.js",
|
|
1645
1947
|
type: "commonjs",
|
|
1646
1948
|
scripts: {
|
|
1647
1949
|
build: "bun build ./src/index.ts --outdir dist --target bun",
|
|
1648
|
-
"build-link": "npm run build && bun link"
|
|
1950
|
+
"build-link": "npm run build && bun link",
|
|
1951
|
+
typecheck: "tsc --noEmit"
|
|
1649
1952
|
},
|
|
1650
1953
|
bin: {
|
|
1651
1954
|
mi: "bin/mi.js"
|
|
1652
1955
|
},
|
|
1653
1956
|
files: [
|
|
1654
1957
|
"bin",
|
|
1655
|
-
"dist"
|
|
1958
|
+
"dist",
|
|
1959
|
+
"template"
|
|
1656
1960
|
],
|
|
1657
1961
|
dependencies: {
|
|
1658
1962
|
cac: "^6.7.14",
|
|
@@ -1669,8 +1973,19 @@ var package_default = {
|
|
|
1669
1973
|
|
|
1670
1974
|
// src/index.ts
|
|
1671
1975
|
var cli = dist_default("mi");
|
|
1976
|
+
create_default(cli);
|
|
1672
1977
|
merge_default(cli);
|
|
1673
1978
|
scrap_default(cli);
|
|
1674
1979
|
cli.help();
|
|
1675
1980
|
cli.version(package_default.version);
|
|
1676
|
-
|
|
1981
|
+
try {
|
|
1982
|
+
cli.parse();
|
|
1983
|
+
} catch (error) {
|
|
1984
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1985
|
+
if (message.includes("missing required args for command `create")) {
|
|
1986
|
+
console.error("\u521B\u5EFA\u5931\u8D25: \u81F3\u5C11\u9700\u8981\u6307\u5B9A\u6A21\u677F\u540D\u3001\u76EE\u6807\u76EE\u5F55\u548C\u7AEF\u53E3\u3002\u7528\u6CD5: mi create <template-name> <target-dir> <port> [project-name]");
|
|
1987
|
+
} else {
|
|
1988
|
+
console.error(`\u547D\u4EE4\u53C2\u6570\u9519\u8BEF: ${message}`);
|
|
1989
|
+
}
|
|
1990
|
+
process.exit(1);
|
|
1991
|
+
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wzyjs/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.36",
|
|
4
4
|
"description": "description",
|
|
5
5
|
"author": "wzy",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"type": "commonjs",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "bun build ./src/index.ts --outdir dist --target bun",
|
|
10
|
-
"build-link": "npm run build && bun link"
|
|
10
|
+
"build-link": "npm run build && bun link",
|
|
11
|
+
"typecheck": "tsc --noEmit"
|
|
11
12
|
},
|
|
12
13
|
"bin": {
|
|
13
14
|
"mi": "bin/mi.js"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"bin",
|
|
17
|
-
"dist"
|
|
18
|
+
"dist",
|
|
19
|
+
"template"
|
|
18
20
|
],
|
|
19
21
|
"dependencies": {
|
|
20
22
|
"cac": "^6.7.14",
|
|
@@ -26,5 +28,5 @@
|
|
|
26
28
|
"publishConfig": {
|
|
27
29
|
"access": "public"
|
|
28
30
|
},
|
|
29
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "7db0faf741993d729a9e1c0742f480f364816222"
|
|
30
32
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# ----------------------------
|
|
2
|
+
# 构建阶段
|
|
3
|
+
# ----------------------------
|
|
4
|
+
FROM oven/bun:latest AS builder
|
|
5
|
+
|
|
6
|
+
# 设置工作目录
|
|
7
|
+
ARG ROOT=app
|
|
8
|
+
WORKDIR /${ROOT}
|
|
9
|
+
|
|
10
|
+
COPY . .
|
|
11
|
+
|
|
12
|
+
# 替换 package.json 中的 workspace:* 为 *
|
|
13
|
+
RUN sed -i 's/"workspace:\*"/"*"/g' package.json
|
|
14
|
+
|
|
15
|
+
# 安装依赖
|
|
16
|
+
RUN bun install -f
|
|
17
|
+
|
|
18
|
+
# 构建
|
|
19
|
+
RUN bun -bun run build
|
|
20
|
+
|
|
21
|
+
# ----------------------------
|
|
22
|
+
# 运行阶段
|
|
23
|
+
# ----------------------------
|
|
24
|
+
FROM oven/bun:latest AS runner
|
|
25
|
+
|
|
26
|
+
ARG ROOT=app
|
|
27
|
+
WORKDIR /${ROOT}
|
|
28
|
+
|
|
29
|
+
# 只复制构建产物
|
|
30
|
+
COPY --from=builder /${ROOT}/.next/standalone ./
|
|
31
|
+
COPY --from=builder /${ROOT}/.next/static ./.next/static
|
|
32
|
+
|
|
33
|
+
# 开放端口
|
|
34
|
+
EXPOSE 3000
|
|
35
|
+
|
|
36
|
+
# 启动服务
|
|
37
|
+
CMD ["bun", "server.js"]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
2
|
+
import nextVitals from 'eslint-config-next/core-web-vitals'
|
|
3
|
+
import nextTs from 'eslint-config-next/typescript'
|
|
4
|
+
|
|
5
|
+
const eslintConfig = defineConfig([
|
|
6
|
+
...nextVitals,
|
|
7
|
+
...nextTs,
|
|
8
|
+
// 配置不参与 ESLint 检查的文件和目录
|
|
9
|
+
globalIgnores([
|
|
10
|
+
// 忽略 Next.js 构建产物目录
|
|
11
|
+
'.next/**',
|
|
12
|
+
// 忽略 Prisma 的 schema 文件
|
|
13
|
+
'prisma/**',
|
|
14
|
+
// 忽略其他构建产物目录
|
|
15
|
+
'build/**',
|
|
16
|
+
// 忽略 Next.js 自动生成的类型声明文件
|
|
17
|
+
'next-env.d.ts',
|
|
18
|
+
// 忽略自动生成的 API 代码
|
|
19
|
+
'src/server/generated/**',
|
|
20
|
+
]),
|
|
21
|
+
{
|
|
22
|
+
// 指定这组规则生效的文件类型
|
|
23
|
+
files: ['**/*.{js,ts,tsx,mts,cts}'],
|
|
24
|
+
// 配置代码解析相关选项
|
|
25
|
+
languageOptions: {
|
|
26
|
+
// 配置解析器参数
|
|
27
|
+
parserOptions: {
|
|
28
|
+
// 让 TypeScript 按项目服务模式提供类型信息
|
|
29
|
+
projectService: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
// 自定义需要关闭的 ESLint 规则
|
|
33
|
+
rules: {
|
|
34
|
+
// 允许匿名默认导出
|
|
35
|
+
'import/no-anonymous-default-export': 'off',
|
|
36
|
+
// 允许在 effect 里调用 setState
|
|
37
|
+
'react-hooks/set-state-in-effect': 'off',
|
|
38
|
+
// 不检查 hook 中的纯函数约束
|
|
39
|
+
'react-hooks/purity': 'off',
|
|
40
|
+
// 不限制 hook 中对 ref 的使用方式
|
|
41
|
+
'react-hooks/refs': 'off',
|
|
42
|
+
// 不强制 hook 中的数据保持不可变
|
|
43
|
+
'react-hooks/immutability': 'off',
|
|
44
|
+
// 不强制检查 effect 依赖项是否完整
|
|
45
|
+
'react-hooks/exhaustive-deps': 'off',
|
|
46
|
+
// 不强制组件设置 displayName
|
|
47
|
+
'react/display-name': 'off',
|
|
48
|
+
// 允许基础类型直接转成字符串
|
|
49
|
+
'@typescript-eslint/no-base-to-string': 'off',
|
|
50
|
+
// 不强制数组类型写法统一
|
|
51
|
+
'@typescript-eslint/array-type': 'off',
|
|
52
|
+
// 不强制统一使用 interface 或 type
|
|
53
|
+
'@typescript-eslint/consistent-type-definitions': 'off',
|
|
54
|
+
// 不强制统一使用 type import
|
|
55
|
+
'@typescript-eslint/consistent-type-imports': 'off',
|
|
56
|
+
// 不检查未使用的变量
|
|
57
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
58
|
+
// 允许没有 await 的 async 函数
|
|
59
|
+
'@typescript-eslint/require-await': 'off',
|
|
60
|
+
// 不严格检查 Promise 的误用场景
|
|
61
|
+
'@typescript-eslint/no-misused-promises': 'off',
|
|
62
|
+
// 允许使用 any 类型
|
|
63
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
64
|
+
// 不强制优先使用 ?? 运算符
|
|
65
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'off',
|
|
66
|
+
// 不检查不安全的对象属性访问
|
|
67
|
+
'@typescript-eslint/no-unsafe-member-access': 'off',
|
|
68
|
+
// 不检查不安全的函数参数传递
|
|
69
|
+
'@typescript-eslint/no-unsafe-argument': 'off',
|
|
70
|
+
// 允许使用 ts 注释指令
|
|
71
|
+
'@typescript-eslint/ban-ts-comment': 'off',
|
|
72
|
+
// 不检查不安全的函数调用
|
|
73
|
+
'@typescript-eslint/no-unsafe-call': 'off',
|
|
74
|
+
// 不检查不安全的赋值
|
|
75
|
+
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
76
|
+
// 不强制处理所有悬空 Promise
|
|
77
|
+
'@typescript-eslint/no-floating-promises': 'off',
|
|
78
|
+
// 不检查不安全的返回值
|
|
79
|
+
'@typescript-eslint/no-unsafe-return': 'off',
|
|
80
|
+
// 不检查多余的类型断言
|
|
81
|
+
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
|
82
|
+
// 不强制 Promise reject 使用 Error 对象
|
|
83
|
+
'@typescript-eslint/prefer-promise-reject-errors': 'off',
|
|
84
|
+
// 允许使用 namespace
|
|
85
|
+
'@typescript-eslint/no-namespace': 'off',
|
|
86
|
+
// 不强制索引对象写法统一
|
|
87
|
+
'@typescript-eslint/consistent-indexed-object-style': 'off',
|
|
88
|
+
// 允许显式声明可推断的类型
|
|
89
|
+
'@typescript-eslint/no-inferrable-types': 'off',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
])
|
|
93
|
+
|
|
94
|
+
export default eslintConfig
|