nsgm-cli 2.1.20 → 2.1.22

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.
Files changed (103) hide show
  1. package/README.md +40 -0
  2. package/client/components/Button.tsx +2 -4
  3. package/client/components/ClientProviders.tsx +12 -12
  4. package/client/components/LanguageSwitcher.tsx +26 -26
  5. package/client/components/SSRSafeAntdProvider.tsx +7 -7
  6. package/client/components/SuppressHydrationWarnings.tsx +30 -30
  7. package/client/components/__tests__/Button.test.tsx +12 -12
  8. package/client/layout/index.tsx +122 -124
  9. package/client/redux/reducers.ts +2 -2
  10. package/client/redux/store.ts +24 -24
  11. package/client/redux/template/manage/actions.ts +40 -40
  12. package/client/redux/template/manage/reducers.ts +32 -32
  13. package/client/redux/template/manage/types.ts +19 -19
  14. package/client/service/template/manage.ts +29 -29
  15. package/client/styled/common.ts +6 -6
  16. package/client/styled/layout/index.ts +17 -17
  17. package/client/styled/template/manage.ts +19 -19
  18. package/client/utils/common.ts +52 -54
  19. package/client/utils/cookie.ts +30 -30
  20. package/client/utils/fetch.ts +111 -111
  21. package/client/utils/i18n.ts +41 -41
  22. package/client/utils/menu.tsx +11 -12
  23. package/client/utils/navigation.ts +22 -22
  24. package/client/utils/sso.ts +124 -124
  25. package/client/utils/suppressWarnings.ts +17 -17
  26. package/generation/client/utils/menu.tsx +0 -1
  27. package/jest.config.js +4 -4
  28. package/lib/args.js +19 -19
  29. package/lib/cli/app.d.ts +1 -1
  30. package/lib/cli/app.js +2 -2
  31. package/lib/cli/commands/build.d.ts +1 -1
  32. package/lib/cli/commands/build.js +9 -9
  33. package/lib/cli/commands/create.d.ts +1 -1
  34. package/lib/cli/commands/create.js +36 -36
  35. package/lib/cli/commands/delete.d.ts +1 -1
  36. package/lib/cli/commands/delete.js +55 -55
  37. package/lib/cli/commands/export.d.ts +1 -1
  38. package/lib/cli/commands/export.js +12 -12
  39. package/lib/cli/commands/help.d.ts +1 -1
  40. package/lib/cli/commands/help.js +29 -29
  41. package/lib/cli/commands/init.d.ts +1 -1
  42. package/lib/cli/commands/init.js +31 -31
  43. package/lib/cli/commands/server.d.ts +1 -1
  44. package/lib/cli/commands/server.js +12 -12
  45. package/lib/cli/commands/upgrade.d.ts +1 -1
  46. package/lib/cli/commands/upgrade.js +13 -13
  47. package/lib/cli/commands/version.d.ts +1 -1
  48. package/lib/cli/commands/version.js +7 -7
  49. package/lib/cli/index.d.ts +13 -13
  50. package/lib/cli/parser.d.ts +1 -1
  51. package/lib/cli/parser.js +12 -12
  52. package/lib/cli/registry.d.ts +1 -1
  53. package/lib/cli/types.d.ts +2 -2
  54. package/lib/cli/utils/console.d.ts +2 -2
  55. package/lib/cli/utils/console.js +22 -22
  56. package/lib/cli/utils/index.d.ts +2 -2
  57. package/lib/cli/utils/prompt.d.ts +1 -1
  58. package/lib/cli/utils/prompt.js +98 -98
  59. package/lib/constants.js +28 -28
  60. package/lib/generate.d.ts +2 -2
  61. package/lib/generate.js +19 -19
  62. package/lib/generate_create.d.ts +1 -1
  63. package/lib/generate_create.js +38 -38
  64. package/lib/generate_delete.js +63 -63
  65. package/lib/generate_init.js +93 -93
  66. package/lib/generators/base-generator.d.ts +1 -1
  67. package/lib/generators/base-generator.js +23 -23
  68. package/lib/generators/file-generator.js +15 -15
  69. package/lib/generators/generator-factory.d.ts +5 -5
  70. package/lib/generators/i18n-generator.d.ts +1 -1
  71. package/lib/generators/i18n-generator.js +127 -127
  72. package/lib/generators/page-generator.d.ts +1 -1
  73. package/lib/generators/page-generator.js +25 -25
  74. package/lib/generators/resolver-generator.d.ts +1 -1
  75. package/lib/generators/resolver-generator.js +27 -27
  76. package/lib/generators/schema-generator.d.ts +1 -1
  77. package/lib/generators/schema-generator.js +4 -4
  78. package/lib/generators/service-generator.d.ts +1 -1
  79. package/lib/generators/service-generator.js +29 -29
  80. package/lib/generators/sql-generator.d.ts +1 -1
  81. package/lib/generators/sql-generator.js +10 -10
  82. package/lib/index.js +33 -30
  83. package/lib/server/csrf.d.ts +3 -3
  84. package/lib/server/csrf.js +20 -20
  85. package/lib/server/db.d.ts +1 -1
  86. package/lib/server/db.js +21 -21
  87. package/lib/server/graphql.js +26 -26
  88. package/lib/server/plugins/date.d.ts +1 -1
  89. package/lib/server/plugins/date.js +6 -6
  90. package/lib/server/utils/graphql-cache.js +5 -5
  91. package/lib/tsconfig.build.tsbuildinfo +1 -1
  92. package/lib/utils/project-config.d.ts +1 -1
  93. package/lib/utils/project-config.js +20 -20
  94. package/lib/utils.js +3 -3
  95. package/next-env.d.ts +1 -0
  96. package/next.config.js +15 -109
  97. package/package.json +5 -3
  98. package/pages/_app.tsx +62 -65
  99. package/pages/_document.tsx +14 -15
  100. package/pages/_error.tsx +25 -26
  101. package/pages/index.tsx +47 -48
  102. package/pages/login.tsx +64 -64
  103. package/pages/template/manage.tsx +175 -175
