@qlover/create-app 0.1.4 → 0.1.5

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 (114) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/bin/create-app.js +44 -4
  3. package/{templates/pack-app → configs/_common}/.env.template +8 -1
  4. package/{templates/pack-app → configs/_common}/.github/workflows/general-check.yml +9 -9
  5. package/{templates/pack-app → configs/_common}/.github/workflows/release.yml.template +18 -18
  6. package/configs/_common/.prettierrc.js +7 -0
  7. package/configs/_common/.release-it.json.template +42 -0
  8. package/configs/_common/.vscode/extensions.json +9 -0
  9. package/configs/_common/.vscode/react.code-snippets +19 -0
  10. package/configs/_common/.vscode/settings.json +11 -0
  11. package/configs/_common/package.json +61 -0
  12. package/configs/node-lib/eslint.config.js +50 -0
  13. package/configs/react-app/eslint.config.js +66 -0
  14. package/dist/cjs/index.d.ts +51 -36
  15. package/dist/cjs/index.js +1 -1
  16. package/dist/es/index.d.ts +51 -36
  17. package/dist/es/index.js +1 -1
  18. package/package.json +2 -1
  19. package/templates/node-lib/.release-it.json +42 -0
  20. package/templates/node-lib/__tests__/readJson.test.ts +1 -0
  21. package/templates/node-lib/bin/test.js +30 -0
  22. package/templates/node-lib/package.json +22 -6
  23. package/templates/node-lib/rollup.config.js +12 -22
  24. package/templates/node-lib/src/readJson.ts +9 -3
  25. package/templates/node-lib/tsconfig.json +19 -1
  26. package/templates/pack-app/eslint.config.js +81 -61
  27. package/templates/pack-app/fe-config.json +1 -5
  28. package/templates/pack-app/package.json +19 -11
  29. package/templates/pack-app/tsconfig.json +1 -1
  30. package/templates/pack-app/vite.config.ts +14 -0
  31. package/templates/react-app/README.md +177 -40
  32. package/templates/react-app/config/i18n.ts +1 -1
  33. package/templates/react-app/lib/fe-react-controller/FeController.ts +7 -3
  34. package/templates/react-app/lib/fe-react-theme/ThemeController.ts +1 -1
  35. package/templates/react-app/package.json +53 -9
  36. package/templates/react-app/src/App.tsx +4 -5
  37. package/templates/react-app/src/{services → base/apis}/feApi/FeApiMockPlugin.ts +1 -1
  38. package/templates/react-app/src/base/cases/UserToken.ts +47 -0
  39. package/templates/react-app/src/base/port/IOCInterface.ts +53 -0
  40. package/templates/react-app/src/base/port/StorageTokenInterface.ts +5 -0
  41. package/templates/react-app/src/{types → base/port}/UIDependenciesInterface.ts +6 -0
  42. package/templates/react-app/src/{types → base/types}/global.d.ts +1 -1
  43. package/templates/react-app/src/components/ThemeSwitcher.tsx +3 -2
  44. package/templates/react-app/src/core/bootstrap.ts +21 -0
  45. package/templates/react-app/src/core/feIOC/FeIOC.ts +32 -0
  46. package/templates/react-app/src/core/feIOC/RegisterApi.ts +41 -0
  47. package/templates/react-app/src/core/feIOC/RegisterCommon.ts +20 -0
  48. package/templates/react-app/src/core/feIOC/RegisterControllers.ts +53 -0
  49. package/templates/react-app/src/core/index.ts +31 -0
  50. package/templates/react-app/src/main.tsx +8 -10
  51. package/templates/react-app/src/pages/404.tsx +2 -2
  52. package/templates/react-app/src/pages/500.tsx +1 -1
  53. package/templates/react-app/src/pages/auth/Layout.tsx +3 -2
  54. package/templates/react-app/src/pages/auth/Login.tsx +6 -4
  55. package/templates/react-app/src/pages/base/About.tsx +1 -1
  56. package/templates/react-app/src/pages/base/Executor.tsx +8 -4
  57. package/templates/react-app/src/pages/base/Home.tsx +1 -1
  58. package/templates/react-app/src/pages/base/JSONStorage.tsx +6 -4
  59. package/templates/react-app/src/pages/base/Layout.tsx +1 -1
  60. package/templates/react-app/src/pages/base/RedirectPathname.tsx +1 -1
  61. package/templates/react-app/src/pages/base/Request.tsx +8 -3
  62. package/templates/react-app/src/pages/index.tsx +7 -2
  63. package/templates/react-app/src/services/{pageProcesser/PageProcesser.ts → processer/ProcesserService.ts} +3 -3
  64. package/templates/react-app/src/{containers/context → uikit/contexts}/BaseRouteContext.ts +4 -4
  65. package/templates/react-app/src/{services → uikit}/controllers/ExecutorController.ts +5 -5
  66. package/templates/react-app/src/{services → uikit}/controllers/JSONStorageController.ts +2 -2
  67. package/templates/react-app/src/{services → uikit}/controllers/RequestController.ts +3 -3
  68. package/templates/react-app/src/{services → uikit}/controllers/RouterController.ts +2 -2
  69. package/templates/react-app/src/{services → uikit}/controllers/UserController.ts +25 -51
  70. package/templates/react-app/src/{containers/context → uikit/providers}/BaseRouteProvider.tsx +2 -2
  71. package/templates/react-app/src/{components → uikit/providers}/ProcessProvider.tsx +13 -7
  72. package/templates/react-app/tsconfig.json +27 -5
  73. package/templates/react-app/tsconfig.node.json +3 -15
  74. package/templates/react-app/vite.config.ts +15 -12
  75. package/templates/pack-app/.env +0 -5
  76. package/templates/pack-app/.gitignore.template +0 -50
  77. package/templates/pack-app/.prettierrc.js +0 -3
  78. package/templates/pack-app/CHANGELOG.md +0 -0
  79. package/templates/pack-app/jest.config.js +0 -31
  80. package/templates/react-app/eslint.config.js +0 -31
  81. package/templates/react-app/src/containers/index.ts +0 -71
  82. package/templates/react-app/src/services/pageProcesser/index.ts +0 -1
  83. package/templates/react-app/tsconfig.app.json +0 -29
  84. package/templates/react-vite-lib/.gitignore.template +0 -27
  85. package/templates/react-vite-lib/README.md +0 -50
  86. package/templates/react-vite-lib/__tests__/Sum.test.ts +0 -9
  87. package/templates/react-vite-lib/__tests__/Text.test.tsx +0 -11
  88. package/templates/react-vite-lib/eslint.config.js +0 -28
  89. package/templates/react-vite-lib/index.html +0 -13
  90. package/templates/react-vite-lib/package.json +0 -30
  91. package/templates/react-vite-lib/public/vite.svg +0 -1
  92. package/templates/react-vite-lib/src/calc.ts +0 -3
  93. package/templates/react-vite-lib/src/commponents/Text.tsx +0 -7
  94. package/templates/react-vite-lib/src/index.ts +0 -2
  95. package/templates/react-vite-lib/src/vite-env.d.ts +0 -1
  96. package/templates/react-vite-lib/tsconfig.json +0 -25
  97. package/templates/react-vite-lib/vite.config.ts +0 -24
  98. /package/{templates/pack-app → configs/_common}/.editorconfig +0 -0
  99. /package/{templates/pack-app → configs/_common}/.gitattributes +0 -0
  100. /package/{templates/react-app → configs/_common}/.gitignore.template +0 -0
  101. /package/{templates/pack-app → configs/_common}/.prettierignore +0 -0
  102. /package/templates/react-app/src/{services → base/apis}/feApi/FeApi.ts +0 -0
  103. /package/templates/react-app/src/{services → base/apis}/feApi/FeApiType.ts +0 -0
  104. /package/templates/react-app/src/{services → base/apis}/feApi/index.ts +0 -0
  105. /package/templates/react-app/src/{types → base/types}/Page.ts +0 -0
  106. /package/templates/react-app/src/{containers → core}/globals.ts +0 -0
  107. /package/templates/react-app/src/{hooks → uikit/hooks}/useLanguageGuard.ts +0 -0
  108. /package/templates/react-app/src/{hooks → uikit/hooks}/useStrictEffect.ts +0 -0
  109. /package/templates/react-app/src/{styles → uikit/styles}/css/index.css +0 -0
  110. /package/templates/react-app/src/{styles → uikit/styles}/css/page.css +0 -0
  111. /package/templates/react-app/src/{styles → uikit/styles}/css/tailwind.css +0 -0
  112. /package/templates/react-app/src/{utils → uikit/utils}/RequestLogger.ts +0 -0
  113. /package/templates/react-app/src/{utils → uikit/utils}/datetime.ts +0 -0
  114. /package/templates/react-app/src/{utils → uikit/utils}/thread.ts +0 -0
