@qlover/create-app 0.0.3 → 0.1.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 (134) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +5 -0
  3. package/bin/create-app.js +7 -9
  4. package/dist/cjs/index.d.ts +41 -16
  5. package/dist/cjs/index.js +1 -1
  6. package/dist/es/index.d.ts +41 -16
  7. package/dist/es/index.js +1 -1
  8. package/package.json +4 -2
  9. package/templates/{pack-app/packages/node → node-lib}/package.json +1 -1
  10. package/templates/pack-app/.gitignore.template +50 -0
  11. package/templates/pack-app/package.json +5 -7
  12. package/templates/react-app/.gitignore.template +32 -0
  13. package/templates/{fe-react → react-app}/config/i18n.ts +1 -1
  14. package/templates/{fe-react → react-app}/lib/fe-react-theme/index.ts +1 -1
  15. package/templates/{fe-react → react-app}/lib/fe-react-theme/tw-generator.js +0 -1
  16. package/templates/{fe-react → react-app}/lib/openAiApi/index.ts +1 -1
  17. package/templates/{fe-react → react-app}/postcss.config.js +3 -3
  18. package/templates/{fe-react → react-app}/src/containers/globals.ts +1 -1
  19. package/templates/{fe-react → react-app}/src/containers/index.ts +1 -1
  20. package/templates/{fe-react → react-app}/src/hooks/useStrictEffect.ts +7 -4
  21. package/templates/{fe-react → react-app}/src/services/controllers/UserController.ts +1 -1
  22. package/templates/{fe-react → react-app}/src/services/feApi/FeApi.ts +1 -1
  23. package/templates/{fe-react → react-app}/src/services/feApi/FeApiMockPlugin.ts +3 -1
  24. package/templates/{fe-react → react-app}/src/services/feApi/FeApiType.ts +0 -1
  25. package/templates/{fe-react → react-app}/src/services/pageProcesser/PageProcesser.ts +1 -1
  26. package/templates/{fe-react → react-app}/src/utils/datetime.ts +10 -5
  27. package/templates/react-app/src/vite-env.d.ts +1 -0
  28. package/templates/react-vite-lib/.gitignore.template +27 -0
  29. package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/__tests__/Sum.test.ts +1 -1
  30. package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/eslint.config.js +12 -12
  31. package/templates/react-vite-lib/src/vite-env.d.ts +1 -0
  32. package/templates/fe-react/src/vite-env.d.ts +0 -1
  33. package/templates/pack-app/packages/browser/__tests__/calc.test.ts +0 -9
  34. package/templates/pack-app/packages/browser/package.json +0 -11
  35. package/templates/pack-app/packages/browser/rollup.config.js +0 -70
  36. package/templates/pack-app/packages/browser/src/calc.ts +0 -3
  37. package/templates/pack-app/packages/browser/src/index.ts +0 -1
  38. package/templates/pack-app/packages/browser/tsconfig.json +0 -15
  39. package/templates/pack-app/packages/react-vite-lib/src/vite-env.d.ts +0 -1
  40. /package/templates/{pack-app/packages/node → node-lib}/__tests__/readJson.test.ts +0 -0
  41. /package/templates/{pack-app/packages/node → node-lib}/rollup.config.js +0 -0
  42. /package/templates/{pack-app/packages/node → node-lib}/src/index.ts +0 -0
  43. /package/templates/{pack-app/packages/node → node-lib}/src/readJson.ts +0 -0
  44. /package/templates/{pack-app/packages/node → node-lib}/tsconfig.json +0 -0
  45. /package/templates/{fe-react → react-app}/.env +0 -0
  46. /package/templates/{fe-react → react-app}/README.md +0 -0
  47. /package/templates/{fe-react → react-app}/config/app.common.ts +0 -0
  48. /package/templates/{fe-react → react-app}/config/app.router.json +0 -0
  49. /package/templates/{fe-react → react-app}/config/feapi.mock.json +0 -0
  50. /package/templates/{fe-react → react-app}/config/theme.json +0 -0
  51. /package/templates/{fe-react → react-app}/eslint.config.js +0 -0
  52. /package/templates/{fe-react → react-app}/index.html +0 -0
  53. /package/templates/{fe-react → react-app}/lib/fe-react-controller/FeController.ts +0 -0
  54. /package/templates/{fe-react → react-app}/lib/fe-react-controller/index.ts +0 -0
  55. /package/templates/{fe-react → react-app}/lib/fe-react-controller/useController.ts +0 -0
  56. /package/templates/{fe-react → react-app}/lib/fe-react-theme/ThemeController.ts +0 -0
  57. /package/templates/{fe-react → react-app}/lib/fe-react-theme/ThemeStateGetter.ts +0 -0
  58. /package/templates/{fe-react → react-app}/lib/fe-react-theme/type.ts +0 -0
  59. /package/templates/{fe-react → react-app}/lib/openAiApi/OpenAIAuthPlugin.ts +0 -0
  60. /package/templates/{fe-react → react-app}/lib/openAiApi/OpenAIClient.ts +0 -0
  61. /package/templates/{fe-react → react-app}/lib/openAiApi/StreamProcessor.ts +0 -0
  62. /package/templates/{fe-react → react-app}/lib/request-common-plugin/index.ts +0 -0
  63. /package/templates/{fe-react → react-app}/lib/tw-root10px/index.css +0 -0
  64. /package/templates/{fe-react → react-app}/lib/tw-root10px/index.js +0 -0
  65. /package/templates/{fe-react → react-app}/package.json +0 -0
  66. /package/templates/{fe-react → react-app}/public/locales/en/about.json +0 -0
  67. /package/templates/{fe-react → react-app}/public/locales/en/common.json +0 -0
  68. /package/templates/{fe-react → react-app}/public/locales/en/executor.json +0 -0
  69. /package/templates/{fe-react → react-app}/public/locales/en/home.json +0 -0
  70. /package/templates/{fe-react → react-app}/public/locales/en/jsonStorage.json +0 -0
  71. /package/templates/{fe-react → react-app}/public/locales/en/login.json +0 -0
  72. /package/templates/{fe-react → react-app}/public/locales/en/request.json +0 -0
  73. /package/templates/{fe-react → react-app}/public/locales/zh/about.json +0 -0
  74. /package/templates/{fe-react → react-app}/public/locales/zh/common.json +0 -0
  75. /package/templates/{fe-react → react-app}/public/locales/zh/executor.json +0 -0
  76. /package/templates/{fe-react → react-app}/public/locales/zh/home.json +0 -0
  77. /package/templates/{fe-react → react-app}/public/locales/zh/jsonStorage.json +0 -0
  78. /package/templates/{fe-react → react-app}/public/locales/zh/login.json +0 -0
  79. /package/templates/{fe-react → react-app}/public/locales/zh/request.json +0 -0
  80. /package/templates/{fe-react → react-app}/public/logo.svg +0 -0
  81. /package/templates/{fe-react → react-app}/src/App.tsx +0 -0
  82. /package/templates/{fe-react → react-app}/src/assets/react.svg +0 -0
  83. /package/templates/{fe-react → react-app}/src/components/Loading.tsx +0 -0
  84. /package/templates/{fe-react → react-app}/src/components/LocaleLink.tsx +0 -0
  85. /package/templates/{fe-react → react-app}/src/components/ProcessProvider.tsx +0 -0
  86. /package/templates/{fe-react → react-app}/src/components/ThemeSwitcher.tsx +0 -0
  87. /package/templates/{fe-react → react-app}/src/containers/context/BaseRouteContext.ts +0 -0
  88. /package/templates/{fe-react → react-app}/src/containers/context/BaseRouteProvider.tsx +0 -0
  89. /package/templates/{fe-react → react-app}/src/hooks/useLanguageGuard.ts +0 -0
  90. /package/templates/{fe-react → react-app}/src/main.tsx +0 -0
  91. /package/templates/{fe-react → react-app}/src/pages/404.tsx +0 -0
  92. /package/templates/{fe-react → react-app}/src/pages/500.tsx +0 -0
  93. /package/templates/{fe-react → react-app}/src/pages/auth/Layout.tsx +0 -0
  94. /package/templates/{fe-react → react-app}/src/pages/auth/Login.tsx +0 -0
  95. /package/templates/{fe-react → react-app}/src/pages/auth/Register.tsx +0 -0
  96. /package/templates/{fe-react → react-app}/src/pages/base/About.tsx +0 -0
  97. /package/templates/{fe-react → react-app}/src/pages/base/Executor.tsx +0 -0
  98. /package/templates/{fe-react → react-app}/src/pages/base/Home.tsx +0 -0
  99. /package/templates/{fe-react → react-app}/src/pages/base/JSONStorage.tsx +0 -0
  100. /package/templates/{fe-react → react-app}/src/pages/base/Layout.tsx +0 -0
  101. /package/templates/{fe-react → react-app}/src/pages/base/RedirectPathname.tsx +0 -0
  102. /package/templates/{fe-react → react-app}/src/pages/base/Request.tsx +0 -0
  103. /package/templates/{fe-react → react-app}/src/pages/base/components/BaseHeader.tsx +0 -0
  104. /package/templates/{fe-react → react-app}/src/pages/index.tsx +0 -0
  105. /package/templates/{fe-react → react-app}/src/services/controllers/ExecutorController.ts +0 -0
  106. /package/templates/{fe-react → react-app}/src/services/controllers/JSONStorageController.ts +0 -0
  107. /package/templates/{fe-react → react-app}/src/services/controllers/RequestController.ts +0 -0
  108. /package/templates/{fe-react → react-app}/src/services/controllers/RouterController.ts +0 -0
  109. /package/templates/{fe-react → react-app}/src/services/feApi/index.ts +0 -0
  110. /package/templates/{fe-react → react-app}/src/services/i18n/index.ts +0 -0
  111. /package/templates/{fe-react → react-app}/src/services/pageProcesser/index.ts +0 -0
  112. /package/templates/{fe-react → react-app}/src/styles/css/index.css +0 -0
  113. /package/templates/{fe-react → react-app}/src/styles/css/page.css +0 -0
  114. /package/templates/{fe-react → react-app}/src/styles/css/tailwind.css +0 -0
  115. /package/templates/{fe-react → react-app}/src/types/Page.ts +0 -0
  116. /package/templates/{fe-react → react-app}/src/types/UIDependenciesInterface.ts +0 -0
  117. /package/templates/{fe-react → react-app}/src/types/global.d.ts +0 -0
  118. /package/templates/{fe-react → react-app}/src/utils/RequestLogger.ts +0 -0
  119. /package/templates/{fe-react → react-app}/src/utils/thread.ts +0 -0
  120. /package/templates/{fe-react → react-app}/tailwind.config.js +0 -0
  121. /package/templates/{fe-react → react-app}/tsconfig.app.json +0 -0
  122. /package/templates/{fe-react → react-app}/tsconfig.json +0 -0
  123. /package/templates/{fe-react → react-app}/tsconfig.node.json +0 -0
  124. /package/templates/{fe-react → react-app}/vite.config.ts +0 -0
  125. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/README.md +0 -0
  126. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/__tests__/Text.test.tsx +0 -0
  127. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/index.html +0 -0
  128. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/package.json +0 -0
  129. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/public/vite.svg +0 -0
  130. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/src/calc.ts +0 -0
  131. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/src/commponents/Text.tsx +0 -0
  132. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/src/index.ts +0 -0
  133. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/tsconfig.json +0 -0
  134. /package/templates/{pack-app/packages/react-vite-lib → react-vite-lib}/vite.config.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
 