package/README.md CHANGED
@@ -383,6 +383,8 @@ npm run export
383
383
 
384
384
  ### Production Deployment
385
385
 
386
+ #### Local Deployment
387
+
386
388
  ```bash
387
389
  # Start production server
388
390
  npm start
@@ -391,6 +393,44 @@ npm start
391
393
  pm2 start npm --name "nsgm-app" -- start
392
394
  ```
393
395
 
396
+ #### Vercel Deployment (Recommended)
397
+
398
+ NSGM CLI 完全支持 Vercel 部署,包括自动化 CI/CD 流程。
399
+
400
+ **快速开始:**
401
+
402
+ 1. 推送项目到 GitHub
403
+ 2. 访问 [Vercel Dashboard](https://vercel.com/dashboard)
404
+ 3. 导入 GitHub 仓库
405
+ 4. 配置环境变量(参考 `.env.vercel.example`)
406
+ 5. 点击 "Deploy"
407
+
408
+ **详细指南:** 查看 [VERCEL_DEPLOYMENT.md](VERCEL_DEPLOYMENT.md)
409
+
410
+ **特性:**
411
+
412
+ - ✅ 自动 CI/CD 流程
413
+ - ✅ 预览环境(每个 PR)
414
+ - ✅ 自动 HTTPS
415
+ - ✅ 全球 CDN
416
+ - ✅ 无服务器函数
417
+ - ✅ 一键回滚
418
+
419
+ **环境变量配置:**
420
+
421
+ ```
422
+ NODE_ENV=production
423
+ LOGIN_USERNAME=admin
424
+ LOGIN_PASSWORD_HASH=your_hash
425
+ DATABASE_URL=mysql://...
426
+ ```
427
+
428
+ **获取密码哈希:**
429
+
430
+ ```bash
431
+ npm run generate-password yourPassword
432
+ ```
433
+
394
434
  ## 🤝 Contributing
395
435
 
396
436
  We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
@@ -1,6 +1,4 @@
1
1
  // src/components/Button.js
2
- import React from 'react'
2
+ const Button = ({ onClick, children }) => <button onClick={onClick}>{children}</button>;
3
3
 
4
- const Button = ({ onClick, children }) => <button onClick={onClick}>{children}</button>
5
-
6
- export default Button
4
+ export default Button;
@@ -1,20 +1,20 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { ThemeProvider } from 'styled-components'
3
- import { GlobalStyle } from '@/styled/common'
1
+ import React, { useEffect, useState } from "react";
2
+ import { ThemeProvider } from "styled-components";
3
+ import { GlobalStyle } from "@/styled/common";
4
4
 
5
5
  interface ClientProvidersProps {
6
- children: React.ReactNode
7
- theme: any
8
- whiteColor?: boolean
6
+ children: React.ReactNode;
7
+ theme: any;
8
+ whiteColor?: boolean;
9
9
  }
10
10
 
11
11
  const ClientProviders: React.FC<ClientProvidersProps> = ({ children, theme, whiteColor = true }) => {
12
- const [isClient, setIsClient] = useState(false)
12
+ const [isClient, setIsClient] = useState(false);
13
13
 
14
14
  useEffect(() => {
15
15
  // 使用更安全的客户端检测
16
- setIsClient(true)
17
- }, [])
16
+ setIsClient(true);
17
+ }, []);
18
18
 
