@qlover/create-app 0.0.1

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 (144) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/bin/create-app.js +28 -0
  3. package/dist/cjs/index.d.ts +67 -0
  4. package/dist/cjs/index.js +1 -0
  5. package/dist/es/index.d.ts +67 -0
  6. package/dist/es/index.js +1 -0
  7. package/package.json +60 -0
  8. package/templates/fe-react/.env +3 -0
  9. package/templates/fe-react/README.md +50 -0
  10. package/templates/fe-react/config/app.common.ts +52 -0
  11. package/templates/fe-react/config/app.router.json +150 -0
  12. package/templates/fe-react/config/feapi.mock.json +14 -0
  13. package/templates/fe-react/config/i18n.ts +21 -0
  14. package/templates/fe-react/config/theme.json +90 -0
  15. package/templates/fe-react/eslint.config.js +31 -0
  16. package/templates/fe-react/index.html +13 -0
  17. package/templates/fe-react/lib/fe-react-controller/FeController.ts +15 -0
  18. package/templates/fe-react/lib/fe-react-controller/index.ts +2 -0
  19. package/templates/fe-react/lib/fe-react-controller/useController.ts +71 -0
  20. package/templates/fe-react/lib/fe-react-theme/ThemeController.ts +40 -0
  21. package/templates/fe-react/lib/fe-react-theme/ThemeStateGetter.ts +53 -0
  22. package/templates/fe-react/lib/fe-react-theme/index.ts +3 -0
  23. package/templates/fe-react/lib/fe-react-theme/tw-generator.js +239 -0
  24. package/templates/fe-react/lib/fe-react-theme/type.ts +21 -0
  25. package/templates/fe-react/lib/openAiApi/OpenAIAuthPlugin.ts +29 -0
  26. package/templates/fe-react/lib/openAiApi/OpenAIClient.ts +51 -0
  27. package/templates/fe-react/lib/openAiApi/StreamProcessor.ts +81 -0
  28. package/templates/fe-react/lib/openAiApi/index.ts +3 -0
  29. package/templates/fe-react/lib/request-common-plugin/index.ts +169 -0
  30. package/templates/fe-react/lib/tw-root10px/index.css +4 -0
  31. package/templates/fe-react/lib/tw-root10px/index.js +178 -0
  32. package/templates/fe-react/package.json +49 -0
  33. package/templates/fe-react/postcss.config.js +6 -0
  34. package/templates/fe-react/public/locales/en/about.json +3 -0
  35. package/templates/fe-react/public/locales/en/common.json +6 -0
  36. package/templates/fe-react/public/locales/en/executor.json +6 -0
  37. package/templates/fe-react/public/locales/en/home.json +10 -0
  38. package/templates/fe-react/public/locales/en/jsonStorage.json +11 -0
  39. package/templates/fe-react/public/locales/en/login.json +7 -0
  40. package/templates/fe-react/public/locales/en/request.json +15 -0
  41. package/templates/fe-react/public/locales/zh/about.json +3 -0
  42. package/templates/fe-react/public/locales/zh/common.json +7 -0
  43. package/templates/fe-react/public/locales/zh/executor.json +7 -0
  44. package/templates/fe-react/public/locales/zh/home.json +10 -0
  45. package/templates/fe-react/public/locales/zh/jsonStorage.json +11 -0
  46. package/templates/fe-react/public/locales/zh/login.json +8 -0
  47. package/templates/fe-react/public/locales/zh/request.json +15 -0
  48. package/templates/fe-react/public/logo.svg +1 -0
  49. package/templates/fe-react/src/App.tsx +20 -0
  50. package/templates/fe-react/src/assets/react.svg +1 -0
  51. package/templates/fe-react/src/components/Loading.tsx +41 -0
  52. package/templates/fe-react/src/components/LocaleLink.tsx +42 -0
  53. package/templates/fe-react/src/components/ProcessProvider.tsx +41 -0
  54. package/templates/fe-react/src/components/ThemeSwitcher.tsx +29 -0
  55. package/templates/fe-react/src/containers/context/BaseRouteContext.ts +27 -0
  56. package/templates/fe-react/src/containers/context/BaseRouteProvider.tsx +11 -0
  57. package/templates/fe-react/src/containers/globals.ts +31 -0
  58. package/templates/fe-react/src/containers/index.ts +71 -0
  59. package/templates/fe-react/src/hooks/useLanguageGuard.ts +25 -0
  60. package/templates/fe-react/src/hooks/useStrictEffect.ts +29 -0
  61. package/templates/fe-react/src/main.tsx +15 -0
  62. package/templates/fe-react/src/pages/404.tsx +14 -0
  63. package/templates/fe-react/src/pages/500.tsx +14 -0
  64. package/templates/fe-react/src/pages/auth/Layout.tsx +14 -0
  65. package/templates/fe-react/src/pages/auth/Login.tsx +62 -0
  66. package/templates/fe-react/src/pages/auth/Register.tsx +3 -0
  67. package/templates/fe-react/src/pages/base/About.tsx +12 -0
  68. package/templates/fe-react/src/pages/base/Executor.tsx +38 -0
  69. package/templates/fe-react/src/pages/base/Home.tsx +78 -0
  70. package/templates/fe-react/src/pages/base/JSONStorage.tsx +124 -0
  71. package/templates/fe-react/src/pages/base/Layout.tsx +17 -0
  72. package/templates/fe-react/src/pages/base/RedirectPathname.tsx +15 -0
  73. package/templates/fe-react/src/pages/base/Request.tsx +91 -0
  74. package/templates/fe-react/src/pages/base/components/BaseHeader.tsx +19 -0
  75. package/templates/fe-react/src/pages/index.tsx +108 -0
  76. package/templates/fe-react/src/services/controllers/ExecutorController.ts +56 -0
  77. package/templates/fe-react/src/services/controllers/JSONStorageController.ts +42 -0
  78. package/templates/fe-react/src/services/controllers/RequestController.ts +105 -0
  79. package/templates/fe-react/src/services/controllers/RouterController.ts +90 -0
  80. package/templates/fe-react/src/services/controllers/UserController.ts +146 -0
  81. package/templates/fe-react/src/services/feApi/FeApi.ts +51 -0
  82. package/templates/fe-react/src/services/feApi/FeApiMockPlugin.ts +42 -0
  83. package/templates/fe-react/src/services/feApi/FeApiType.ts +55 -0
  84. package/templates/fe-react/src/services/feApi/index.ts +2 -0
  85. package/templates/fe-react/src/services/i18n/index.ts +50 -0
  86. package/templates/fe-react/src/services/pageProcesser/PageProcesser.ts +29 -0
  87. package/templates/fe-react/src/services/pageProcesser/index.ts +1 -0
  88. package/templates/fe-react/src/styles/css/index.css +2 -0
  89. package/templates/fe-react/src/styles/css/page.css +3 -0
  90. package/templates/fe-react/src/styles/css/tailwind.css +3 -0
  91. package/templates/fe-react/src/types/Page.ts +49 -0
  92. package/templates/fe-react/src/types/UIDependenciesInterface.ts +31 -0
  93. package/templates/fe-react/src/types/global.d.ts +7 -0
  94. package/templates/fe-react/src/utils/RequestLogger.ts +34 -0
  95. package/templates/fe-react/src/utils/datetime.ts +25 -0
  96. package/templates/fe-react/src/utils/thread.ts +3 -0
  97. package/templates/fe-react/src/vite-env.d.ts +1 -0
  98. package/templates/fe-react/tailwind.config.js +18 -0
  99. package/templates/fe-react/tsconfig.app.json +29 -0
  100. package/templates/fe-react/tsconfig.json +7 -0
  101. package/templates/fe-react/tsconfig.node.json +22 -0
  102. package/templates/fe-react/vite.config.ts +32 -0
  103. package/templates/pack-app/.editorconfig +23 -0
  104. package/templates/pack-app/.env +5 -0
  105. package/templates/pack-app/.env.template +6 -0
  106. package/templates/pack-app/.gitattributes +2 -0
  107. package/templates/pack-app/.github/workflows/general-check.yml +50 -0
  108. package/templates/pack-app/.github/workflows/release.yml.template +110 -0
  109. package/templates/pack-app/.prettierignore +5 -0
  110. package/templates/pack-app/.prettierrc.js +3 -0
  111. package/templates/pack-app/CHANGELOG.md +0 -0
  112. package/templates/pack-app/README.md +1 -0
  113. package/templates/pack-app/eslint.config.js +77 -0
  114. package/templates/pack-app/fe-config.json +10 -0
  115. package/templates/pack-app/jest.config.js +31 -0
  116. package/templates/pack-app/package.json +66 -0
  117. package/templates/pack-app/packages/browser/__tests__/calc.test.ts +9 -0
  118. package/templates/pack-app/packages/browser/package.json +11 -0
  119. package/templates/pack-app/packages/browser/rollup.config.js +70 -0
  120. package/templates/pack-app/packages/browser/src/calc.ts +3 -0
  121. package/templates/pack-app/packages/browser/src/index.ts +1 -0
  122. package/templates/pack-app/packages/browser/tsconfig.json +15 -0
  123. package/templates/pack-app/packages/node/__tests__/readJson.test.ts +25 -0
  124. package/templates/pack-app/packages/node/package.json +11 -0
  125. package/templates/pack-app/packages/node/rollup.config.js +89 -0
  126. package/templates/pack-app/packages/node/src/index.ts +7 -0
  127. package/templates/pack-app/packages/node/src/readJson.ts +6 -0
  128. package/templates/pack-app/packages/node/tsconfig.json +17 -0
  129. package/templates/pack-app/packages/react-vite-lib/README.md +50 -0
  130. package/templates/pack-app/packages/react-vite-lib/__tests__/Sum.test.ts +9 -0
  131. package/templates/pack-app/packages/react-vite-lib/__tests__/Text.test.tsx +11 -0
  132. package/templates/pack-app/packages/react-vite-lib/eslint.config.js +28 -0
  133. package/templates/pack-app/packages/react-vite-lib/index.html +13 -0
  134. package/templates/pack-app/packages/react-vite-lib/package.json +30 -0
  135. package/templates/pack-app/packages/react-vite-lib/public/vite.svg +1 -0
  136. package/templates/pack-app/packages/react-vite-lib/src/calc.ts +3 -0
  137. package/templates/pack-app/packages/react-vite-lib/src/commponents/Text.tsx +7 -0
  138. package/templates/pack-app/packages/react-vite-lib/src/index.ts +2 -0
  139. package/templates/pack-app/packages/react-vite-lib/src/vite-env.d.ts +1 -0
  140. package/templates/pack-app/packages/react-vite-lib/tsconfig.json +25 -0
  141. package/templates/pack-app/packages/react-vite-lib/vite.config.ts +24 -0
  142. package/templates/pack-app/pnpm-workspace.yaml +2 -0
  143. package/templates/pack-app/tsconfig.json +9 -0
  144. package/templates/pack-app/tsconfig.test.json +10 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+
