@nutin/cli 1.1.0 → 1.2.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.
- package/CHANGELOG.md +69 -6
- package/README.md +49 -2
- package/lib/index.mjs +9 -9
- package/lib/src/file-generator.mjs +24 -9
- package/lib/src/package-manager.mjs +72 -51
- package/lib/src/prompts.mjs +10 -10
- package/lib/src/utils.mjs +4 -1
- package/package.json +4 -3
- package/templates/base/.dockerignore.hbs +12 -2
- package/templates/base/README.md.hbs +23 -0
- package/templates/base/builder.config.js.hbs +28 -0
- package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +11 -12
- package/templates/base/src/app/dom.test.js.hbs +8 -1
- package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +2 -1
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +11 -11
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +3 -0
- package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.ts.hbs +3 -0
- package/templates/base/src/core/base-classes/base-component/helpers/token.helper.ts.hbs +5 -4
- package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +55 -27
- package/templates/base/src/core/services/http-client/http-client.ts.hbs +24 -17
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +3 -3
- package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.ts.hbs +2 -2
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +25 -10
- package/templates/base/src/core/services/router/router.ts.hbs +1 -0
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +4 -3
- package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +1 -1
- package/templates/base/src/index.html.hbs +2 -2
- package/templates/base/src/libs/popover/popover.ts.hbs +2 -1
- package/templates/base/src/styles/main.scss.hbs +4 -1
- package/templates/base/tools/builder/builder.js.hbs +19 -26
- package/templates/base/tools/builder/core/copy-static.js.hbs +41 -20
- package/templates/base/tools/builder/core/esbuild.js.hbs +26 -0
- package/templates/base/tools/builder/core/finalize-build.js.hbs +24 -0
- package/templates/base/tools/builder/core/minify-html.js.hbs +60 -0
- package/templates/base/tools/builder/core/paths.js.hbs +19 -0
- package/templates/base/tools/builder/core/sass.js.hbs +22 -0
- package/templates/base/tools/builder/core/tsc.js.hbs +12 -0
- package/templates/base/tools/builder/core/validate-html.js.hbs +32 -12
- package/templates/base/tools/deployment/Dockerfile.hbs +22 -0
- package/templates/base/tools/deployment/gzip.conf.hbs +19 -0
- package/templates/base/tools/deployment/nginx.conf.hbs +78 -0
- package/templates/base/tools/dev/dev-serve.js.hbs +32 -0
- package/templates/base/tools/dev/serve.js.hbs +23 -0
- package/templates/base/tools/{watcher.js.hbs → dev/watcher.js.hbs} +8 -8
- package/templates/base/tools/generator/generator.js.hbs +21 -6
- package/templates/base/tools/generator/handle-file.js.hbs +32 -2
- package/templates/base/tools/generator/templates/index.js.hbs +3 -0
- package/templates/base/tools/utils/export-flags.js.hbs +6 -0
- package/templates/base/tools/utils/get-files-recursive.js.hbs +1 -3
- package/templates/base/tools/utils/index.js.hbs +8 -1
- package/templates/base/tools/utils/prompt-boolean.js.hbs +15 -0
- package/templates/base/tools/utils/run-command.js.hbs +12 -0
- package/templates/base/tools/utils/run-script.js.hbs +22 -0
- package/templates/features/i18n/src/core/config.ts.hbs +3 -0
- package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +2 -0
- package/templates/features/i18n/src/core/services/i18n/i18n.ts.hbs +10 -1
- package/templates/features/i18n/src/core/services/i18n/languages.ts.hbs +7 -0
- package/templates/features/i18n/tools/builder/core/build-i18n.js.hbs +12 -17
- package/templates/features/i18n/tools/utils/languages.js.hbs +7 -0
- package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +1 -1
- package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -0
- package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
- package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +4 -0
- package/templates/features/template/tools/builder/core/merge-templates.js.hbs +13 -26
- package/templates/features/testinNutin/{test → testin-nutin}/core/index.js.hbs +1 -1
- package/templates/features/testinNutin/testin-nutin/core/src/globals/assertion-lib.js.hbs +136 -0
- package/templates/features/testinNutin/testin-nutin/core/src/globals/jsdom-setup.js.hbs +101 -0
- package/templates/features/testinNutin/{test → testin-nutin}/core/src/globals/register-test-globals.js.hbs +15 -1
- package/templates/features/testinNutin/testin-nutin/core/src/globals/spyon.js.hbs +59 -0
- package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/print.js.hbs +3 -1
- package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/test-discovery.js.hbs +5 -1
- package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/test-queue.js.hbs +3 -1
- package/templates/features/testinNutin/{test → testin-nutin}/core/tests/assertions.test.js.hbs +26 -2
- package/templates/features/testinNutin/testin-nutin/runner.js.hbs +35 -0
- package/templates/features/testinNutin/{test → testin-nutin}/watch-tests.js.hbs +1 -1
- package/templates/features/testinNutin/testin-nutin.config.js.hbs +14 -0
- package/templates/base/Dockerfile.hbs +0 -13
- package/templates/base/tools/builder/core/sass.config.js.hbs +0 -17
- package/templates/base/tools/builder/docs.md.hbs +0 -9
- package/templates/features/testinNutin/test/core/src/globals/assertion-lib.js.hbs +0 -118
- package/templates/features/testinNutin/test/core/src/globals/spyon.js.hbs +0 -22
- package/templates/features/testinNutin/test/core/src/jsdom-setup.js.hbs +0 -12
- package/templates/features/testinNutin/test/docs.md.hbs +0 -39
- package/templates/features/testinNutin/test/runner.js.hbs +0 -36
- /package/templates/features/testinNutin/{test → testin-nutin}/core/src/utils/queue.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/core/tests/globals-each-all.test.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/mocks/create-mock-method.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-event-bus.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-http-client.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-i18n.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-router.js.hbs +0 -0
- /package/templates/features/testinNutin/{test → testin-nutin}/mocks/mock-store.js.hbs +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,19 +1,74 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## V1.
|
|
3
|
+
## V1.2.1
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- Builder
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Added config file `builder.config.js` file (esbuild, verbose)
|
|
8
8
|
|
|
9
|
-
-
|
|
9
|
+
- I18N
|
|
10
|
+
|
|
11
|
+
- Added JSON config file for centralized languages (`config/languages.json`)
|
|
12
|
+
|
|
13
|
+
- testin-nutin
|
|
14
|
+
|
|
15
|
+
- Added config file `test.config.js` (origins array, verbose boolean)
|
|
16
|
+
- Added assertions + automated 'not' counterparts
|
|
17
|
+
- Improved spyOn
|
|
18
|
+
- Improved JSDOM setup & global registration
|
|
19
|
+
|
|
20
|
+
- Improved deployment tools Dockerfile (nginx conf + gzip)
|
|
21
|
+
|
|
22
|
+
- Fixed typo and added comments in `nginx.conf`.
|
|
23
|
+
- Extracted gzip config from Dockerfile (removed `sed` command)
|
|
24
|
+
- Moved Dockerfile and deployment config files (`nginx.conf`, `gzip.conf`) into their own folder `tools/deployment`.
|
|
25
|
+
- Added `docker:build` and `docker:run` scripts in package.json.
|
|
26
|
+
|
|
27
|
+
See [DEPLOYMENT.md file](../../docs/DEPLOYMENT_HELPERS.md) for details.
|
|
28
|
+
|
|
29
|
+
- Moved dev tools (`serve.js`, `dev-serve.js`, `watcher.js`) into their own `tools/dev` folder.
|
|
30
|
+
|
|
31
|
+
- Added explicit chokidar devDependency (sass & live-server transitive).
|
|
32
|
+
|
|
33
|
+
## V1.2.0
|
|
34
|
+
|
|
35
|
+
- Fixed `npm run dev` command. Added middleware to reload nested routes.
|
|
36
|
+
|
|
37
|
+
- Improved `data-optional` tag:
|
|
38
|
+
- Can now specify which attribute to check with `data-optional="attrName"` (`src`, `href`, ...)
|
|
39
|
+
- Now works for `img`, `input`, etc
|
|
40
|
+
|
|
41
|
+
- Event Bus :
|
|
42
|
+
- Tracks both event name + callback.
|
|
43
|
+
- cleanupEventListeners now works correctly.
|
|
44
|
+
- New property: `once`. `once` subscriptions automatically remove themselves after first call.
|
|
45
|
+
|
|
46
|
+
- HTTP client :
|
|
47
|
+
- Optional request / response interceptors.
|
|
48
|
+
- Full timeout / abort controller support preserved.
|
|
49
|
+
- onDestroy now clears interceptors to prevent memory leaks.
|
|
50
|
+
|
|
51
|
+
- Improved builder
|
|
52
|
+
|
|
53
|
+
- Implemented `esbuild` & `html-minifier-terser`.
|
|
54
|
+
- Added flags `--bundle` (for production-ready build. *`npm run build --bundle` is equivalent to `npm run build:prod`)* and `--log` (verbose output). **Doesn't work with yarn or bun**.
|
|
55
|
+
- Commands: `npm run build`, `npm run build:prod`, `npm run serve:only`, `npm run serve`, `npm run dev`.
|
|
56
|
+
|
|
57
|
+
*Note: `--prod` or `--production` will set NODE_ENV to production, and have the same effect as `--bundle`.* `const isProd = process.env.npm_config_bundle || process.env.NODE_ENV === 'production';`
|
|
58
|
+
|
|
59
|
+
- Improved deployment tools Dockerfile (nginx conf + gzip)
|
|
60
|
+
|
|
61
|
+
See [DEPLOYMENT.md file](../../docs/DEPLOYMENT_HELPERS.md) for details.
|
|
62
|
+
|
|
63
|
+
- stylin-nutin (generator)
|
|
64
|
+
- When generating a component, prompts (boolean) to generate a `_component-name.scss` file in `styles/components` (forwarded by `stymes/components/_index.scss`).
|
|
10
65
|
|
|
11
66
|
## V1.1.0
|
|
12
67
|
|
|
13
68
|
- Added index access in CatalogConfig. Use with `config.index`.
|
|
14
69
|
```typescript
|
|
15
70
|
interface CatalogItemBase {
|
|
16
|
-
|
|
71
|
+
index: number;
|
|
17
72
|
}
|
|
18
73
|
type CatalogItemObject<T extends object> = T & CatalogItemBase;
|
|
19
74
|
interface CatalogItemPrimitive extends CatalogItemBase {
|
|
@@ -25,4 +80,12 @@ type CatalogItemConfig<T = any> =
|
|
|
25
80
|
T extends object ? CatalogItemObject<T> : CatalogItemPrimitive;
|
|
26
81
|
```
|
|
27
82
|
|
|
28
|
-
**Notes:** *Primitive data arrays (string, number, etc) needs to be accessed with `config.value`.*
|
|
83
|
+
**Notes:** *Primitive data arrays (string, number, etc) needs to be accessed with `config.value`.*
|
|
84
|
+
|
|
85
|
+
## V1.0.2
|
|
86
|
+
|
|
87
|
+
- Partially fixed `npm run dev` script when using internal templates. *Page still needs to be reload manually from time to time.*
|
|
88
|
+
|
|
89
|
+
## V1.0.1
|
|
90
|
+
|
|
91
|
+
- Fixed typo issue when using i18n feature
|
package/README.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# [nutin](https://www.nutin.org)
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Build SPAs by understanding SPAs. A minimal frontend toolkit crafted for learning and lean applications.**
|
|
4
4
|
Includes essential features out of the box, with zero runtime dependencies.
|
|
5
|
-
*TypeScript/Javascript,SASS,HTML*
|
|
5
|
+
*TypeScript / Javascript, SASS, HTML*
|
|
6
|
+
|
|
7
|
+
- Required : Node >=18 **If using testin-nutin: Node >=20.19.0 (JSDOM requirement : `{ node: '^20.19.0 || ^22.12.0 || >=24.0.0' }`)**
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# install package globally
|
|
13
|
+
npm install -g @nutin/cli
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## New App
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# create a new app
|
|
20
|
+
create-nutin-app # or
|
|
21
|
+
nutin-new
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- Flags
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# argument: project-name
|
|
28
|
+
|
|
29
|
+
-d --defaults
|
|
30
|
+
-pm --package-manager <manager> # npm (Default), yarn, pnpm, bun
|
|
31
|
+
|
|
32
|
+
--no-template # Use inline templates
|
|
33
|
+
--no-stylin-nutin # Do not use built-in SCSS utility
|
|
34
|
+
--testin-nutin # Use testin-nutin toolkit
|
|
35
|
+
--no-i18n # Do not use i18n & json-based content
|
|
36
|
+
--transition # Use animated view transitions. Note: May interfere with CSS `position: fixed`, `z-index`...
|
|
37
|
+
|
|
38
|
+
# Defaults
|
|
39
|
+
--template # (Default) Use external templates
|
|
40
|
+
--stylin-nutin # (Default) Use built-in SCSS utility classes & mixins
|
|
41
|
+
--i18n # (Default) Use i18n & json-based content
|
|
42
|
+
--no-testin-nutin # (Default) Do not use testin-nutin toolkit
|
|
43
|
+
--no-transition # (Default) Do not use animated view transitions
|
|
44
|
+
|
|
45
|
+
# Help
|
|
46
|
+
-h --help
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## [First app tutorial](https://www.nutin.org/tutorial)
|
|
50
|
+
|
|
51
|
+
- Visit the [website](https://www.nutin.org)
|
|
52
|
+
- [Project repository](https://github.com/LoisKOUNINEF/nutin)
|
package/lib/index.mjs
CHANGED
|
@@ -2,24 +2,24 @@ import { program } from 'commander';
|
|
|
2
2
|
import { print } from './src/print.mjs';
|
|
3
3
|
import { promptUser } from './src/prompts.mjs';
|
|
4
4
|
import { createProject } from './src/file-generator.mjs';
|
|
5
|
-
import { displaySuccessMessage } from './src/utils.mjs';
|
|
5
|
+
import { displaySuccessMessage, packageVersion } from './src/utils.mjs';
|
|
6
6
|
|
|
7
7
|
export async function createApp() {
|
|
8
8
|
program
|
|
9
|
-
.version(
|
|
9
|
+
.version(packageVersion)
|
|
10
10
|
.argument('[projectName]', 'Name of the project')
|
|
11
11
|
.option('-d, --defaults', 'Use default options')
|
|
12
|
-
.option('-pm, --package-manager <manager>', 'Specify package manager (npm, yarn, pnpm)')
|
|
13
|
-
.option('--template', 'Use external templates')
|
|
14
|
-
.option('--no-template', '
|
|
12
|
+
.option('-pm, --package-manager <manager>', 'Specify package manager (npm, yarn, pnpm, bun)')
|
|
13
|
+
.option('--template', '(Default) Use external templates')
|
|
14
|
+
.option('--no-template', 'Do not use external templates')
|
|
15
15
|
.option('--stylin-nutin', '(Default) Use built-in SCSS utility classes & mixins')
|
|
16
16
|
.option('--no-stylin-nutin', 'Do not use built-in SCSS utility')
|
|
17
|
-
.option('--i18n', 'Use i18n & json-based content')
|
|
18
|
-
.option('--no-i18n', '
|
|
19
|
-
.option('--transition', 'Use animated view transitions\nNote: May interfere with CSS `position: fixed`, `z-index`...')
|
|
20
|
-
.option('--no-transition', '(Default) Do not use animated view transitions')
|
|
17
|
+
.option('--i18n', '(Default) Use i18n & json-based content')
|
|
18
|
+
.option('--no-i18n', 'Do not use i18n & json-based content')
|
|
21
19
|
.option('--testin-nutin', 'Use testin-nutin toolkit')
|
|
22
20
|
.option('--no-testin-nutin', '(Default) Do not use testin-nutin toolkit')
|
|
21
|
+
.option('--transition', 'Use animated view transitions\nNote: May interfere with CSS `position: fixed`, `z-index`...')
|
|
22
|
+
.option('--no-transition', '(Default) Do not use animated view transitions')
|
|
23
23
|
.addHelpText('afterAll', '\nChaining options :\nExample: -d -pm npm --i18n --testinNutin')
|
|
24
24
|
.action(async (projectName, cliOptions) => {
|
|
25
25
|
print.blue('🚀 Welcome to nutin !');
|
|
@@ -4,7 +4,8 @@ import * as fsExtra from 'fs-extra';
|
|
|
4
4
|
import { TemplateCompiler } from './template-compiler.mjs';
|
|
5
5
|
import { print } from './print.mjs';
|
|
6
6
|
import { initializeGit } from './git-manager.mjs';
|
|
7
|
-
import { installDependencies, generatePackageJson, generateTsconfigJson } from './package-manager.mjs';
|
|
7
|
+
import { installDependencies, generatePackageJson, generateTsconfigJson, getCiCommand } from './package-manager.mjs';
|
|
8
|
+
import { packageVersion } from './utils.mjs';
|
|
8
9
|
|
|
9
10
|
const fs = fsExtra.default;
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -48,14 +49,15 @@ export class ProjectGenerator {
|
|
|
48
49
|
const context = this.buildContext(answers);
|
|
49
50
|
const templateDir = this.getTemplateDirectory(answers);
|
|
50
51
|
|
|
51
|
-
print.section('
|
|
52
|
+
print.section('📝 Processing templates...');
|
|
52
53
|
await this.processTemplateDirectory(templateDir, projectPath, context);
|
|
53
54
|
|
|
54
55
|
await this.processFeatureTemplates(projectPath, context);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
buildContext(answers) {
|
|
58
|
-
const version =
|
|
59
|
+
const version = packageVersion;
|
|
60
|
+
const ciCommand = getCiCommand(answers.packageManager);
|
|
59
61
|
|
|
60
62
|
return {
|
|
61
63
|
projectName: answers.projectName,
|
|
@@ -71,6 +73,7 @@ export class ProjectGenerator {
|
|
|
71
73
|
|
|
72
74
|
year: new Date().getFullYear(),
|
|
73
75
|
packageManager: answers.packageManager || 'npm',
|
|
76
|
+
ciCommand: ciCommand,
|
|
74
77
|
version: version
|
|
75
78
|
};
|
|
76
79
|
}
|
|
@@ -111,7 +114,7 @@ export class ProjectGenerator {
|
|
|
111
114
|
if (BINARY_EXTENSIONS.has(fileExt)) {
|
|
112
115
|
const outputPath = path.join(outputDir, fileName);
|
|
113
116
|
await fs.copy(templatePath, outputPath);
|
|
114
|
-
print.info(`📄 Copied: ${fileName}`);
|
|
117
|
+
// print.info(`📄 Copied: ${fileName}`);
|
|
115
118
|
} else if (fileName.endsWith('.hbs')) {
|
|
116
119
|
|
|
117
120
|
const outputFileName = fileName.replace('.hbs', '');
|
|
@@ -120,7 +123,7 @@ export class ProjectGenerator {
|
|
|
120
123
|
try {
|
|
121
124
|
const compiledContent = await this.compiler.compileFile(templatePath, context);
|
|
122
125
|
await fs.writeFile(outputPath, compiledContent);
|
|
123
|
-
print.info(`📝 Generated: ${outputFileName}`);
|
|
126
|
+
// print.info(`📝 Generated: ${outputFileName}`);
|
|
124
127
|
} catch (error) {
|
|
125
128
|
print.boldError(`❌ Failed to process template: ${fileName}`);
|
|
126
129
|
throw error;
|
|
@@ -128,7 +131,7 @@ export class ProjectGenerator {
|
|
|
128
131
|
} else {
|
|
129
132
|
const outputPath = path.join(outputDir, fileName);
|
|
130
133
|
await fs.copy(templatePath, outputPath);
|
|
131
|
-
print.info(`📄 Copied: ${fileName}`);
|
|
134
|
+
// print.info(`📄 Copied: ${fileName}`);
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
|
|
@@ -146,7 +149,7 @@ export class ProjectGenerator {
|
|
|
146
149
|
const featureTemplateDir = path.join(featuresDir, feature);
|
|
147
150
|
|
|
148
151
|
if (await fs.pathExists(featureTemplateDir)) {
|
|
149
|
-
print.info(
|
|
152
|
+
print.info(`🔧 Adding ${feature} feature...`);
|
|
150
153
|
await this.processTemplateDirectory(featureTemplateDir, projectPath, context);
|
|
151
154
|
}
|
|
152
155
|
}
|
|
@@ -156,6 +159,18 @@ export class ProjectGenerator {
|
|
|
156
159
|
async generateJsonFiles(projectPath, answers) {
|
|
157
160
|
await generatePackageJson(projectPath, answers);
|
|
158
161
|
await generateTsconfigJson(projectPath, answers);
|
|
162
|
+
if (answers.i18n) this.generateConfigFiles(projectPath);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async generateConfigFiles(projectPath) {
|
|
166
|
+
const configPath = path.join(projectPath, 'config');
|
|
167
|
+
await fs.ensureDir(configPath);
|
|
168
|
+
const languages = {
|
|
169
|
+
"languages": ["en"],
|
|
170
|
+
"defaultLanguage": "en"
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
await fs.writeJSON(path.join(configPath, 'languages.json'), languages, { spaces: 2 });
|
|
159
174
|
}
|
|
160
175
|
|
|
161
176
|
async runPostSetupTasks(projectPath, answers) {
|
|
@@ -168,10 +183,10 @@ export class ProjectGenerator {
|
|
|
168
183
|
}
|
|
169
184
|
|
|
170
185
|
async runSetupScripts(projectPath, answers) {
|
|
171
|
-
print.section('
|
|
186
|
+
print.section('⚙️ Running setup scripts...');
|
|
172
187
|
|
|
173
188
|
try {
|
|
174
|
-
const setupScriptsTemplate = path.join(__dirname, '
|
|
189
|
+
const setupScriptsTemplate = path.join(__dirname, '..', '..', 'templates', 'scripts');
|
|
175
190
|
|
|
176
191
|
if (await fs.pathExists(setupScriptsTemplate)) {
|
|
177
192
|
const scriptsDir = path.join(projectPath, 'scripts');
|
|
@@ -12,84 +12,102 @@ export async function installDependencies(projectPath, packageManager) {
|
|
|
12
12
|
await promiseExec(installCommand, { cwd: projectPath });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function
|
|
15
|
+
export function getCiCommand(packageManager) {
|
|
16
|
+
switch (packageManager) {
|
|
17
|
+
case 'yarn':
|
|
18
|
+
return 'yarn install --frozen-lockfile';
|
|
19
|
+
case 'pnpm':
|
|
20
|
+
return 'pnpm install --frozen-lockfile';
|
|
21
|
+
case 'bun':
|
|
22
|
+
return 'bun install --frozen-lockfile'
|
|
23
|
+
default:
|
|
24
|
+
return 'npm ci';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getInstallCommand(packageManager) {
|
|
16
29
|
switch (packageManager) {
|
|
17
30
|
case 'yarn':
|
|
18
31
|
return 'yarn install';
|
|
19
32
|
case 'pnpm':
|
|
20
33
|
return 'pnpm install';
|
|
34
|
+
case 'bun':
|
|
35
|
+
return 'bun install'
|
|
21
36
|
default:
|
|
22
37
|
return 'npm install';
|
|
23
38
|
}
|
|
24
39
|
}
|
|
25
40
|
|
|
26
|
-
|
|
27
|
-
const { testinNutin,
|
|
28
|
-
|
|
29
|
-
const baseDevDeps = {
|
|
30
|
-
"concurrently": "^9.1.2",
|
|
31
|
-
"live-server": "^1.2.2",
|
|
32
|
-
"sass": "^1.89.0",
|
|
33
|
-
"typescript": "^5.8.3"
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const devDependencies = testinNutin
|
|
37
|
-
? { ...baseDevDeps, "jsdom": "^26.1.0" }
|
|
38
|
-
: baseDevDeps;
|
|
41
|
+
function getScripts(answers) {
|
|
42
|
+
const { testinNutin, packageManager, projectName } = answers;
|
|
39
43
|
|
|
40
44
|
const baseScripts = {
|
|
41
|
-
"patch":
|
|
42
|
-
"minor":
|
|
43
|
-
"major":
|
|
44
|
-
"build
|
|
45
|
-
"build
|
|
46
|
-
"serve": "
|
|
47
|
-
"
|
|
48
|
-
|
|
45
|
+
"patch": `${packageManager} version patch -m 'CI/CD: Bump version to %s'`,
|
|
46
|
+
"minor": `${packageManager} version minor -m 'CI/CD: Bump version to %s'`,
|
|
47
|
+
"major": `${packageManager} version major -m 'CI/CD: Bump version to %s'`,
|
|
48
|
+
"build": "node tools/builder/builder.js",
|
|
49
|
+
"build:prod": "NODE_ENV=production node tools/builder/builder.js",
|
|
50
|
+
"serve:only": "node tools/dev/serve.js",
|
|
51
|
+
"serve": `${packageManager} run build && ${packageManager} run serve:only`,
|
|
52
|
+
"dev": "node tools/dev/dev-serve.js",
|
|
53
|
+
"generate": "node tools/generator/generator.js",
|
|
54
|
+
"docker:build": `docker build -t ${projectName} -f tools/deployment/Dockerfile .`,
|
|
55
|
+
"docker:run": `docker run -p 9090:9090 ${projectName}:latest`
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const testinNutinScripts = {
|
|
59
|
+
"test": "node testin-nutin/runner.js",
|
|
60
|
+
"test:rebuild": `${packageManager} run build && ${packageManager} run test`,
|
|
61
|
+
"test:watch": `${packageManager} run build && node testin-nutin/watch-tests.js`
|
|
62
|
+
}
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
return testinNutin
|
|
51
65
|
? {
|
|
52
66
|
...baseScripts,
|
|
53
|
-
|
|
54
|
-
"test--rebuild": "npm run build && npm run test",
|
|
55
|
-
"test:watch": "npm run build && node test/watch-tests.js",
|
|
56
|
-
"serve": "npm run build && npm run serve:only",
|
|
57
|
-
"serve:only": "live-server dist/src --port=9090 --entry-file=index.html --open",
|
|
58
|
-
"dev": "concurrently \"node tools/watcher.js\" \"npm run build && npm run serve:only > /dev/null 2>&1\""
|
|
67
|
+
...testinNutinScripts
|
|
59
68
|
}
|
|
60
69
|
: baseScripts;
|
|
70
|
+
}
|
|
61
71
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
export async function generatePackageJson(projectPath, answers) {
|
|
73
|
+
const { testinNutin, projectName, packageManager } = answers;
|
|
74
|
+
|
|
75
|
+
const devDependencies = {
|
|
76
|
+
"chokidar": "^4.0.3",
|
|
77
|
+
"esbuild": "^0.25.12",
|
|
78
|
+
"html-minifier-terser": "^7.2.0",
|
|
79
|
+
"live-server": "^1.2.2",
|
|
80
|
+
"sass": "^1.89.0",
|
|
81
|
+
"typescript": "^5.8.3",
|
|
82
|
+
...(testinNutin && {
|
|
83
|
+
"jsdom": "^26.1.0",
|
|
84
|
+
})
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const scripts = getScripts(answers);
|
|
74
88
|
|
|
75
89
|
const packageJson = {
|
|
76
90
|
"name": projectName,
|
|
77
91
|
"version": "0.1.0",
|
|
78
|
-
"main": "index.js",
|
|
79
92
|
"type": "module",
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
-
|
|
93
|
+
...(testinNutin && {
|
|
94
|
+
"imports": {
|
|
95
|
+
"#root/*.js": "./*.js"
|
|
96
|
+
}
|
|
97
|
+
}),
|
|
83
98
|
scripts,
|
|
84
|
-
devDependencies
|
|
99
|
+
devDependencies,
|
|
100
|
+
...(testinNutin && {
|
|
101
|
+
"engines": {
|
|
102
|
+
"node": ">=20.19.0"
|
|
103
|
+
}
|
|
104
|
+
})
|
|
85
105
|
};
|
|
86
106
|
|
|
87
107
|
await fs.writeJSON(path.join(projectPath, 'package.json'), packageJson, { spaces: 2 });
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
export async function generateTsconfigJson(projectPath, answers) {
|
|
91
|
-
const { template } = answers;
|
|
92
|
-
|
|
93
111
|
const tsconfig = {
|
|
94
112
|
"compilerOptions": {
|
|
95
113
|
"baseUrl": "./",
|
|
@@ -97,13 +115,16 @@ export async function generateTsconfigJson(projectPath, answers) {
|
|
|
97
115
|
"target": "ESNext",
|
|
98
116
|
"module": "NodeNext",
|
|
99
117
|
"moduleResolution": "NodeNext",
|
|
100
|
-
"rootDir": "
|
|
101
|
-
"outDir":
|
|
118
|
+
"rootDir": "src",
|
|
119
|
+
"outDir": "dist-build/src",
|
|
102
120
|
"strict": true,
|
|
121
|
+
"skipLibCheck": true,
|
|
122
|
+
"forceConsistentCasingInFileNames": true,
|
|
123
|
+
"noUncheckedIndexedAccess": true,
|
|
103
124
|
"esModuleInterop": true,
|
|
104
125
|
"allowSyntheticDefaultImports": true,
|
|
105
126
|
"lib": ["es2022", "DOM"],
|
|
106
|
-
"
|
|
127
|
+
"removeComments": true,
|
|
107
128
|
"resolveJsonModule": true,
|
|
108
129
|
"typeRoots": ["src/types", "node_modules/@types"]
|
|
109
130
|
},
|
package/lib/src/prompts.mjs
CHANGED
|
@@ -22,7 +22,7 @@ export async function promptUser(initialName, cliOptions = {}) {
|
|
|
22
22
|
type: 'list',
|
|
23
23
|
name: 'packageManager',
|
|
24
24
|
message: 'Package manager:',
|
|
25
|
-
choices: ['npm', 'yarn', 'pnpm'],
|
|
25
|
+
choices: ['npm', 'yarn', 'pnpm', 'bun'],
|
|
26
26
|
default: 'npm'
|
|
27
27
|
}
|
|
28
28
|
]);
|
|
@@ -34,10 +34,10 @@ export async function promptUser(initialName, cliOptions = {}) {
|
|
|
34
34
|
projectName,
|
|
35
35
|
packageManager,
|
|
36
36
|
stylinNutin: cliOptions.stylinNutin || true,
|
|
37
|
-
template: cliOptions.template ||
|
|
38
|
-
i18n: cliOptions.i18n ||
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
template: cliOptions.template || true,
|
|
38
|
+
i18n: cliOptions.i18n || true,
|
|
39
|
+
testinNutin: cliOptions.testinNutin || false,
|
|
40
|
+
transition: cliOptions.transitions || false
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -47,7 +47,7 @@ export async function promptUser(initialName, cliOptions = {}) {
|
|
|
47
47
|
questions.push({
|
|
48
48
|
type: 'confirm',
|
|
49
49
|
name: 'stylinNutin',
|
|
50
|
-
message: 'Use built-in SCSS utility classes?',
|
|
50
|
+
message: 'Use built-in SCSS utility classes ?',
|
|
51
51
|
default: true
|
|
52
52
|
});
|
|
53
53
|
}
|
|
@@ -56,8 +56,8 @@ export async function promptUser(initialName, cliOptions = {}) {
|
|
|
56
56
|
questions.push({
|
|
57
57
|
type: 'confirm',
|
|
58
58
|
name: 'template',
|
|
59
|
-
message: 'Use external templates?',
|
|
60
|
-
default:
|
|
59
|
+
message: 'Use external templates ?',
|
|
60
|
+
default: true
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -65,8 +65,8 @@ export async function promptUser(initialName, cliOptions = {}) {
|
|
|
65
65
|
questions.push({
|
|
66
66
|
type: 'confirm',
|
|
67
67
|
name: 'i18n',
|
|
68
|
-
message: 'Use i18n
|
|
69
|
-
default:
|
|
68
|
+
message: 'Use i18n with json-based content ?',
|
|
69
|
+
default: true
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
|
package/lib/src/utils.mjs
CHANGED
|
@@ -5,11 +5,14 @@ import { print } from './print.mjs';
|
|
|
5
5
|
export const promiseExec = promisify(exec);
|
|
6
6
|
|
|
7
7
|
export function displaySuccessMessage(answers) {
|
|
8
|
-
const { projectName
|
|
8
|
+
const { projectName } = answers;
|
|
9
9
|
|
|
10
10
|
print.boldSuccess('\n🎉 Your project is ready!');
|
|
11
11
|
print.info('\nNext steps:');
|
|
12
12
|
print.info(` cd ${projectName} && npm run serve`);
|
|
13
|
+
print.boldInfo(`\nDocumentation on https://www.nutin.org`);
|
|
13
14
|
|
|
14
15
|
print.success('\nHappy coding! 🚀\n');
|
|
15
16
|
}
|
|
17
|
+
|
|
18
|
+
export const packageVersion = '1.2.1';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nutin/cli",
|
|
3
|
-
"version": "1.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "Build SPAs by understanding SPAs. A minimal frontend toolkit crafted for learning and lean applications.",
|
|
5
5
|
"preferGlobal": true,
|
|
6
6
|
"main": "lib/index.mjs",
|
|
7
7
|
"bin": {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"nutin",
|
|
20
20
|
"Frontend",
|
|
21
21
|
"SPA",
|
|
22
|
+
"Learning",
|
|
22
23
|
"Minimalist",
|
|
23
24
|
"Lighweight",
|
|
24
25
|
"Customizable"
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"inquirer": "^9.0.0"
|
|
33
34
|
},
|
|
34
35
|
"engines": {
|
|
35
|
-
"node": ">=18
|
|
36
|
+
"node": ">=18"
|
|
36
37
|
},
|
|
37
38
|
"repository": {
|
|
38
39
|
"type": "git",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
node_modules
|
|
2
2
|
dist
|
|
3
|
+
dist-build
|
|
3
4
|
.github
|
|
4
5
|
.gitignore
|
|
5
6
|
.git
|
|
@@ -7,6 +8,15 @@ dist
|
|
|
7
8
|
*.md
|
|
8
9
|
.env
|
|
9
10
|
*.txt
|
|
10
|
-
{{#if
|
|
11
|
-
*.test
|
|
11
|
+
{{#if testinNutin}}
|
|
12
|
+
*.test.js
|
|
13
|
+
testin-nutin
|
|
12
14
|
{{/if}}
|
|
15
|
+
*.log
|
|
16
|
+
|
|
17
|
+
npm-debug.log
|
|
18
|
+
.nyc_output
|
|
19
|
+
coverage
|
|
20
|
+
.DS_Store
|
|
21
|
+
.cache
|
|
22
|
+
.parcel-cache
|
|
@@ -1 +1,24 @@
|
|
|
1
1
|
# {{projectName}} - Built with nutin
|
|
2
|
+
|
|
3
|
+
## Start
|
|
4
|
+
|
|
5
|
+
- `{{packageManager}} run serve` (rebuild), `{{packageManager}} run serve:only` (no rebuild), `{{packageManager}} run dev` (watch).
|
|
6
|
+
|
|
7
|
+
## Build
|
|
8
|
+
|
|
9
|
+
- `{{packageManager}} run build` (dev) or `{{packageManager}} run build:prod` (production)
|
|
10
|
+
|
|
11
|
+
Accepts `--bundle` (= build:prod) and `--log` (verbose output) flags
|
|
12
|
+
|
|
13
|
+
## Generate Component, View, Service
|
|
14
|
+
|
|
15
|
+
- `{{packageManager}} run generate ELEMENT ELEMENT_NAME`
|
|
16
|
+
|
|
17
|
+
Supports nested paths.
|
|
18
|
+
|
|
19
|
+
{{#if testinNutin}}
|
|
20
|
+
## Test
|
|
21
|
+
|
|
22
|
+
- `{{packageManager}} run test:rebuild`, `{{packageManager}} run test`, `{{packageManager}} run test:watch`.
|
|
23
|
+
|
|
24
|
+
{{/if}}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
esbuild: {
|
|
3
|
+
bundle: true,
|
|
4
|
+
minify: true,
|
|
5
|
+
sourcemap: false,
|
|
6
|
+
platform: 'browser',
|
|
7
|
+
format: 'esm',
|
|
8
|
+
target: ['es2015'],
|
|
9
|
+
legalComments: 'none',
|
|
10
|
+
loader: {
|
|
11
|
+
'.json': 'json',
|
|
12
|
+
},
|
|
13
|
+
define: {
|
|
14
|
+
'process.env.NODE_ENV': '"production"',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
sass: {
|
|
18
|
+
paths: [
|
|
19
|
+
'base',
|
|
20
|
+
'core',
|
|
21
|
+
{{#if stylinNutin}}
|
|
22
|
+
'components',
|
|
23
|
+
'views',
|
|
24
|
+
{{/if}}
|
|
25
|
+
], // in styles/
|
|
26
|
+
},
|
|
27
|
+
verbose: false,
|
|
28
|
+
}
|