19
19
  // 在服务端渲染时,使用一个占位符来保持结构一致性
20
20
  // 但不渲染可能引起 useLayoutEffect 警告的组件
@@ -23,7 +23,7 @@ const ClientProviders: React.FC<ClientProvidersProps> = ({ children, theme, whit
23
23
  {isClient && <GlobalStyle whiteColor={whiteColor} />}
24
24
  {children}
25
25
  </ThemeProvider>
26
- )
27
- }
26
+ );
27
+ };
28
28
 
29
- export default ClientProviders
29
+ export default ClientProviders;
@@ -1,40 +1,40 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { Select } from 'antd'
3
- import { useRouter } from 'next/router'
4
- import { GlobalOutlined } from '@ant-design/icons'
1
+ import React, { useEffect, useState } from "react";
2
+ import { Select } from "antd";
3
+ import { useRouter } from "next/router";
4
+ import { GlobalOutlined } from "@ant-design/icons";
5
5
 
6
- const { Option } = Select
6
+ const { Option } = Select;
7
7
 
8
8
  interface LanguageSwitcherProps {
9
- style?: React.CSSProperties
10
- size?: 'small' | 'middle' | 'large'
9
+ style?: React.CSSProperties;
10
+ size?: "small" | "middle" | "large";
11
11
  }
12
12
 
13
- const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({ style, size = 'middle' }) => {
14
- const router = useRouter()
15
- const [mounted, setMounted] = useState(false)
16
- const [currentLocale, setCurrentLocale] = useState('zh-CN')
13
+ const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({ style, size = "middle" }) => {
14
+ const router = useRouter();
15
+ const [mounted, setMounted] = useState(false);
16
+ const [currentLocale, setCurrentLocale] = useState("zh-CN");
17
17
 
18
18
  useEffect(() => {
19
- setMounted(true)
19
+ setMounted(true);
20
20
  // 只在客户端获取当前语言
21
- if (typeof window !== 'undefined' && router.locale) {
22
- setCurrentLocale(router.locale)
21
+ if (typeof window !== "undefined" && router.locale) {
22
+ setCurrentLocale(router.locale);
23
23
  }
24
- }, [router.locale])
24
+ }, [router.locale]);
25
25
 
26
26
  const languages = [
27
- { code: 'zh-CN', name: '中文', flag: '🇨🇳' },
28
- { code: 'en-US', name: 'English', flag: '🇺🇸' },
29
- { code: 'ja-JP', name: '日本語', flag: '🇯🇵' },
30
- ]
27
+ { code: "zh-CN", name: "中文", flag: "🇨🇳" },
28
+ { code: "en-US", name: "English", flag: "🇺🇸" },
29
+ { code: "ja-JP", name: "日本語", flag: "🇯🇵" },
30
+ ];
31
31
 
32
32
  const handleLanguageChange = (locale: string) => {
33
- if (mounted && typeof window !== 'undefined') {
34
- const { pathname, asPath, query } = router
35
- router.push({ pathname, query }, asPath, { locale })
33
+ if (mounted && typeof window !== "undefined") {
34
+ const { pathname, asPath, query } = router;
35
+ router.push({ pathname, query }, asPath, { locale });
36
36
  }
37
- }
37
+ };
38
38
 
39
39
  return (
40
40
  <Select
@@ -53,7 +53,7 @@ const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({ style, size = 'midd
53
53
  </Option>
54
54
  ))}
55
55
  </Select>
56
- )
57
- }
56
+ );
57
+ };
58
58
 
59
- export default LanguageSwitcher
59
+ export default LanguageSwitcher;
@@ -1,9 +1,9 @@
1
- import React from 'react'
2
- import { ConfigProvider } from 'antd'
1
+ import React from "react";
2
+ import { ConfigProvider } from "antd";
3
3
 
4
4
  interface SSRSafeAntdProviderProps {
5
- children: React.ReactNode
6
- locale?: any
5
+ children: React.ReactNode;
6
+ locale?: any;
7
7
  }
8
8
 
9
9
  const SSRSafeAntdProvider: React.FC<SSRSafeAntdProviderProps> = ({ children, locale }) => {
@@ -18,7 +18,7 @@ const SSRSafeAntdProvider: React.FC<SSRSafeAntdProviderProps> = ({ children, loc
18
18
  >
19
19
  {children}
20
20
  </ConfigProvider>
21
- )
22
- }
21
+ );
22
+ };
23
23
 