@@ -6,21 +6,49 @@ import ignore from 'ignore';
6
6
  type GeneratorPrompt = DistinctQuestion;
7
7
  type GeneratorOptions = {
8
8
  prompts?: GeneratorPrompt[];
9
+ /**
10
+ * template root path
11
+ */
9
12
  templateRootPath: string;
13
+ /**
14
+ * configs root path
15
+ */
16
+ configsRootPath: string;
17
+ /**
18
+ * whether to copy config files
19
+ */
20
+ config?: boolean;
10
21
  };
11
- interface GeneratorResult extends GeneratorOptions {
22
+ interface GeneratorRuntimes extends GeneratorOptions {
23
+ /**
24
+ * project name
25
+ */
12
26
  name: string;
27
+ /**
28
+ * choose template name
29
+ *
30
+ * mayby is pack-app
31
+ */
13
32
  template: string;
33
+ /**
34
+ * choose sub packages
35
+ *
36
+ * mayby is ['node-lib', 'react-app']
37
+ */
14
38
  subPackages?: string[];
15
39
  /**
16
40
  * @default `packages`
17
41
  */
18
42
  packagesNames?: string;
43
+ /**
44
+ * Generated project path
45
+ * @default `./`
46
+ */
19
47
  targetPath?: string;
20
48
  }
21
49
  type TaskOptions = {
22
50
  templateFiles: TemplateFile[];
23
- result: GeneratorResult;
51
+ result: GeneratorRuntimes;
24
52
  };
25
53
  type TemplateFile = {
26
54
  path: string;
@@ -30,41 +58,34 @@ type TemplateFile = {
30
58
  declare class Generator {
31
59
  private ora;
32
60
  protected context: FeScriptContext<GeneratorOptions>;
61
+ private subPackages;
62
+ private copyer;
33
63
  constructor(context: Partial<FeScriptContext<GeneratorOptions>>);
34
64
  get logger(): Logger;
35
- steps(prompts: GeneratorPrompt[]): Promise<GeneratorResult>;
65
+ steps(prompts: GeneratorPrompt[]): Promise<GeneratorRuntimes>;
36
66
  action({ label, task }: {
37
67
  label: string;
38
68
  task: (() => Promise<unknown>) | (() => unknown);
39
69
  }): Promise<unknown>;
40
- /**
41
- * Creates files and directories based on the provided template files.
42
- *
43
- * This method iterates through the template files and writes their content
44
- * to the file system. It handles both files and directories, ensuring that
45
- * the directory structure is preserved.
46
- *
47
- * @param result - The result object containing the name and template name.
48
- *
49
- * @returns A promise that resolves when all files have been created.
50
- *
51
- * @example
52
- * const result = { name: 'my-app', template: 'react-app' };
53
- * await this.create(result);
54
- */
55
- create(result: GeneratorResult): Promise<void>;
56
70
  private isPackageTemplate;
57
- getGeneratorResult(): Promise<GeneratorResult>;
71
+ private getGeneratorResult;
72
+ private copyConfigs;
58
73
  generate(): Promise<void>;
74
+ private generateTemplateDir;
75
+ private generateSubPackages;
59
76
  }
60
77
 
61
78
  declare const validRequiredString: (value: string, key: string) => string | true;
62
- declare const defaultPrompts: GeneratorPrompt[];
63
- declare const packagePrompts: GeneratorPrompt[];
79
+ declare function createDefaultPrompts(templates: string[], packages: string[]): GeneratorPrompt[];
80
+ declare function createPackagePrompts(templates: string[]): GeneratorPrompt[];
64
81
 
82
+ type CopyCallback = (sourceFilePath: string, targetFilePath: string) => boolean | Promise<boolean>;
65
83
  declare class Copyer {
84
+ private readonly ignoreTargetPath;
85
+ private readonly ignoreFile;
66
86
  static IGNORE_FILE: string;
67
- getIg(targetDir: string): ignore.Ignore | undefined;
87
+ constructor(ignoreTargetPath: string, ignoreFile?: string);
88
+ getIg(targetDir?: string): ignore.Ignore | undefined;
68
89
  ensureDir(dir: string): void;
69
90
  /**
70
91
  * Asynchronously copy files from source to target directory.
@@ -75,18 +96,12 @@ declare class Copyer {
75
96
  * @example
76
97
  * await copyer.copyFilesPromise('src', 'dest', ignoreInstance);
77
98
  */
78
- copyFilesPromise(sourcePath: string, targetDir: string, ig?: ignore.Ignore): Promise<void>;
79
- /**
80
- * copy templates recursively
81
- * @param {string} sourePath - source directory
82
- * @param {string} targetDir - target directory
83
- * @param {ignore.Ignore} ig - ignore rules
84
- */
85
- copyFilesSync(sourePath: string, targetDir: string, ig?: ignore.Ignore): void;
86
- create(result: GeneratorResult): void;
87
- createPromise(result: GeneratorResult): Promise<void>;
88
- createPath(result: GeneratorResult): void;
89
- createPathPromise(result: GeneratorResult): Promise<void>;
99
+ copyFiles(sourcePath: string, targetDir: string, ig?: ignore.Ignore, copyCallback?: CopyCallback): Promise<void>;
100
+ copyPaths({ sourcePath, targetPath, copyCallback }: {
101
+ sourcePath: string;
102
+ targetPath: string;
103
+ copyCallback?: CopyCallback;
104
+ }): Promise<void>;
90
105
  }
91
106
 
92
- export { Copyer, Generator, type GeneratorOptions, type GeneratorPrompt, type GeneratorResult, type TaskOptions, type TemplateFile, defaultPrompts, packagePrompts, validRequiredString };
107
+ export { type CopyCallback, Copyer, Generator, type GeneratorOptions, type GeneratorPrompt, type GeneratorRuntimes, type TaskOptions, type TemplateFile, createDefaultPrompts, createPackagePrompts, validRequiredString };
package/dist/es/index.js CHANGED
@@ -1 +1 @@
1
- import{FeScriptContext as t}from"@qlover/scripts-context";import e from"inquirer";import{join as a,dirname as r}from"path";import{oraPromise as s}from"ora";import{existsSync as o,readFileSync as i,mkdirSync as c,promises as n,readdirSync as p,statSync as h,copyFileSync as m}from"fs";import l from"ignore";const g=(t,e)=>"string"==typeof t&&""!==t.trim()||`${e} is required`,P=["node-lib","react-app","react-vite-lib"],u=[{type:"input",name:"name",message:"Project name",validate:t=>g(t,"Project name")},{type:"list",name:"template",message:"Template name",choices:[...P,"pack-app"]}],f=[{type:"checkbox",name:"subPackages",message:"Sub package names",choices:P}],{copyFile:y,stat:w}=n;class k{static IGNORE_FILE=".gitignore.template";getIg(t){const e=a(t,k.IGNORE_FILE);if(!o(e))return;const r=i(e,"utf8").split("\n").map((t=>t.trim())).filter((t=>t&&!t.startsWith("#")));return l().add(r)}ensureDir(t){o(t)||c(t,{recursive:!0})}async copyFilesPromise(t,e,s){const o=await n.readdir(t);await Promise.all(o.map((async o=>{const i=a(t,o),c=a(e,o);if(s&&s.ignores(o))return;this.ensureDir(r(c));(await w(i)).isDirectory()?await this.copyFilesPromise(i,c,s):await y(i,c)})))}copyFilesSync(t,e,s){const o=p(t);for(const i of o){const o=a(t,i),c=a(e,i);s&&s.ignores(i)||(this.ensureDir(r(c)),h(o).isDirectory()?this.copyFilesSync(o,c,s):m(o,c))}}create(t){const{targetPath:e,templateRootPath:r,subPackages:s,packagesNames:o="packages"}=t;if(!e||!r)throw new Error("targetPath and templatePath are required");if(this.createPath(t),s)for(const r of s){const s=a(e,o,r);this.createPath({...t,targetPath:s,template:r})}}async createPromise(t){const{targetPath:e,templateRootPath:r,subPackages:s,packagesNames:o="packages"}=t;if(!e||!r)throw new Error("targetPath and templatePath are required");if(await this.createPathPromise(t),s)for(const r of s){const s=a(e,o,r);await this.createPathPromise({...t,targetPath:s,template:r})}}createPath(t){const{targetPath:e="",templateRootPath:r,template:s}=t;this.ensureDir(e);const o=a(r,s),i=this.getIg(e);this.copyFilesSync(o,e,i)}createPathPromise(t){const{targetPath:e="",templateRootPath:r,template:s}=t;this.ensureDir(e);const o=a(r,s),i=this.getIg(e);return this.copyFilesPromise(o,e,i)}}class d{ora;context;constructor(e){const a=e.options?.templateRootPath;if(!a)throw new Error("template path not exit");if(!o(a))throw new Error("template path not exit");this.ora=s,this.context=new t(e)}get logger(){return this.context.logger}async steps(t){try{return await e.prompt(t)}catch(t){throw this.logger.error(t),t}}async action({label:t,task:e}){let a=e();a instanceof Promise||(a=Promise.resolve(a));const r=t;return this.ora(a,r),a}async create(t){const e=a(process.cwd(),t.name),r=new k,s={...t,targetPath:e,templateRootPath:this.context.options.templateRootPath};return this.logger.debug(s),r.createPromise(s)}isPackageTemplate(t){return"pack-app"===t}async getGeneratorResult(){const t=await this.steps(u);if(this.isPackageTemplate(t.template)){const e=await this.steps(f);Object.assign(t,e)}return t}async generate(){const t=await this.getGeneratorResult();await this.action({label:"Creating project",task:()=>this.create(t)})}}export{k as Copyer,d as Generator,u as defaultPrompts,f as packagePrompts,g as validRequiredString};
1
+ import{FeScriptContext as t}from"@qlover/scripts-context";import e from"inquirer";import{join as a,dirname as s}from"path";import{oraPromise as o}from"ora";import{existsSync as i,readFileSync as r,mkdirSync as c,promises as n}from"fs";import g from"ignore";const h=(t,e)=>"string"==typeof t&&""!==t.trim()||`${e} is required`;function p(t,e){return[{type:"input",name:"name",message:"Project name",validate:t=>h(t,"Project name")},{type:"list",name:"template",message:"Template name",choices:[...t,...e]}]}function l(t){return[{type:"checkbox",name:"subPackages",message:"Sub package names",choices:t}]}const{copyFile:m,stat:u}=n;class P{ignoreTargetPath;ignoreFile;static IGNORE_FILE=".gitignore.template";constructor(t,e=P.IGNORE_FILE){this.ignoreTargetPath=t,this.ignoreFile=e}getIg(t=this.ignoreTargetPath){const e=a(t,this.ignoreFile);if(!i(e))return;const s=r(e,"utf8").split("\n").map((t=>t.trim())).filter((t=>t&&!t.startsWith("#")));return g().add(s)}ensureDir(t){i(t)||c(t,{recursive:!0})}async copyFiles(t,e,o,i){const r=await n.readdir(t);await Promise.all(r.map((async r=>{const c=a(t,r),n=a(e,r);if(o&&o.ignores(r))return;this.ensureDir(s(n));if((await u(c)).isDirectory())await this.copyFiles(c,n,o);else{if(i&&await i(c,n))return;await m(c,n)}})))}copyPaths({sourcePath:t,targetPath:e,copyCallback:a}){this.ensureDir(e);const s=this.getIg();return this.copyFiles(t,e,s,a)}}const y=["pack-app"];class f{ora;context;subPackages;copyer;constructor(e){const s=e.options?.templateRootPath;if(!s)throw new Error("template path not exit");if(!i(s))throw new Error("template path not exit");this.ora=o,this.context=new t(e),this.subPackages=["node-lib","react-app"],this.copyer=new P(a(this.context.options.configsRootPath,"_common"))}get logger(){return this.context.logger}async steps(t){try{return await e.prompt(t)}catch(t){throw this.logger.error(t),t}}async action({label:t,task:e}){let a=e();a instanceof Promise||(a=Promise.resolve(a));const s=t;return this.ora(a,s),a}isPackageTemplate(t){return y.includes(t)}async getGeneratorResult(){const t=p(this.subPackages,y),e=await this.steps(t);if(this.isPackageTemplate(e.template)){const t=l(this.subPackages),a=await this.steps(t);Object.assign(e,a)}return e}async copyConfigs(t,e){const{configsRootPath:s,config:o}=this.context.options;o?await this.copyer.copyPaths({sourcePath:a(s,e),targetPath:t,copyCallback:(t,e)=>(this.logger.debug("copyCallback",t,e),!1)}):this.logger.debug("no copy config files")}async generate(){const t=await this.getGeneratorResult();t.targetPath=a(process.cwd(),t.name),this.logger.debug("result is:",t,this.context.options.templateRootPath),t.subPackages?await this.action({label:"Generate Directories(subPackages)",task:async()=>{await this.generateTemplateDir(t),await this.generateSubPackages(t),await this.copyConfigs(t.targetPath,"_common")}}):await this.action({label:"Generate Directory",task:async()=>{await this.generateTemplateDir(t),await this.copyConfigs(t.targetPath,"_common"),await this.copyConfigs(t.targetPath,t.template)}})}generateTemplateDir(t){return this.copyer.copyPaths({sourcePath:a(this.context.options.templateRootPath,t.template),targetPath:t.targetPath})}async generateSubPackages(t){const{packagesNames:e="packages",subPackages:s=[],targetPath:o=""}=t,{templateRootPath:i}=this.context.options;for(const t of s){const s=a(i,t),r=a(o,e,t);this.logger.debug("copy sub package",s,r),await this.copyer.copyPaths({sourcePath:s,targetPath:r})}}}export{P as Copyer,f as Generator,p as createDefaultPrompts,l as createPackagePrompts,h as validRequiredString};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlover/create-app",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/es/index.js",
@@ -19,6 +19,7 @@
19
19
  "files": [
20
20
  "dist",
21
21
  "bin",
22
+ "configs",
22
23
  "templates",
23
24
  "package.json",
24
25
  "README.md",
@@ -0,0 +1,42 @@
1
+ {
2
+ "git": {
3
+ "commitMessage": "chore(tag): [PKG_NAME] v${version}",
4
+ "tagName": "[PKG_NAME]-v${version}",
5
+ "tagMatch": "[PKG_NAME]-v*",
6
+ "tagAnnotation": "chore(tag): [PKG_NAME] v${version}",
7
+ "push": true,
8
+ "pushArgs": ["--follow-tags"]
9
+ },
10
+ "npm": {
11
+ "publishPath": "",
12
+ "versionArgs": ["--allow-same-version", "--workspaces-update=false"]
13
+ },
14
+ "github": {
15
+ "release": true,
16
+ "releaseName": "chore(tag): [PKG_NAME] v${version}"
17
+ },
18
+
19
+ "plugins": {
20
+ "@release-it/conventional-changelog": {
21
+ "infile": "CHANGELOG.md",
22
+ "preset": {
23
+ "name": "conventionalcommits",
24
+ "types": [
25
+ { "type": "feat", "section": "Features" },
26
+ { "type": "fix", "section": "Bug Fixes" },
27
+ { "type": "revert", "section": "Reverts" },
28
+ { "type": "build", "hidden": true, "section": "Build System" },
29
+ { "type": "chore", "hidden": true },
30
+ { "type": "docs", "section": "Documentation" },
31
+ { "type": "style", "hidden": true },
32
+ { "type": "refactor", "hidden": true },
33
+ { "type": "perf", "hidden": true },
34
+ { "type": "test", "hidden": true }
35
+ ]
36
+ },
37
+ "gitRawCommitsOpts": {
38
+ "path": "."
39
+ }
40
+ }
41
+ }
42
+ }
@@ -1,3 +1,4 @@
1
+ import { expect, describe, it, beforeAll, afterAll } from 'vitest';
1
2
  import { readJson } from '../src/readJson';
2
3
  import { writeFileSync, unlinkSync } from 'fs';
3
4
 
@@ -0,0 +1,30 @@
1
+ #! /usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+
5
+ function programArgs() {
6
+ const program = new Command();
7
+ program
8
+ .option(
9
+ '-d, --dry-run',
10
+ 'Do not touch or write anything, but show the commands'
11
+ )
12
+ .option('-V, --verbose', 'Show more information')
13
+ .option('-n, --name <name>', 'The name of the test')
14
+ // parse arguments
15
+ program.parse();
16
+
17
+ return program.opts();
18
+ }
19
+
20
+ async function main() {
21
+ const { dryRun, verbose, ...commandOptions } = programArgs();
22
+
23
+ console.log('dryRun:', dryRun);
24
+ console.log('verbose:', verbose);
25
+ console.log('commandOptions:', commandOptions);
26
+ }
27
+
28
+ main().catch(() => {
29
+ process.exit(1);
30
+ });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-lib",
3
- "description": "A node lib for frontwork",
3
+ "description": "A node lib template",
4
4
  "version": "0.0.0",
5
5
  "type": "module",
6
6
  "private": true,
@@ -12,9 +12,9 @@
12
12
  "types": "./dist/es/index.d.ts",
13
13
  "exports": {
14
14
  ".": {
15
+ "types": "./dist/es/index.d.ts",
15
16
  "import": "./dist/es/index.js",
16
- "require": "./dist/cjs/index.js",
17
- "types": "./dist/es/index.d.ts"
17
+ "require": "./dist/cjs/index.js"
18
18
  },
19
19
  "./cjs/*": "./dist/cjs/*",
20
20
  "./es/*": "./dist/es/*",
@@ -26,23 +26,39 @@
26
26
  "directory": ""
27
27
  },
28
28
  "files": [
29
+ "bin",
29
30
  "dist",
30
31
  "package.json",
31
32
  "README.md"
32
33
  ],
33
34
  "keywords": [
34
- "node-lib"
35
+ "lib",
36
+ "node lib"
35
37
  ],
36
38
  "publishConfig": {
37
39
  "access": "public"
38
40
  },
41
+ "bin": {},
39
42
  "scripts": {
40
43
  "build": "rollup -c",
41
- "test": "jest"
44
+ "lint": "eslint .",
45
+ "test": "vitest run",
46
+ "run:command": "node bin/test.js"
42
47
  },
43
48
  "devDependencies": {
49
+ "@qlover/env-loader": "latest",
44
50
  "@qlover/fe-standard": "latest",
45
- "@qlover/env-loader": "latest"
51
+ "@qlover/scripts-context": "latest",
52
+ "@release-it/conventional-changelog": "^8.0.1",
53
+ "@rollup/plugin-commonjs": "^28.0.1",
54
+ "@rollup/plugin-json": "^6.1.0",
55
+ "@rollup/plugin-node-resolve": "^15.3.0",
56
+ "@rollup/plugin-terser": "^0.4.4",
57
+ "@types/node": "^22.13.2",
58
+ "commander": "^11.0.0",
59
+ "release-it": "^17.10.0",
60
+ "rollup-plugin-dts": "^6.1.1",
61
+ "rollup-plugin-typescript2": "^0.36.0"
46
62
  },
47
63
  "dependencies": {
48
64
  "@qlover/fe-utils": "latest"
@@ -9,10 +9,9 @@ import { readFileSync, rmSync } from 'fs';
9
9
  import { Env } from '@qlover/env-loader';
10
10
 
11
11
  const pkg = JSON.parse(readFileSync('./package.json'), 'utf-8');
12
- const tsConfig = JSON.parse(readFileSync('./tsconfig.json'), 'utf-8');
13
12
  const env = Env.searchEnv({ logger: console });
14
13
  const isProduction = env.get('NODE_ENV') === 'production';
15
- const buildDir = tsConfig.compilerOptions.outDir;
14
+ const buildDir = 'dist';
16
15
 
17
16
  const treeshake = {
18
17
  moduleSideEffects: false,
@@ -50,6 +49,8 @@ function cleanBuildDir() {
50
49
 
51
50
  cleanBuildDir();
52
51
 
52
+ const formats = ['cjs', 'es'];
53
+
53
54
  /**
54
55
  * @type {import('rollup').RollupOptions[]}
55
56
  */
@@ -57,31 +58,20 @@ const config = [
57
58
  {
58
59
  input: 'src/index.ts',
59
60
  external: defaultExternal,
60
- output: [
61
- {
62
- file: 'dist/cjs/index.js',
63
- format: 'cjs'
64
- },
65
- {
66
- file: 'dist/es/index.js',
67
- format: 'es'
68
- }
69
- ],
61
+ output: formats.map((format) => ({
62
+ file: `dist/${format}/index.js`,
63
+ format
64
+ })),
70
65
  plugins: createPlugin(isProduction),
71
66
  treeshake
72
67
  },
73
68
  {
74
69
  input: './src/index.ts',
75
- output: [
76
- {
77
- file: 'dist/cjs/index.d.ts',
78
- format: 'cjs'
79
- },
80
- {
81
- file: 'dist/es/index.d.ts',
82
- format: 'es'
83
- }
84
- ],
70
+ external: defaultExternal,
71
+ output: formats.map((format) => ({
72
+ file: `dist/${format}/index.d.ts`,
73
+ format
74
+ })),
85
75
  plugins: [dts()],
86
76
  treeshake
87
77
  }
@@ -1,6 +1,12 @@
1
1
  import { readFileSync } from 'fs';
2
2
 
3
- export function readJson(path: string): Record<string, unknown> {
4
- const packageJson = readFileSync(path, 'utf8');
5
- return JSON.parse(packageJson);
3
+ export function readJson(path: string) {
4
+ return ReadJson.read(path);
5
+ }
6
+
7
+ export class ReadJson {
8
+ static read(path: string): Record<string, unknown> {
9
+ const packageJson = readFileSync(path, 'utf8');
10
+ return JSON.parse(packageJson);
11
+ }
6
12
  }
@@ -1,5 +1,23 @@
1
1
  {
2
- "extends": "@qlover/fe-standard/config/tsconfig.base.json",
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "resolveJsonModule": true,
10
+ "isolatedModules": true,
11
+ "jsx": "react-jsx",
12
+ "strict": true,
13
+ "noUnusedLocals": true,
14
+ "noUnusedParameters": true,
15
+ "noFallthroughCasesInSwitch": true,
16
+ "esModuleInterop": true,
17
+ "allowJs": true,
18
+ "declaration": false,
19
+ "outDir": "dist"
20
+ },
3
21
  "include": ["src"],
4
22
  "exclude": ["dist", "node_modules"]
5
23
  }
@@ -1,77 +1,97 @@
1
+ import js from '@eslint/js';
1
2
  import globals from 'globals';
2
- import jest from 'eslint-plugin-jest';
3
- import * as eslintChain from '@qlover/fe-standard/eslint/index.js';
4
- import reactEslint from './packages/react-vite-lib/eslint.config.js';
3
+ import react from 'eslint-plugin-react';
4
+ import reactHooks from 'eslint-plugin-react-hooks';
5
+ import reactRefresh from 'eslint-plugin-react-refresh';
6
+ import prettierConfig from './.prettierrc.js';
7
+ import prettier from 'eslint-plugin-prettier';
8
+ import tseslint from '@typescript-eslint/eslint-plugin';
9
+ import tsparser from '@typescript-eslint/parser';
10
+ import * as feDev from '@qlover/eslint-plugin-fe-dev';
11
+ import vitestPlugin from 'eslint-plugin-vitest';
5
12
 
6
- const { createCommon, createTslintRecommended, chainEnv } = eslintChain;
7
- const allGlobals = {
13
+ const allowedGlobals = {
8
14
  ...globals.browser,
9
15
  ...globals.node,
10
16
  ...globals.jest
11
17
  };
12
18
 
13
- function createBrowserConfig() {
14
- return chainEnv({
15
- allGlobals,
16
- files: ['packages/browser/**/*.ts'],
17
- languageOptions: {
18
- globals: globals.browser
19
- }
20
- });
21
- }
22
-
23
- function createNodeConfig() {
24
- return chainEnv({
25
- allGlobals,
26
- files: ['packages/node/**/*.ts'],
19
+ export default [
20
+ {
21
+ ignores: ['dist', 'node_modules']
22
+ },
23
+ {
24
+ files: ['packages/**/*.{js,jsx,ts,tsx}'],
27
25
  languageOptions: {
28
- globals: globals.node
26
+ parser: tsparser,
27
+ ecmaVersion: 2020,
28
+ globals: {
29
+ ...globals.browser,
30
+ ...globals.node
31
+ },
32
+ parserOptions: {
33
+ ecmaVersion: 'latest',
34
+ ecmaFeatures: { jsx: true },
35
+ sourceType: 'module',
36
+ project: './tsconfig.json'
37
+ }
38
+ },
39
+ settings: { react: { version: '18.3' } },
40
+ plugins: {
41
+ react,
42
+ 'react-hooks': reactHooks,
43
+ 'react-refresh': reactRefresh,
44
+ prettier,
45
+ '@typescript-eslint': tseslint,
46
+ 'fe-dev': feDev
47
+ },
48
+ rules: {
49
+ ...js.configs.recommended.rules,
50
+ ...react.configs.recommended.rules,
51
+ ...react.configs['jsx-runtime'].rules,
52
+ ...reactHooks.configs.recommended.rules,
53
+ ...tseslint.configs.recommended.rules,
54
+ 'react/jsx-no-target-blank': 'off',
55
+ 'react/prefer-stateless-function': 'error',
56
+ 'react-refresh/only-export-components': [
57
+ 'warn',
58
+ { allowConstantExport: true }
59
+ ],
60
+ '@typescript-eslint/no-explicit-any': 'error',
61
+ 'prettier/prettier': ['error', prettierConfig],
62
+ '@typescript-eslint/ban-ts-comment': [
63
+ 'off',
64
+ {
65
+ 'ts-expect-error': {
66
+ descriptionFormat: '^.*$'
67
+ }
68
+ }
69
+ ],
70
+ 'react-hooks/exhaustive-deps': 'off',
71
+ 'fe-dev/ts-class-method-return': 'error'
29
72
  }
30
- });
31
- }
32
-
33
- function createReactConfig() {
34
- return chainEnv({
35
- allGlobals,
36
- files: ['packages/react/**/*.tsx'],
37
- ...reactEslint
38
- });
39
- }
40
-
41
- function createJESTConfig() {
42
- const config = chainEnv({
43
- allGlobals,
44
- files: ['packages/**/*.test.ts', 'packages/**/*.test.js'],
73
+ },
74
+ {
75
+ files: ['packages/**/__tests__/**/*.test.{ts,tsx}'],
45
76
  plugins: {
46
- jest
77
+ vitest: vitestPlugin
47
78
  },
48
79
  languageOptions: {
80
+ parser: tsparser,
49
81
  globals: {
50
- // ...globals.browser,
51
- ...globals.node,
52
- ...globals.jest
82
+ ...allowedGlobals,
83
+ ...vitestPlugin.environments.env.globals
84
+ },
85
+ parserOptions: {
86
+ ecmaVersion: 'latest',
87
+ sourceType: 'module',
88
+ ecmaFeatures: { jsx: true },
89
+ project: './tsconfig.json'
53
90
  }
91
+ },
92
+ rules: {
93
+ ...vitestPlugin.configs.recommended.rules,
94
+ 'no-restricted-globals': 'off'
54
95
  }
55
- });
56
- return config;
57
- }
58
-
59
- /**
60
- * @type {import('eslint').Linter.Config[]}
61
- */
62
- export default [
63
- {
64
- ignores: ['**/dist/**', '**/build/**', '**/node_modules/**', 'templates/**']
65
- },
66
- // common js and ts
67
- createCommon(),
68
- createTslintRecommended(['packages/**/*.ts']),
69
- // browser
70
- createBrowserConfig(),
71
- // node
72
- createNodeConfig(),
73
- // react
74
- createReactConfig(),
75
- // jest
76
- createJESTConfig()
96
+ }
77
97
  ];
@@ -1,10 +1,6 @@
1
1
  {
2
2
  "protectedBranches": ["master", "develop"],
3
3
  "release": {
4
- "packagesDirectories": [
5
- "packages/browser",
6
- "packages/node",
7
- "packages/react-vite-lib"
8
- ]
4
+ "packagesDirectories": []
9
5
  }
10
6
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "@qlover/pack-app",
2
+ "name": "pack-app",
3
3
  "version": "0.0.0",
4
4
  "description": "A template for fe-pack-app",
5
5
  "type": "module",
@@ -10,11 +10,10 @@
10
10
  },
11
11
  "homepage": "https://github.com/qlover/fe-base#readme",
12
12
  "scripts": {
13
- "build": "pnpm run build:[PKG_NAME]",
14
- "build:[PKG_NAME]": "pnpm run build --filter=@qlover/${PKG_NAME}",
13
+ "build": "pnpm -r run build",
15
14
  "prettier": "prettier --ignore-path .prettierignore **/*.{js,ts,json,cjs,mjs} --write",
16
15
  "lint": "eslint . --fix",
17
- "test": "jest",
16
+ "test": "pnpm run test",
18
17
  "clean": "fe-clean",
19
18
  "clean:build": "fe-clean -f packages/*/dist -r",
20
19
  "check-packages": "fe-check-packages",
@@ -39,25 +38,34 @@
39
38
  "@rollup/plugin-node-resolve": "^15.3.0",
40
39
  "@rollup/plugin-terser": "^0.4.4",
41
40
  "@rollup/plugin-typescript": "^12.1.1",
42
- "@testing-library/jest-dom": "^6.6.3",
43
41
  "@testing-library/react": "^16.1.0",
44
- "@types/jest": "^29.5.11",
45
42
  "eslint": "^9.17.0",
46
- "jest": "^29.7.0",
47
- "jest-environment-jsdom": "^29.7.0",
43
+ "eslint-plugin-react": "^7.37.4",
44
+ "eslint-plugin-react-hooks": "^5.0.0",
45
+ "eslint-plugin-react-refresh": "^0.4.14",
46
+ "globals": "^15.12.0",
47
+ "husky": "^9.1.7",
48
+ "jsdom": "^26.0.0",
49
+ "prettier": "^3.5.0",
48
50
  "rollup": "^4.24.2",
49
51
  "rollup-plugin-delete": "^2.1.0",
50
52
  "rollup-plugin-dts": "^6.1.1",
51
53
  "rollup-plugin-typescript2": "^0.36.0",
52
54
  "ts-node": "^10.9.2",
53
- "typescript": "~5.4.0"
55
+ "typescript": "~5.4.0",
56
+ "vite": "^5.4.8",
57
+ "vitest": "^3.0.5"
54
58
  },
55
59
  "workspaces": [
56
60
  "packages/*"
57
61
  ],
58
62
  "lint-staged": {
59
- "*.{js,jsx,ts,tsx}": [
60
- "eslint --fix"
63
+ "packages/**/*.{js,jsx,ts,tsx}": [
64
+ "eslint --cache --fix --quiet",
65
+ "prettier --write"
66
+ ],
67
+ "packages/**/*.{json,css,scss,md}": [
68
+ "prettier --write"
61
69
  ]
62
70
  },
63
71
  "packageManager": "pnpm@9.1.0"
@@ -4,6 +4,6 @@
4
4
  "jsx": "react-jsx",
5
5
  "rootDir": "./"
6
6
  },
7
- "include": ["./packages"],
7
+ "include": ["./packages", "configs/node-lib/eslint.config.js"],
8
8
  "exclude": ["**/node_modules/*", "**/dist", "**/build"]
9
9
  }