2
2
 
3
+ ## [0.1.1](https://github.com/qlover/fe-base/compare/create-app-v0.0.4...create-app-v0.1.1) (2025-01-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * create app v0.1 ([#209](https://github.com/qlover/fe-base/issues/209)) ([b730d76](https://github.com/qlover/fe-base/commit/b730d76512a9e1ce765ec77145abfe179b585178))
9
+
10
+ ## [0.0.4](https://github.com/qlover/fe-base/compare/create-app-v0.0.3...create-app-v0.0.4) (2025-01-15)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * .gitignore no file ([#207](https://github.com/qlover/fe-base/issues/207)) ([e61d468](https://github.com/qlover/fe-base/commit/e61d4683a072048326205272d927e7e67b87ba70))
16
+
3
17
  ## 0.0.1 (2025-01-14)
4
18
 
5
19
  ## 0.0.2 (2025-01-14)
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ ## @qlover/create-app
2
+
3
+ ```
4
+ npx @qlover/create-app
5
+ ```
package/bin/create-app.js CHANGED
@@ -7,20 +7,18 @@ import { existsSync } from 'fs';
7
7
 
8
8
  async function main() {
9
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
10
- const templatePath = join(__dirname, '../templates');
10
+ const templateRootPath = join(__dirname, '../templates');
11
11
 
12
- const options = {
13
- options: {
14
- templatePath
15
- }
16
- };
17
-
18
- if (!existsSync(templatePath)) {
12
+ if (!existsSync(templateRootPath)) {
19
13
  console.error('Template is empty!');
20
14
  process.exit(1);
21
15
  }
22
16
 
23
- const generator = new Generator(options);
17
+ const generator = new Generator({
18
+ options: {
19
+ templateRootPath
20
+ }
21
+ });
24
22
 
25
23
  await generator.generate();
26
24
  }
@@ -3,13 +3,20 @@ import { Logger } from '@qlover/fe-utils';
3
3
  import { DistinctQuestion } from 'inquirer';
4
4
  import ignore from 'ignore';
5
5
 
6
+ type GeneratorPrompt = DistinctQuestion;
6
7
  type GeneratorOptions = {
7
- prompts?: DistinctQuestion[];
8
- templatePath: string;
8
+ prompts?: GeneratorPrompt[];
9
+ templateRootPath: string;
9
10
  };
10
- interface GeneratorResult {
11
+ interface GeneratorResult extends GeneratorOptions {
11
12
  name: string;
12
- templateName: string;
13
+ template: string;
14
+ subPackages?: string[];
15
+ /**
16
+ * @default `packages`
17
+ */
18
+ packagesNames?: string;
19
+ targetPath?: string;
13
20
  }
14
21
  type TaskOptions = {
15
22
  templateFiles: TemplateFile[];
@@ -19,17 +26,16 @@ type TemplateFile = {
19
26
  path: string;
20
27
  content: string;
21
28
  };
29
+
22
30
  declare class Generator {
23
- private prompts;
24
31
  private ora;
25
32
  protected context: FeScriptContext<GeneratorOptions>;
26
33
  constructor(context: Partial<FeScriptContext<GeneratorOptions>>);
27
34
  get logger(): Logger;
28
- steps(prompts: DistinctQuestion[]): Promise<GeneratorResult>;
29
- getTemplateFiles(path: string): Promise<TemplateFile[]>;
35
+ steps(prompts: GeneratorPrompt[]): Promise<GeneratorResult>;
30
36
  action({ label, task }: {
31
37
  label: string;
32
- task: () => Promise<unknown>;
38
+ task: (() => Promise<unknown>) | (() => unknown);
33
39
  }): Promise<unknown>;
34
40
  /**
35
41
  * Creates files and directories based on the provided template files.
@@ -38,30 +44,49 @@ declare class Generator {
38
44
  * to the file system. It handles both files and directories, ensuring that
39
45
  * the directory structure is preserved.
40
46
  *
41
- * @param templateFiles - An array of template files to be created.
42
47
  * @param result - The result object containing the name and template name.
43
48
  *
44
49
  * @returns A promise that resolves when all files have been created.
45
50
  *
46
51
  * @example
47
- * const templateFiles = [{ type: 'file', name: 'example.txt', content: 'Hello World' }];
48
- * await taskCreate({ templateFiles, result });
52
+ * const result = { name: 'my-app', template: 'react-app' };
53
+ * await this.create(result);
49
54
  */
50
- create(targetPath: string, name: string): Promise<void>;
55
+ create(result: GeneratorResult): Promise<void>;
56
+ private isPackageTemplate;
57
+ getGeneratorResult(): Promise<GeneratorResult>;
51
58
  generate(): Promise<void>;
52
59
  }
53
60
 
54
61
  declare const validRequiredString: (value: string, key: string) => string | true;
62
+ declare const defaultPrompts: GeneratorPrompt[];
63
+ declare const packagePrompts: GeneratorPrompt[];
55
64
 
56
65
  declare class Copyer {
57
- getIg(targetDir: string): ignore.Ignore;
66
+ static IGNORE_FILE: string;
67
+ getIg(targetDir: string): ignore.Ignore | undefined;
68
+ ensureDir(dir: string): void;
69
+ /**
70
+ * Asynchronously copy files from source to target directory.
71
+ * @param {string} sourcePath - Source directory.
72
+ * @param {string} targetDir - Target directory.
73
+ * @param {ignore.Ignore} ig - Ignore rules.
74
+ * @returns {Promise<void>} - A promise that resolves when the copy is complete.
75
+ * @example
76
+ * await copyer.copyFilesPromise('src', 'dest', ignoreInstance);
77
+ */
78
+ copyFilesPromise(sourcePath: string, targetDir: string, ig?: ignore.Ignore): Promise<void>;
58
79
  /**
59
80
  * copy templates recursively
60
- * @param {string} templatesDir - source directory
81
+ * @param {string} sourePath - source directory
61
82
  * @param {string} targetDir - target directory
62
83
  * @param {ignore.Ignore} ig - ignore rules
63
84
  */
64
- copyTemplates(templatesDir: string, targetDir: string, ig: ignore.Ignore): void;
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>;
65
90
  }
66
91
 
67
- export { Copyer, Generator, type GeneratorOptions, type GeneratorResult, type TaskOptions, type TemplateFile, validRequiredString };
92
+ export { Copyer, Generator, type GeneratorOptions, type GeneratorPrompt, type GeneratorResult, type TaskOptions, type TemplateFile, defaultPrompts, packagePrompts, validRequiredString };
package/dist/cjs/index.js CHANGED
@@ -1 +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;
1
+ "use strict";var t=require("@qlover/fe-scripts"),e=require("inquirer"),r=require("path"),i=require("ora"),s=require("fs"),o=require("ignore");function a(t,e,r,i){return new(r||(r=Promise))((function(s,o){function a(t){try{c(i.next(t))}catch(t){o(t)}}function n(t){try{c(i.throw(t))}catch(t){o(t)}}function c(t){var e;t.done?s(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(a,n)}c((i=i.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const n=(t,e)=>"string"==typeof t&&""!==t.trim()||`${e} is required`,c=["node-lib","react-app","react-vite-lib"],p=[{type:"input",name:"name",message:"Project name",validate:t=>n(t,"Project name")},{type:"list",name:"template",message:"Template name",choices:[...c,"pack-app"]}],h=[{type:"checkbox",name:"subPackages",message:"Sub package names",choices:c}],{copyFile:l,stat:u}=s.promises;class m{getIg(t){const e=r.join(t,m.IGNORE_FILE);if(!s.existsSync(e))return;const i=s.readFileSync(e,"utf8").split("\n").map((t=>t.trim())).filter((t=>t&&!t.startsWith("#")));return o().add(i)}ensureDir(t){s.existsSync(t)||s.mkdirSync(t,{recursive:!0})}copyFilesPromise(t,e,i){return a(this,void 0,void 0,(function*(){const o=yield s.promises.readdir(t);yield Promise.all(o.map((s=>a(this,void 0,void 0,(function*(){const o=r.join(t,s),a=r.join(e,s);if(i&&i.ignores(s))return;this.ensureDir(r.dirname(a));(yield u(o)).isDirectory()?yield this.copyFilesPromise(o,a,i):yield l(o,a)})))))}))}copyFilesSync(t,e,i){const o=s.readdirSync(t);for(const a of o){const o=r.join(t,a),n=r.join(e,a);i&&i.ignores(a)||(this.ensureDir(r.dirname(n)),s.statSync(o).isDirectory()?this.copyFilesSync(o,n,i):s.copyFileSync(o,n))}}create(t){const{targetPath:e,templateRootPath:i,subPackages:s,packagesNames:o="packages"}=t;if(!e||!i)throw new Error("targetPath and templatePath are required");if(this.createPath(t),s)for(const i of s){const s=r.join(e,o,i);this.createPath(Object.assign(Object.assign({},t),{targetPath:s,template:i}))}}createPromise(t){return a(this,void 0,void 0,(function*(){const{targetPath:e,templateRootPath:i,subPackages:s,packagesNames:o="packages"}=t;if(!e||!i)throw new Error("targetPath and templatePath are required");if(yield this.createPathPromise(t),s)for(const i of s){const s=r.join(e,o,i);yield this.createPathPromise(Object.assign(Object.assign({},t),{targetPath:s,template:i}))}}))}createPath(t){const{targetPath:e="",templateRootPath:i,template:s}=t;this.ensureDir(e);const o=r.join(i,s),a=this.getIg(e);this.copyFilesSync(o,e,a)}createPathPromise(t){const{targetPath:e="",templateRootPath:i,template:s}=t;this.ensureDir(e);const o=r.join(i,s),a=this.getIg(e);return this.copyFilesPromise(o,e,a)}}m.IGNORE_FILE=".gitignore.template";exports.Copyer=m,exports.Generator=class{constructor(e){var r;const o=null===(r=e.options)||void 0===r?void 0:r.templateRootPath;if(!o)throw new Error("template path not exit");if(!s.existsSync(o))throw new Error("template path not exit");this.ora=i.oraPromise,this.context=new t.FeScriptContext(e)}get logger(){return this.context.logger}steps(t){return a(this,void 0,void 0,(function*(){try{return yield e.prompt(t)}catch(t){throw this.logger.error(t),t}}))}action(t){return a(this,arguments,void 0,(function*({label:t,task:e}){let r=e();r instanceof Promise||(r=Promise.resolve(r));const i=t;return this.ora(r,i),r}))}create(t){return a(this,void 0,void 0,(function*(){const e=r.join(process.cwd(),t.name),i=new m,s=Object.assign(Object.assign({},t),{targetPath:e,templateRootPath:this.context.options.templateRootPath});return this.logger.debug(s),i.createPromise(s)}))}isPackageTemplate(t){return"pack-app"===t}getGeneratorResult(){return a(this,void 0,void 0,(function*(){const t=yield this.steps(p);if(this.isPackageTemplate(t.template)){const e=yield this.steps(h);Object.assign(t,e)}return t}))}generate(){return a(this,void 0,void 0,(function*(){const t=yield this.getGeneratorResult();yield this.action({label:"Creating project",task:()=>this.create(t)})}))}},exports.defaultPrompts=p,exports.packagePrompts=h,exports.validRequiredString=n;
@@ -3,13 +3,20 @@ import { Logger } from '@qlover/fe-utils';
3
3
  import { DistinctQuestion } from 'inquirer';
4
4
  import ignore from 'ignore';
5
5
 
6
+ type GeneratorPrompt = DistinctQuestion;
6
7
  type GeneratorOptions = {
7
- prompts?: DistinctQuestion[];
8
- templatePath: string;
8
+ prompts?: GeneratorPrompt[];
9
+ templateRootPath: string;
9
10
  };
10
- interface GeneratorResult {
11
+ interface GeneratorResult extends GeneratorOptions {
11
12
  name: string;
12
- templateName: string;
13
+ template: string;
14
+ subPackages?: string[];
15
+ /**
16
+ * @default `packages`
17
+ */
18
+ packagesNames?: string;
19
+ targetPath?: string;
13
20
  }
14
21
  type TaskOptions = {
15
22
  templateFiles: TemplateFile[];
@@ -19,17 +26,16 @@ type TemplateFile = {
19
26
  path: string;
20
27
  content: string;
21
28
  };
29
+
22
30
  declare class Generator {
23
- private prompts;
24
31
  private ora;
25
32
  protected context: FeScriptContext<GeneratorOptions>;
26
33
  constructor(context: Partial<FeScriptContext<GeneratorOptions>>);
27
34
  get logger(): Logger;
28
- steps(prompts: DistinctQuestion[]): Promise<GeneratorResult>;
29
- getTemplateFiles(path: string): Promise<TemplateFile[]>;
35
+ steps(prompts: GeneratorPrompt[]): Promise<GeneratorResult>;
30
36
  action({ label, task }: {
31
37
  label: string;
32
- task: () => Promise<unknown>;
38
+ task: (() => Promise<unknown>) | (() => unknown);
33
39
  }): Promise<unknown>;
34
40
  /**
35
41
  * Creates files and directories based on the provided template files.
@@ -38,30 +44,49 @@ declare class Generator {
38
44
  * to the file system. It handles both files and directories, ensuring that
39
45
  * the directory structure is preserved.
40
46
  *
41
- * @param templateFiles - An array of template files to be created.
42
47
  * @param result - The result object containing the name and template name.
43
48
  *
44
49
  * @returns A promise that resolves when all files have been created.
45
50
  *
46
51
  * @example
47
- * const templateFiles = [{ type: 'file', name: 'example.txt', content: 'Hello World' }];
48
- * await taskCreate({ templateFiles, result });
52
+ * const result = { name: 'my-app', template: 'react-app' };
53
+ * await this.create(result);
49
54
  */
50
- create(targetPath: string, name: string): Promise<void>;
55
+ create(result: GeneratorResult): Promise<void>;
56
+ private isPackageTemplate;
57
+ getGeneratorResult(): Promise<GeneratorResult>;
51
58
  generate(): Promise<void>;
52
59
  }
53
60
 
54
61
  declare const validRequiredString: (value: string, key: string) => string | true;
62
+ declare const defaultPrompts: GeneratorPrompt[];
63
+ declare const packagePrompts: GeneratorPrompt[];
55
64
 
56
65
  declare class Copyer {
57
- getIg(targetDir: string): ignore.Ignore;
66
+ static IGNORE_FILE: string;
67
+ getIg(targetDir: string): ignore.Ignore | undefined;
68
+ ensureDir(dir: string): void;
69
+ /**
70
+ * Asynchronously copy files from source to target directory.
71
+ * @param {string} sourcePath - Source directory.
72
+ * @param {string} targetDir - Target directory.
73
+ * @param {ignore.Ignore} ig - Ignore rules.
74
+ * @returns {Promise<void>} - A promise that resolves when the copy is complete.
75
+ * @example
76
+ * await copyer.copyFilesPromise('src', 'dest', ignoreInstance);
77
+ */
78
+ copyFilesPromise(sourcePath: string, targetDir: string, ig?: ignore.Ignore): Promise<void>;
58
79
  /**
59
80
  * copy templates recursively
60
- * @param {string} templatesDir - source directory
81
+ * @param {string} sourePath - source directory
61
82
  * @param {string} targetDir - target directory
62
83
  * @param {ignore.Ignore} ig - ignore rules
63
84
  */
64
- copyTemplates(templatesDir: string, targetDir: string, ig: ignore.Ignore): void;
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>;
65
90
  }
66
91
 
67
- export { Copyer, Generator, type GeneratorOptions, type GeneratorResult, type TaskOptions, type TemplateFile, validRequiredString };
92
+ export { Copyer, Generator, type GeneratorOptions, type GeneratorPrompt, type GeneratorResult, type TaskOptions, type TemplateFile, defaultPrompts, packagePrompts, validRequiredString };
package/dist/es/index.js CHANGED
@@ -1 +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};
1
+ import{FeScriptContext as t}from"@qlover/fe-scripts";import e from"inquirer";import{join as r,dirname as i}from"path";import{oraPromise as o}from"ora";import{existsSync as s,readFileSync as a,mkdirSync as n,readdirSync as c,statSync as h,copyFileSync as p,promises as l}from"fs";import m from"ignore";function u(t,e,r,i){return new(r||(r=Promise))((function(o,s){function a(t){try{c(i.next(t))}catch(t){s(t)}}function n(t){try{c(i.throw(t))}catch(t){s(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(a,n)}c((i=i.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const g=(t,e)=>"string"==typeof t&&""!==t.trim()||`${e} is required`,d=["node-lib","react-app","react-vite-lib"],f=[{type:"input",name:"name",message:"Project name",validate:t=>g(t,"Project name")},{type:"list",name:"template",message:"Template name",choices:[...d,"pack-app"]}],P=[{type:"checkbox",name:"subPackages",message:"Sub package names",choices:d}],{copyFile:y,stat:v}=l;class b{getIg(t){const e=r(t,b.IGNORE_FILE);if(!s(e))return;const i=a(e,"utf8").split("\n").map((t=>t.trim())).filter((t=>t&&!t.startsWith("#")));return m().add(i)}ensureDir(t){s(t)||n(t,{recursive:!0})}copyFilesPromise(t,e,o){return u(this,void 0,void 0,(function*(){const s=yield l.readdir(t);yield Promise.all(s.map((s=>u(this,void 0,void 0,(function*(){const a=r(t,s),n=r(e,s);if(o&&o.ignores(s))return;this.ensureDir(i(n));(yield v(a)).isDirectory()?yield this.copyFilesPromise(a,n,o):yield y(a,n)})))))}))}copyFilesSync(t,e,o){const s=c(t);for(const a of s){const s=r(t,a),n=r(e,a);o&&o.ignores(a)||(this.ensureDir(i(n)),h(s).isDirectory()?this.copyFilesSync(s,n,o):p(s,n))}}create(t){const{targetPath:e,templateRootPath:i,subPackages:o,packagesNames:s="packages"}=t;if(!e||!i)throw new Error("targetPath and templatePath are required");if(this.createPath(t),o)for(const i of o){const o=r(e,s,i);this.createPath(Object.assign(Object.assign({},t),{targetPath:o,template:i}))}}createPromise(t){return u(this,void 0,void 0,(function*(){const{targetPath:e,templateRootPath:i,subPackages:o,packagesNames:s="packages"}=t;if(!e||!i)throw new Error("targetPath and templatePath are required");if(yield this.createPathPromise(t),o)for(const i of o){const o=r(e,s,i);yield this.createPathPromise(Object.assign(Object.assign({},t),{targetPath:o,template:i}))}}))}createPath(t){const{targetPath:e="",templateRootPath:i,template:o}=t;this.ensureDir(e);const s=r(i,o),a=this.getIg(e);this.copyFilesSync(s,e,a)}createPathPromise(t){const{targetPath:e="",templateRootPath:i,template:o}=t;this.ensureDir(e);const s=r(i,o),a=this.getIg(e);return this.copyFilesPromise(s,e,a)}}b.IGNORE_FILE=".gitignore.template";class k{constructor(e){var r;const i=null===(r=e.options)||void 0===r?void 0:r.templateRootPath;if(!i)throw new Error("template path not exit");if(!s(i))throw new Error("template path not exit");this.ora=o,this.context=new t(e)}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}}))}action(t){return u(this,arguments,void 0,(function*({label:t,task:e}){let r=e();r instanceof Promise||(r=Promise.resolve(r));const i=t;return this.ora(r,i),r}))}create(t){return u(this,void 0,void 0,(function*(){const e=r(process.cwd(),t.name),i=new b,o=Object.assign(Object.assign({},t),{targetPath:e,templateRootPath:this.context.options.templateRootPath});return this.logger.debug(o),i.createPromise(o)}))}isPackageTemplate(t){return"pack-app"===t}getGeneratorResult(){return u(this,void 0,void 0,(function*(){const t=yield this.steps(f);if(this.isPackageTemplate(t.template)){const e=yield this.steps(P);Object.assign(t,e)}return t}))}generate(){return u(this,void 0,void 0,(function*(){const t=yield this.getGeneratorResult();yield this.action({label:"Creating project",task:()=>this.create(t)})}))}}export{b as Copyer,k as Generator,f as defaultPrompts,P as packagePrompts,g as validRequiredString};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlover/create-app",
3
- "version": "0.0.3",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/es/index.js",
@@ -28,7 +28,9 @@
28
28
  "create-app": "./bin/create-app.js"
29
29
  },
30
30
  "scripts": {
31
- "build": "node ./scripts/copy-templates.js && rollup -c"
31
+ "build": "rollup -c",
32
+ "create:app:build": "npm run build && npm run create:app",
33
+ "create:app": "node ./bin/create-app.js"
32
34
  },
33
35
  "repository": {
34
36
  "type": "git",
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "@qlover/pack-app-node",
2
+ "name": "@qlover/node-lib",
3
3
  "version": "0.0.1",
4
4
  "main": "index.js",
5
5
  "type": "module",
@@ -0,0 +1,50 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ node_modules
5
+ /.pnp
6
+ .pnp.js
7
+
8
+ # testing
9
+ /coverage
10
+
11
+ # next.js
12
+ /.next/
13
+ /out/
14
+
15
+ # production
16
+ /build
17
+
18
+ # misc
19
+ .DS_Store
20
+ *.pem
21
+
22
+ # debug
23
+ npm-debug.log*
24
+ yarn-debug.log*
25
+ yarn-error.log*
26
+ .pnpm-debug.log*
27
+
28
+ # local env files
29
+ .env*.local
30
+
31
+ # vercel
32
+ .vercel
33
+
34
+ # typescript
35
+ *.tsbuildinfo
36
+ next-env.d.ts
37
+
38
+ /package-lock.json
39
+ /yarn.lock
40
+ .husky
41
+ /pnpm-lock.yaml
42
+ public/robots.txt
43
+ public/sitemap*.xml
44
+ dist
45
+ .eslintcache
46
+ .npmrc
47
+ .secrets
48
+
49
+ # local output dir
50
+ *.output/
@@ -10,10 +10,8 @@
10
10
  },
11
11
  "homepage": "https://github.com/qlover/fe-base#readme",
12
12
  "scripts": {
13
- "build": "pnpm run build:node && pnpm run build:browser && pnpm run build:react",
14
- "build:node": "pnpm run build --filter=@qlover/pack-app-node",
15
- "build:browser": "pnpm run build --filter=@qlover/pack-app-browser",
16
- "build:react": "pnpm run build --filter=@qlover/pack-app-react",
13
+ "build": "pnpm run build:[PKG_NAME]",
14
+ "build:[PKG_NAME]": "pnpm run build --filter=@qlover/${PKG_NAME}",
17
15
  "prettier": "prettier --ignore-path .prettierignore **/*.{js,ts,json,cjs,mjs} --write",
18
16
  "lint": "eslint . --fix",
19
17
  "test": "jest",
@@ -33,9 +31,9 @@
33
31
  "node": ">=18.19.0"
34
32
  },
35
33
  "devDependencies": {
36
- "@qlover/fe-scripts": "^0.5.1",
37
- "@qlover/fe-standard": "^0.0.2",
38
- "@qlover/fe-utils": "^1.1.3",
34
+ "@qlover/fe-scripts": "latest",
35
+ "@qlover/fe-standard": "latest",
36
+ "@qlover/fe-utils": "latest",
39
37
  "@rollup/plugin-commonjs": "^28.0.1",
40
38
  "@rollup/plugin-json": "^6.1.0",
41
39
  "@rollup/plugin-node-resolve": "^15.3.0",
@@ -0,0 +1,32 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+ # typescript
15
+ *.tsbuildinfo
16
+
17
+ # Editor directories and files
18
+ .vscode/*
19
+ !.vscode/extensions.json
20
+ .idea
21
+ .DS_Store
22
+ *.suo
23
+ *.ntvs*
24
+ *.njsproj
25
+ *.sln
26
+ *.sw?
27
+
28
+ # lock
29
+ yarn.lock
30
+ pnpm-lock.yaml
31
+ pnpm-lock.yml
32
+ package-lock.json
@@ -1,4 +1,4 @@
1
- import { isProduction } from "@/containers/globals";
1
+ import { isProduction } from '@/containers/globals';
2
2
 
3
3
  /** @type {import('i18next').InitOptions} */
4
4
  export const i18nConfig = {
@@ -1,3 +1,3 @@
1
1
  export * from './ThemeController';
2
2
  export * from './ThemeStateGetter';
3
- export * from './type';
3
+ export * from './type';
@@ -3,7 +3,6 @@ import template from 'lodash/template';
3
3
  import isPlainObject from 'lodash/isPlainObject';
4
4
  import isString from 'lodash/isString';
5
5
 
6
-
7
6
  class KeyTemplate {
8
7
  constructor(options) {
9
8
  /**
@@ -1,3 +1,3 @@
1
1
  export * from './OpenAIClient';
2
2
  export * from './OpenAIAuthPlugin';
3
- export * from './StreamProcessor';
3
+ export * from './StreamProcessor';
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  plugins: {
3
3
  tailwindcss: {},
4
- autoprefixer: {},
5
- },
6
- }
4
+ autoprefixer: {}
5
+ }
6
+ };
@@ -1,4 +1,4 @@
1
- //! global variables, don't import any dependencies and don't have side effects
1
+ // ! global variables, don't import any dependencies and don't have side effects
2
2
  import {
3
3
  JSONStorage,
4
4
  JSONSerializer,
@@ -1,4 +1,4 @@
1
- //! dont't import tsx, only ts file
1
+ // ! dont't import tsx, only ts file
2
2
  import { FetchAbortPlugin, FetchURLPlugin } from '@qlover/fe-utils';
3
3
  import { OpenAIClient } from '@lib/openAiApi';
4
4
  import { ThemeController } from '@lib/fe-react-theme/ThemeController';
@@ -14,8 +14,11 @@ export const useStrictEffect = (
14
14
 
15
15
  useEffect(() => {
16
16
  // Check if the dependencies have changed
17
- const depsChanged = !deps || !depsRef.current || deps.some((dep, i) => dep !== depsRef.current![i]);
18
-
17
+ const depsChanged =
18
+ !deps ||
19
+ !depsRef.current ||
20
+ deps.some((dep, i) => dep !== depsRef.current![i]);
21
+
19
22
  // Update the dependency reference
20
23
  depsRef.current = deps;
21
24
 
@@ -24,6 +27,6 @@ export const useStrictEffect = (
24
27
  mountedRef.current = true;
25
28
  return effect();
26
29
  }
27
- // eslint-disable-next-line react-hooks/exhaustive-deps
30
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
31
  }, deps);
29
- };
32
+ };
@@ -1,7 +1,7 @@
1
1
  import { ExecutorPlugin, JSONStorage } from '@qlover/fe-utils';
2
2
  import { sleep } from '@/utils/thread';
3
3
  import { FeController } from '@lib/fe-react-controller';
4
- import { FeApi, } from '@/services/feApi';
4
+ import { FeApi } from '@/services/feApi';
5
5
  import { FeApiGetUserInfo, FeApiLogin } from '@/services/feApi/FeApiType';
6
6
  import { adjustExpirationTime } from '@/utils/datetime';
7
7
  import { RouterController } from './RouterController';
@@ -14,7 +14,7 @@ import {
14
14
 
15
15
  export class FeApi extends RequestScheduler<RequestAdapterConfig> {
16
16
  private abortPlugin: FetchAbortPlugin;
17
-
17
+
18
18
  constructor({
19
19
  abortPlugin,
20
20
  config
@@ -9,7 +9,9 @@ import { sleep } from '@/utils/thread';
9
9
  export class FeApiMockPlugin implements ExecutorPlugin {
10
10
  readonly pluginName = 'FeApiMockPlugin';
11
11
 
12
- constructor(private readonly mockDataJson: typeof import('@config/feapi.mock.json')) {}
12
+ constructor(
13
+ private readonly mockDataJson: typeof import('@config/feapi.mock.json')
14
+ ) {}
13
15
 
14
16
  async onExec({
15
17
  parameters
@@ -37,7 +37,6 @@ export type FeApiGetRandomUser = FeApiType<
37
37
  }
38
38
  >;
39
39
 
40
-
41
40
  export type FeApiGetUserInfo = FeApiType<
42
41
  string,
43
42
  {
@@ -17,7 +17,7 @@ export class PageProcesser {
17
17
 
18
18
  handler(): Promise<{ success: boolean }> {
19
19
  return Promise.resolve({
20
- success: true,
20
+ success: true
21
21
  });
22
22
  }
23
23
 
@@ -1,13 +1,16 @@
1
1
  /**
2
2
  * Adjusts the expiration time based on the provided `expiresIn` value.
3
- *
3
+ *
4
4
  * @param {number} baseTime - The base time in milliseconds to adjust.
5
5
  * @returns {number} - The adjusted time in milliseconds.
6
- *
6
+ *
7
7
  * @example
8
8
  * const adjustedTime = userController.adjustExpirationTime(Date.now());
9
9
  */
10
- export function adjustExpirationTime(baseTime: number, expiresIn: number | 'day' | 'week' | 'month' | 'year'): number {
10
+ export function adjustExpirationTime(
11
+ baseTime: number,
12
+ expiresIn: number | 'day' | 'week' | 'month' | 'year'
13
+ ): number {
11
14
  const dayInMs = 24 * 60 * 60 * 1000;
12
15
 
13
16
  switch (expiresIn) {
@@ -20,6 +23,8 @@ export function adjustExpirationTime(baseTime: number, expiresIn: number | 'day'
20
23
  case 'year':
21
24
  return baseTime + 365 * dayInMs; // Approximation
22
25
  default:
23
- return baseTime + (typeof expiresIn === 'number' ? expiresIn : 30 * dayInMs);
26
+ return (
27
+ baseTime + (typeof expiresIn === 'number' ? expiresIn : 30 * dayInMs)
28
+ );
24
29
  }
25
- }
30
+ }
@@ -0,0 +1 @@
1
+ // / <reference types="vite/client" />
@@ -0,0 +1,27 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
+ .idea
19
+ .DS_Store
20
+ *.suo
21
+ *.ntvs*
22
+ *.njsproj
23
+ *.sln
24
+ *.sw?
25
+
26
+ tsconfig.app.json
27
+ tsconfig.node.json
@@ -1,4 +1,4 @@
1
- import { sum } from '../src/sum';
1
+ import { sum } from '../src/calc';
2
2
 
3
3
  describe('sum 函数测试', () => {
4
4
  it('应该返回两个数字的和', () => {