24
- export default SSRSafeAntdProvider
24
+ export default SSRSafeAntdProvider;
@@ -1,55 +1,55 @@
1
- import { useEffect } from 'react'
1
+ import { useEffect } from "react";
2
2
 
3
3
  // 全局抑制 useLayoutEffect 警告的函数
4
4
  const suppressUseLayoutEffectWarnings = () => {
5
- if (typeof window === 'undefined' && process.env.NODE_ENV === 'development') {
6
- const originalError = console.error
7
- const originalWarn = console.warn
5
+ if (typeof window === "undefined" && process.env.NODE_ENV === "development") {
6
+ const originalError = console.error;
7
+ const originalWarn = console.warn;
8
8
 
9
9
  console.error = (...args) => {
10
- const errorMessage = args[0]
10
+ const errorMessage = args[0];
11
11
  if (
12
- typeof errorMessage === 'string' &&
13
- (errorMessage.includes('useLayoutEffect does nothing on the server') ||
14
- errorMessage.includes('Warning: useLayoutEffect does nothing on the server'))
12
+ typeof errorMessage === "string" &&
13
+ (errorMessage.includes("useLayoutEffect does nothing on the server") ||
14
+ errorMessage.includes("Warning: useLayoutEffect does nothing on the server"))
15
15
  ) {
16
- return
16
+ return;
17
17
  }
18
- originalError.apply(console, args)
19
- }
18
+ originalError.apply(console, args);
19
+ };
20
20
 
21
21
  console.warn = (...args) => {
22
- const warnMessage = args[0]
22
+ const warnMessage = args[0];
23
23
  if (
24
- typeof warnMessage === 'string' &&
25
- (warnMessage.includes('useLayoutEffect does nothing on the server') ||
26
- warnMessage.includes('Warning: useLayoutEffect does nothing on the server'))
24
+ typeof warnMessage === "string" &&
25
+ (warnMessage.includes("useLayoutEffect does nothing on the server") ||
26
+ warnMessage.includes("Warning: useLayoutEffect does nothing on the server"))
27
27
  ) {
28
- return
28
+ return;
29
29
  }
30
- originalWarn.apply(console, args)
31
- }
30
+ originalWarn.apply(console, args);
31
+ };
32
32
 
33
33
  // 返回清理函数
34
34
  return () => {
35
- console.error = originalError
36
- console.warn = originalWarn
37
- }
35
+ console.error = originalError;
36
+ console.warn = originalWarn;
37
+ };
38
38
  }
39
- return undefined
40
- }
39
+ return undefined;
40
+ };
41
41
 
42
42
  // 在模块加载时立即执行
43
- suppressUseLayoutEffectWarnings()
43
+ suppressUseLayoutEffectWarnings();
44
44
 
45
45
  const SuppressHydrationWarnings = () => {
46
46
  useEffect(() => {
47
47
  // 在客户端也抑制这些警告(以防万一)
48
- const cleanup = suppressUseLayoutEffectWarnings()
49
- return cleanup
50
- }, [])
48
+ const cleanup = suppressUseLayoutEffectWarnings();
49
+ return cleanup;
50
+ }, []);
51
51
 
52
- return null
53
- }
52
+ return null;
53
+ };
54
54
 
55
- export default SuppressHydrationWarnings
55
+ export default SuppressHydrationWarnings;
@@ -1,15 +1,15 @@
1
1
  // src/components/Button.test.js
2
- import { render, screen, fireEvent } from '@testing-library/react'
3
- import Button from '../Button'
2
+ import { render, screen, fireEvent } from "@testing-library/react";
3
+ import Button from "../Button";
4
4
 
5
- test('renders button with text', () => {
6
- render(<Button>Click me</Button>)
7
- expect(screen.getByText('Click me')).toBeInTheDocument()
8
- })
5
+ test("renders button with text", () => {
6
+ render(<Button>Click me</Button>);
7
+ expect(screen.getByText("Click me")).toBeInTheDocument();
8
+ });
9
9
 
10
- test('calls onClick when clicked', () => {
11
- const handleClick = jest.fn()
12
- render(<Button onClick={handleClick}>Click me</Button>)
13
- fireEvent.click(screen.getByText('Click me'))
14
- expect(handleClick).toHaveBeenCalledTimes(1)
15
- })
10
+ test("calls onClick when clicked", () => {
11
+ const handleClick = jest.fn();
12
+ render(<Button onClick={handleClick}>Click me</Button>);
13
+ fireEvent.click(screen.getByText("Click me"));
14
+ expect(handleClick).toHaveBeenCalledTimes(1);
15
+ });