2
+
3
+ ## 0.0.1 (2025-01-14)
4
+
5
+ ## 0.0.2 (2025-01-14)
6
+
7
+
8
+ ### Features
9
+
10
+ * create fe app ([#200](https://github.com/qlover/fe-base/issues/200)) ([8d3668f](https://github.com/qlover/fe-base/commit/8d3668f0e69a579994a72fc7b36b5ba7d5633c70))
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join } from 'path';
5
+ import { Generator } from '../dist/es/index.js';
6
+ import { existsSync } from 'fs';
7
+
8
+ async function main() {
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const templatePath = join(__dirname, '../templates');
11
+
12
+ const options = {
13
+ options: {
14
+ templatePath
15
+ }
16
+ };
17
+
18
+ if (!existsSync(templatePath)) {
19
+ console.error('Template is empty!');
20
+ process.exit(1);
21
+ }
22
+
23
+ const generator = new Generator(options);
24
+
25
+ await generator.generate();
26
+ }
27
+
28
+ main();
@@ -0,0 +1,67 @@
1
+ import { FeScriptContext } from '@qlover/fe-scripts';
2
+ import { Logger } from '@qlover/fe-utils';
3
+ import { DistinctQuestion } from 'inquirer';
4
+ import ignore from 'ignore';
5
+
6
+ type GeneratorOptions = {
7
+ prompts?: DistinctQuestion[];
8
+ templatePath: string;
9
+ };
10
+ interface GeneratorResult {
11
+ name: string;
12
+ templateName: string;
13
+ }
14
+ type TaskOptions = {
15
+ templateFiles: TemplateFile[];
16
+ result: GeneratorResult;
17
+ };
18
+ type TemplateFile = {
19
+ path: string;
20
+ content: string;
21
+ };
22
+ declare class Generator {
23
+ private prompts;
24
+ private ora;
25
+ protected context: FeScriptContext<GeneratorOptions>;
26
+ constructor(context: Partial<FeScriptContext<GeneratorOptions>>);
27
+ get logger(): Logger;
28
+ steps(prompts: DistinctQuestion[]): Promise<GeneratorResult>;
29
+ getTemplateFiles(path: string): Promise<TemplateFile[]>;
30
+ action({ label, task }: {
31
+ label: string;
32
+ task: () => Promise<unknown>;
33
+ }): Promise<unknown>;
34
+ /**
35
+ * Creates files and directories based on the provided template files.
36
+ *
37
+ * This method iterates through the template files and writes their content
38
+ * to the file system. It handles both files and directories, ensuring that
39
+ * the directory structure is preserved.
40
+ *
41
+ * @param templateFiles - An array of template files to be created.
42
+ * @param result - The result object containing the name and template name.
43
+ *
44
+ * @returns A promise that resolves when all files have been created.
45
+ *
46
+ * @example
47
+ * const templateFiles = [{ type: 'file', name: 'example.txt', content: 'Hello World' }];
48
+ * await taskCreate({ templateFiles, result });
49
+ */
50
+ create(targetPath: string, name: string): Promise<void>;
51
+ generate(): Promise<void>;
52
+ }
53
+
54
+ declare const validRequiredString: (value: string, key: string) => string | true;
55
+
56
+ declare class Copyer {
57
+ getIg(targetDir: string): ignore.Ignore;
58
+ /**
59
+ * copy templates recursively
60
+ * @param {string} templatesDir - source directory
61
+ * @param {string} targetDir - target directory
62
+ * @param {ignore.Ignore} ig - ignore rules
63
+ */
64
+ copyTemplates(templatesDir: string, targetDir: string, ig: ignore.Ignore): void;
65
+ }
66
+
67
+ export { Copyer, Generator, type GeneratorOptions, type GeneratorResult, type TaskOptions, type TemplateFile, validRequiredString };
@@ -0,0 +1 @@
1
+ "use strict";var t=require("@qlover/fe-scripts"),e=require("inquirer"),r=require("path"),o=require("ora"),i=require("fs"),n=require("ignore");function s(t,e,r,o){return new(r||(r=Promise))((function(i,n){function s(t){try{c(o.next(t))}catch(t){n(t)}}function a(t){try{c(o.throw(t))}catch(t){n(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(s,a)}c((o=o.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const a=(t,e)=>"string"==typeof t&&""!==t.trim()||`${e} is required`,c=[{type:"input",name:"name",message:"Project name",validate:t=>a(t,"Project name")},{type:"list",name:"templateName",message:"Template name",choices:["fe-react","pack-app"]}];class p{getIg(t){const e=r.join(t,".gitignore"),o=i.readFileSync(e,"utf8").split("\n").map((t=>t.trim())).filter((t=>t&&!t.startsWith("#")));return n().add(o)}copyTemplates(t,e,o){const n=i.readdirSync(t);for(const s of n){const n=r.join(t,s),a=r.join(e,s);if(o.ignores(s))continue;const c=r.dirname(a);i.existsSync(c)||i.mkdirSync(c,{recursive:!0}),i.statSync(n).isDirectory()?this.copyTemplates(n,a,o):i.copyFileSync(n,a)}}}exports.Copyer=p,exports.Generator=class{constructor(e){var r,n;this.prompts=[];const s=null===(r=e.options)||void 0===r?void 0:r.templatePath;if(!s)throw new Error("template path not exit");if(!i.existsSync(s))throw new Error("template path not exit");this.ora=o.oraPromise,this.context=new t.FeScriptContext(e),this.prompts=(null===(n=e.options)||void 0===n?void 0:n.prompts)||c}get logger(){return this.context.logger}steps(t){return s(this,void 0,void 0,(function*(){try{return yield e.prompt(t)}catch(t){throw this.logger.error(t),t}}))}getTemplateFiles(t){return s(this,void 0,void 0,(function*(){return console.log("jj paths",t),[]}))}action(t){return s(this,arguments,void 0,(function*({label:t,task:e}){let r=e();r instanceof Promise||(r=Promise.resolve(r));const o=t;return this.ora(r,o),r}))}create(t,e){return s(this,void 0,void 0,(function*(){const r=new p;r.copyTemplates(t,e,r.getIg(t))}))}generate(){return s(this,void 0,void 0,(function*(){const{templatePath:t}=this.context.options,e=yield this.steps(this.prompts);this.logger.info(e);const o=r.join(t,e.templateName);yield this.action({label:"Creating project",task:()=>this.create(o,e.name)})}))}},exports.validRequiredString=a;
@@ -0,0 +1,67 @@
1
+ import { FeScriptContext } from '@qlover/fe-scripts';
2
+ import { Logger } from '@qlover/fe-utils';
3
+ import { DistinctQuestion } from 'inquirer';
4
+ import ignore from 'ignore';
5
+
6
+ type GeneratorOptions = {
7
+ prompts?: DistinctQuestion[];
8
+ templatePath: string;
9
+ };
10
+ interface GeneratorResult {
11
+ name: string;
12
+ templateName: string;
13
+ }
14
+ type TaskOptions = {
15
+ templateFiles: TemplateFile[];
16
+ result: GeneratorResult;
17
+ };
18
+ type TemplateFile = {
19
+ path: string;
20
+ content: string;
21
+ };
22
+ declare class Generator {
23
+ private prompts;
24
+ private ora;
25
+ protected context: FeScriptContext<GeneratorOptions>;
26
+ constructor(context: Partial<FeScriptContext<GeneratorOptions>>);
27
+ get logger(): Logger;
28
+ steps(prompts: DistinctQuestion[]): Promise<GeneratorResult>;
29
+ getTemplateFiles(path: string): Promise<TemplateFile[]>;
30
+ action({ label, task }: {
31
+ label: string;
32
+ task: () => Promise<unknown>;
33
+ }): Promise<unknown>;
34
+ /**
35
+ * Creates files and directories based on the provided template files.
36
+ *
37
+ * This method iterates through the template files and writes their content
38
+ * to the file system. It handles both files and directories, ensuring that
39
+ * the directory structure is preserved.
40
+ *
41
+ * @param templateFiles - An array of template files to be created.
42
+ * @param result - The result object containing the name and template name.
43
+ *
44
+ * @returns A promise that resolves when all files have been created.
45
+ *
46
+ * @example
47
+ * const templateFiles = [{ type: 'file', name: 'example.txt', content: 'Hello World' }];
48
+ * await taskCreate({ templateFiles, result });
49
+ */
50
+ create(targetPath: string, name: string): Promise<void>;
51
+ generate(): Promise<void>;
52
+ }
53
+
54
+ declare const validRequiredString: (value: string, key: string) => string | true;
55
+
56
+ declare class Copyer {
57
+ getIg(targetDir: string): ignore.Ignore;
58
+ /**
59
+ * copy templates recursively
60
+ * @param {string} templatesDir - source directory
61
+ * @param {string} targetDir - target directory
62
+ * @param {ignore.Ignore} ig - ignore rules
63
+ */
64
+ copyTemplates(templatesDir: string, targetDir: string, ig: ignore.Ignore): void;
65
+ }
66
+
67
+ export { Copyer, Generator, type GeneratorOptions, type GeneratorResult, type TaskOptions, type TemplateFile, validRequiredString };
@@ -0,0 +1 @@
1
+ import{FeScriptContext as t}from"@qlover/fe-scripts";import e from"inquirer";import{join as o,dirname as r}from"path";import{oraPromise as i}from"ora";import{readFileSync as n,readdirSync as s,existsSync as a,mkdirSync as p,statSync as c,copyFileSync as m}from"fs";import l from"ignore";function u(t,e,o,r){return new(o||(o=Promise))((function(i,n){function s(t){try{p(r.next(t))}catch(t){n(t)}}function a(t){try{p(r.throw(t))}catch(t){n(t)}}function p(t){var e;t.done?i(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(s,a)}p((r=r.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const h=(t,e)=>"string"==typeof t&&""!==t.trim()||`${e} is required`,f=[{type:"input",name:"name",message:"Project name",validate:t=>h(t,"Project name")},{type:"list",name:"templateName",message:"Template name",choices:["fe-react","pack-app"]}];class g{getIg(t){const e=o(t,".gitignore"),r=n(e,"utf8").split("\n").map((t=>t.trim())).filter((t=>t&&!t.startsWith("#")));return l().add(r)}copyTemplates(t,e,i){const n=s(t);for(const s of n){const n=o(t,s),l=o(e,s);if(i.ignores(s))continue;const u=r(l);a(u)||p(u,{recursive:!0}),c(n).isDirectory()?this.copyTemplates(n,l,i):m(n,l)}}}class d{constructor(e){var o,r;this.prompts=[];const n=null===(o=e.options)||void 0===o?void 0:o.templatePath;if(!n)throw new Error("template path not exit");if(!a(n))throw new Error("template path not exit");this.ora=i,this.context=new t(e),this.prompts=(null===(r=e.options)||void 0===r?void 0:r.prompts)||f}get logger(){return this.context.logger}steps(t){return u(this,void 0,void 0,(function*(){try{return yield e.prompt(t)}catch(t){throw this.logger.error(t),t}}))}getTemplateFiles(t){return u(this,void 0,void 0,(function*(){return console.log("jj paths",t),[]}))}action(t){return u(this,arguments,void 0,(function*({label:t,task:e}){let o=e();o instanceof Promise||(o=Promise.resolve(o));const r=t;return this.ora(o,r),o}))}create(t,e){return u(this,void 0,void 0,(function*(){const o=new g;o.copyTemplates(t,e,o.getIg(t))}))}generate(){return u(this,void 0,void 0,(function*(){const{templatePath:t}=this.context.options,e=yield this.steps(this.prompts);this.logger.info(e);const r=o(t,e.templateName);yield this.action({label:"Creating project",task:()=>this.create(r,e.name)})}))}}export{g as Copyer,d as Generator,h as validRequiredString};
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@qlover/create-app",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "private": false,
6
+ "main": "./dist/es/index.js",
7
+ "module": "./dist/es/index.js",
8
+ "types": "./dist/es/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/es/index.js",
12
+ "require": "./dist/cjs/index.js",
13
+ "types": "./dist/es/index.d.ts"
14
+ },
15
+ "./cjs/*": "./dist/cjs/*",
16
+ "./es/*": "./dist/es/*",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "bin",
22
+ "templates",
23
+ "package.json",
24
+ "README.md",
25
+ "CHANGELOG.md"
26
+ ],
27
+ "bin": {
28
+ "create-app": "./bin/create-app.js"
29
+ },
30
+ "scripts": {
31
+ "build": "node ./scripts/copy-templates.js && rollup -c"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/qlover/fe-base.git",
36
+ "directory": "packages/create-app"
37
+ },
38
+ "homepage": "https://github.com/qlover/fe-base#readme",
39
+ "keywords": [
40
+ "create-app",
41
+ "fe-scripts",
42
+ "scripts"
43
+ ],
44
+ "author": "qlover",
45
+ "license": "ISC",
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "dependencies": {
50
+ "@octokit/graphql": "^8.1.2",
51
+ "@octokit/rest": "^21.1.0",
52
+ "@qlover/fe-scripts": "^0.5.2",
53
+ "@qlover/fe-utils": "^1.1.3",
54
+ "ignore": "^7.0.3",
55
+ "inquirer": "^12.3.2"
56
+ },
57
+ "devDependencies": {
58
+ "ora": "^8.1.1"
59
+ }
60
+ }
@@ -0,0 +1,3 @@
1
+ VITE_SERVER_PORT=3200
2
+ VITE_OPENAI_API_URL=
3
+ VITE_OPENAI_API_KEY=
@@ -0,0 +1,50 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## Expanding the ESLint configuration
11
+
12
+ If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13
+
14
+ - Configure the top-level `parserOptions` property like this:
15
+
16
+ ```js
17
+ export default tseslint.config({
18
+ languageOptions: {
19
+ // other options...
20
+ parserOptions: {
21
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
22
+ tsconfigRootDir: import.meta.dirname,
23
+ },
24
+ },
25
+ })
26
+ ```
27
+
28
+ - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29
+ - Optionally add `...tseslint.configs.stylisticTypeChecked`
30
+ - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31
+
32
+ ```js
33
+ // eslint.config.js
34
+ import react from 'eslint-plugin-react'
35
+
36
+ export default tseslint.config({
37
+ // Set the react version
38
+ settings: { react: { version: '18.3' } },
39
+ plugins: {
40
+ // Add the react plugin
41
+ react,
42
+ },
43
+ rules: {
44
+ // other rules...
45
+ // Enable its recommended rules
46
+ ...react.configs.recommended.rules,
47
+ ...react.configs['jsx-runtime'].rules,
48
+ },
49
+ })
50
+ ```
@@ -0,0 +1,52 @@
1
+ import { i18nConfig } from '@config/i18n';
2
+ import { OpenAIClientConfig } from '@lib/openAiApi';
3
+ import { RequestCommonPluginConfig } from '@lib/request-common-plugin';
4
+ import { RequestAdapterFetchConfig } from '@qlover/fe-utils';
5
+
6
+ export const openAiModels = [
7
+ 'gpt-3.5-turbo',
8
+ 'gpt-3.5-turbo-2',
9
+ 'gpt-4',
10
+ 'gpt-4-32k'
11
+ ];
12
+
13
+ export const requestCommonPluginConfig: RequestCommonPluginConfig = {
14
+ tokenPrefix: 'Bearer',
15
+ defaultHeaders: {
16
+ 'Content-Type': 'application/json'
17
+ },
18
+ defaultRequestData: {
19
+ model: 'gpt-4o-mini',
20
+ stream: true
21
+ },
22
+ requiredToken: true,
23
+ token: import.meta.env.VITE_OPENAI_API_KEY
24
+ };
25
+
26
+ export const openAiConfig: OpenAIClientConfig = {
27
+ baseURL: import.meta.env.VITE_OPENAI_API_URL,
28
+ models: openAiModels,
29
+ commonPluginConfig: requestCommonPluginConfig
30
+ };
31
+
32
+ export const defaultBaseRoutemeta = {
33
+ localNamespace: i18nConfig.defaultNS,
34
+ title: '',
35
+ icon: ''
36
+ } as const;
37
+
38
+ export const defaultLoginInfo = {
39
+ name: 'qlover',
40
+ password: 'q1234566'
41
+ };
42
+
43
+ export const defaultFeApiConfig: {
44
+ adapter: Partial<RequestAdapterFetchConfig>;
45
+ commonPluginConfig: RequestCommonPluginConfig;
46
+ } = {
47
+ adapter: {
48
+ responseType: 'json',
49
+ baseURL: 'https://api.example.com/'
50
+ },
51
+ commonPluginConfig: requestCommonPluginConfig
52
+ };
@@ -0,0 +1,150 @@
1
+ {
2
+ "base": {
3
+ "routes": [
4
+ {
5
+ "path": "/",
6
+ "element": "base/RedirectPathname",
7
+ "meta": {
8
+ "category": "main"
9
+ }
10
+ },
11
+ {
12
+ "path": "/:lng",
13
+ "element": "base/Layout",
14
+ "meta": {
15
+ "category": "main"
16
+ },
17
+ "children": [
18
+ {
19
+ "index": true,
20
+ "element": "base/Home",
21
+ "meta": {
22
+ "title": "fe-utils/home",
23
+ "icon": "home",
24
+ "localNamespace": "home"
25
+ }
26
+ },
27
+ {
28
+ "path": "about",
29
+ "element": "base/About",
30
+ "meta": {
31
+ "title": "关于",
32
+ "icon": "info",
33
+ "localNamespace": "about"
34
+ }
35
+ },
36
+ {
37
+ "path": "jsonStorage",
38
+ "element": "base/JSONStorage",
39
+ "meta": {
40
+ "title": "FE-Utils JSONStorage",
41
+ "icon": "info",
42
+ "localNamespace": "jsonStorage"
43
+ }
44
+ },
45
+ {
46
+ "path": "request",
47
+ "element": "base/Request",
48
+ "meta": {
49
+ "title": "FE-Utils Request",
50
+ "icon": "info",
51
+ "localNamespace": "request"
52
+ }
53
+ },
54
+ {
55
+ "path": "executor",
56
+ "element": "base/Executor",
57
+ "meta": {
58
+ "title": "FE-Utils Executor",
59
+ "icon": "info",
60
+ "localNamespace": "executor"
61
+ }
62
+ },
63
+ {
64
+ "path": "404",
65
+ "element": "404",
66
+ "meta": {
67
+ "category": "common",
68
+ "title": "404",
69
+ "layout": "blank",
70
+ "localNamespace": "common"
71
+ }
72
+ },
73
+ {
74
+ "path": "500",
75
+ "element": "500",
76
+ "meta": {
77
+ "category": "common",
78
+ "title": "500",
79
+ "layout": "blank",
80
+ "localNamespace": "common"
81
+ }
82
+ }
83
+ ]
84
+ },
85
+
86
+ {
87
+ "path": "/:lng",
88
+ "element": "auth/Layout",
89
+ "meta": {
90
+ "category": "auth"
91
+ },
92
+ "children": [
93
+ {
94
+ "index": true,
95
+ "element": "auth/Login"
96
+ },
97
+ {
98
+ "path": "login",
99
+ "element": "auth/Login",
100
+ "meta": {
101
+ "title": "登录",
102
+ "icon": "info",
103
+ "localNamespace": "login"
104
+ }
105
+ },
106
+ {
107
+ "path": "register",
108
+ "element": "auth/Register",
109
+ "meta": {
110
+ "title": "注册",
111
+ "icon": "info",
112
+ "localNamespace": "register"
113
+ }
114
+ }
115
+ ]
116
+ },
117
+
118
+ {
119
+ "path": "404",
120
+ "element": "404",
121
+ "meta": {
122
+ "category": "common",
123
+ "title": "404",
124
+ "layout": "blank",
125
+ "localNamespace": "common"
126
+ }
127
+ },
128
+ {
129
+ "path": "500",
130
+ "element": "500",
131
+ "meta": {
132
+ "category": "common",
133
+ "title": "500",
134
+ "layout": "blank",
135
+ "localNamespace": "common"
136
+ }
137
+ },
138
+ {
139
+ "path": "*",
140
+ "element": "404",
141
+ "meta": {
142
+ "category": "common",
143
+ "title": "404",
144
+ "layout": "blank",
145
+ "localNamespace": "common"
146
+ }
147
+ }
148
+ ]
149
+ }
150
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "_default": {
3
+ "mock": true,
4
+ "noUrl": true
5
+ },
6
+ "GET https://api.example.com/api/userinfo": {
7
+ "name": "John Doe",
8
+ "email": "john.doe@example.com",
9
+ "picture": "https://randomuser.me/api/portraits/men/1.jpg"
10
+ },
11
+ "POST https://api.example.com/api/login": {
12
+ "token": "asdfasdf123123asdfasdf"
13
+ }
14
+ }
@@ -0,0 +1,21 @@
1
+ import { isProduction } from "@/containers/globals";
2
+
3
+ /** @type {import('i18next').InitOptions} */
4
+ export const i18nConfig = {
5
+ /**
6
+ * default language
7
+ */
8
+ fallbackLng: 'en',
9
+ debug: !isProduction,
10
+ interpolation: {
11
+ escapeValue: false // React already does escaping
12
+ },
13
+ ns: ['common'],
14
+ defaultNS: 'common',
15
+ backend: {
16
+ loadPath: '/locales/{{lng}}/{{ns}}.json'
17
+ },
18
+ supportedLngs: ['en', 'zh']
19
+ } as const;
20
+
21
+ export type I18nServiceLocale = (typeof i18nConfig.supportedLngs)[number];
@@ -0,0 +1,90 @@
1
+ {
2
+ "base": {
3
+ "domAttribute": "data-theme",
4
+ "defaultTheme": "system",
5
+ "target": "html",
6
+ "storageKey": "fe_theme",
7
+ "supportedThemes": ["light", "dark", "pink"],
8
+ "styleThemeKeyTemplate": "${target}[${domAttribute}='${theme}']",
9
+ "colors": {
10
+ "light": {
11
+ "primary": "#00f",
12
+ "secondary": "#fff",
13
+ "text": "#000",
14
+ "background": "#fff"
15
+ },
16
+ "dark": {
17
+ "primary": "#f00",
18
+ "secondary": "#000",
19
+ "text": "#fff",
20
+ "background": "#000"
21
+ },
22
+ "pink": {
23
+ "primary": "#f0f",
24
+ "secondary": "#aaa",
25
+ "text": "#ddd",
26
+ "background": "#e0e0e0"
27
+ }
28
+ }
29
+ },
30
+ "override": {
31
+ "domAttribute": "data-theme",
32
+ "defaultTheme": "system",
33
+ "target": "html",
34
+ "supportedThemes": ["light", "dark", "pink"],
35
+ "storageKey": "fe_theme",
36
+ "styleThemeKeyTemplate": "${target}[${domAttribute}='${theme}']",
37
+ "styleKeyTemplate": "--fe-color-${colorKey}",
38
+ "colorsValueTemplate": "rgb(var(${styleKey}))",
39
+ "colors": {
40
+ "light": {
41
+ "white": "255 255 255",
42
+ "black": "0 0 0",
43
+ "gray": {
44
+ "50": "249 250 251",
45
+ "100": "243 244 246",
46
+ "200": "229 231 235",
47
+ "300": "209 213 219",
48
+ "400": "156 163 175",
49
+ "500": "107 114 128",
50
+ "600": "75 85 99",
51
+ "700": "55 65 81",
52
+ "800": "31 41 55",
53
+ "900": "17 24 39"
54
+ }
55
+ },
56
+ "dark": {
57
+ "white": "226 232 240",
58
+ "black": "0 0 0",
59
+ "gray": {
60
+ "50": "10 10 10",
61
+ "100": "28 28 28",
62
+ "200": "46 46 46",
63
+ "300": "64 64 64",
64
+ "400": "82 82 82",
65
+ "500": "100 100 100",
66
+ "600": "120 120 120",
67
+ "700": "138 138 138",
68
+ "800": "156 156 156",
69
+ "900": "176 176 176"
70
+ }
71
+ },
72
+ "pink": {
73
+ "white": "255 228 225",
74
+ "black": "51 51 51",
75
+ "gray": {
76
+ "50": "255 245 245",
77
+ "100": "255 234 234",
78
+ "200": "255 194 194",
79
+ "300": "255 153 153",
80
+ "400": "255 112 112",
81
+ "500": "255 71 71",
82
+ "600": "255 31 31",
83
+ "700": "230 0 0",
84
+ "800": "179 0 0",
85
+ "900": "128 0 0"
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,31 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+ import reactHooks from 'eslint-plugin-react-hooks';
4
+ import reactRefresh from 'eslint-plugin-react-refresh';
5
+ import tseslint from 'typescript-eslint';
6
+ import * as feDev from '@qlover/eslint-plugin-fe-dev';
7
+
8
+ export default tseslint.config(
9
+ { ignores: ['dist', 'node_modules'] },
10
+ {
11
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
12
+ files: ['src/**/*.{ts,tsx}'],
13
+ languageOptions: {
14
+ ecmaVersion: 2020,
15
+ globals: globals.browser
16
+ },
17
+ plugins: {
18
+ 'react-hooks': reactHooks,
19
+ 'react-refresh': reactRefresh,
20
+ 'fe-dev': feDev
21
+ },
22
+ rules: {
23
+ ...reactHooks.configs.recommended.rules,
24
+ 'react-refresh/only-export-components': [
25
+ 'warn',
26
+ { allowConstantExport: true }
27
+ ],
28
+ 'fe-dev/ts-class-method-return': 'error'
29
+ }
30
+ }
31
+ );
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Template FE-React</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>