diff --git a/package-lock.json b/package-lock.json index 6215e6d..1a31726 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@lenne.tech/cli", - "version": "0.0.108", + "version": "0.0.109", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@lenne.tech/cli", - "version": "0.0.108", + "version": "0.0.109", "license": "MIT", "dependencies": { "@lenne.tech/cli-plugin-helper": "0.0.11", diff --git a/package.json b/package.json index a55a7f9..88ab387 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lenne.tech/cli", - "version": "0.0.108", + "version": "0.0.109", "description": "lenne.Tech CLI: lt", "keywords": [ "lenne.Tech", diff --git a/src/commands/server/create.ts b/src/commands/server/create.ts index 5005f97..81b41b6 100644 --- a/src/commands/server/create.ts +++ b/src/commands/server/create.ts @@ -20,23 +20,24 @@ const NewCommand: GluegunCommand = { parameters, patching, print: { error, info, spin, success }, + prompt: { confirm }, server, strings: { kebabCase }, system, template, } = toolbox; - + // Start timer const timer = system.startTimer(); - + // Info info('Create a new server'); - + // Check git if (!(await git.gitInstalled())) { return; } - + // Get name const name = await helper.getInput(parameters.first, { name: 'server name', @@ -45,17 +46,17 @@ const NewCommand: GluegunCommand = { if (!name) { return; } - + // Set project directory const projectDir = kebabCase(name); - + // Check if directory already exists if (filesystem.exists(projectDir)) { info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } - + // Clone git repository const cloneSpinner = spin('Clone https://github.com/lenneTech/nest-server-starter.git'); await system.run(`git clone https://github.com/lenneTech/nest-server-starter.git ${projectDir}`); @@ -63,38 +64,38 @@ const NewCommand: GluegunCommand = { filesystem.remove(`./${projectDir}/.git`); cloneSpinner.succeed('Repository cloned from https://github.com/lenneTech/nest-server-starter.git'); } - + // Check directory if (!filesystem.isDirectory(`./${projectDir}`)) { error(`The directory "${projectDir}" could not be created.`); return undefined; } - + // Get description const description = await helper.getInput(parameters.second, { name: 'Description', showError: false, }); - + // Get author const author = await helper.getInput(parameters.second, { name: 'Author', showError: false, }); - + const prepareSpinner = spin('Prepare files'); - + // Set readme await template.generate({ props: { description, name }, target: `./${projectDir}/README.md`, template: 'nest-server-starter/README.md.ejs', }); - + // Replace secret or private keys and remove `nest-server` await patching.update(`./${projectDir}/src/config.env.ts`, content => server.replaceSecretOrPrivateKeys(content).replace(/nest-server-/g, `${projectDir }-`)); - + // Set package.json await patching.update(`./${projectDir}/package.json`, (config) => { config.author = author; @@ -111,7 +112,7 @@ const NewCommand: GluegunCommand = { config.version = '0.0.1'; return config; }); - + // Set package.json if (filesystem.exists(`./${projectDir}/src/meta`)) { await patching.update(`./${projectDir}/src/meta`, (config) => { @@ -120,21 +121,27 @@ const NewCommand: GluegunCommand = { return config; }); } - + prepareSpinner.succeed('Files prepared'); - + // Init const installSpinner = spin('Install npm packages'); await system.run(`cd ${projectDir} && npm i`); installSpinner.succeed('NPM packages installed'); if (git) { - const initGitSpinner = spin('Initialize git'); - await system.run( - `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"`, - ); - initGitSpinner.succeed('Git initialized'); + const inGit = (await system.run('git rev-parse --is-inside-work-tree'))?.trim(); + if (inGit !== 'true') { + const initializeGit = await confirm('Initialize git?', true); + if (initializeGit) { + const initGitSpinner = spin('Initialize git'); + await system.run( + `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"`, + ); + initGitSpinner.succeed('Git initialized'); + } + } } - + // We're done, so show what to do next info(''); success( @@ -148,11 +155,11 @@ const NewCommand: GluegunCommand = { info(' Run tests: npm run test:e2e'); info(' Start server: npm start'); info(''); - + if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); } - + // For tests return `new server ${name}`; }, diff --git a/src/commands/server/set-secrets.ts b/src/commands/server/set-secrets.ts new file mode 100644 index 0000000..d79b305 --- /dev/null +++ b/src/commands/server/set-secrets.ts @@ -0,0 +1,41 @@ +import { GluegunCommand } from 'gluegun'; + +import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; + +/** + * Set secrets for the server configuration + */ +const NewCommand: GluegunCommand = { + alias: ['scs'], + description: 'Set secrets for the server configuration', + hidden: false, + name: 'setConfigSecrets', + run: async (toolbox: ExtendedGluegunToolbox) => { + // Retrieve the tools we need + const { + filesystem, + parameters, + patching, + print: { error, info, spin }, + server, + } = toolbox; + + // Check if file exists + const filePath = parameters.first || 'src/config.env.ts'; + if (!filesystem.exists(filePath)) { + info(''); + error(`There's no file named "${filePath}"`); + return undefined; + } + + // Set secrets + const prepareSpinner = spin(`Setting secrets in server configuration: ${filePath}`); + await patching.update(filePath, content => server.replaceSecretOrPrivateKeys(content)); + prepareSpinner.succeed(`Secrets set in server configuration ${filePath}`); + + // For tests + return 'secrets in server configuration set'; + }, +}; + +export default NewCommand; diff --git a/src/templates/nest-server-starter/README.md.ejs b/src/templates/nest-server-starter/README.md.ejs index 1194f36..4a4c949 100755 --- a/src/templates/nest-server-starter/README.md.ejs +++ b/src/templates/nest-server-starter/README.md.ejs @@ -1,6 +1,11 @@ # <%= props.name %> + +The <%= props.name %> is a backend server based on the [NestJS](https://nestjs.com/) framework. + <%= props.description %> +The server was initialized with the [Starter for lenne.Tech Nest Server](https://github.com/lenneTech/nest-server-starter). + ## Requirements - [Node.js incl. npm](https://nodejs.org): @@ -12,8 +17,9 @@ the database for your objects ## Start the server -`$ npm run start:dev` - +``` +$ npm run start:dev +``` ## Extend the server @@ -22,6 +28,12 @@ This server is based on [lenne.Tech Nest Server](https://github.com/lenneTech/ne Since the lenne.Tech Nest Server is based on [Nest](https://nestjs.com/), you can find all information about extending the **<%= props.name %>** in the [documentation of Nest](https://docs.nestjs.com/). +To create a new Module with model, inputs, resolver and service you can use the [CLI](https://github.com/lenneTech/cli): + +``` +$ lt server module MODULE_NAME +``` + The documentation of the extensions and auxiliary classes that the [lenne.Tech Nest Server](https://github.com/lenneTech/nest-server) contains is currently under construction. As long as this is not yet available,have a look at the @@ -37,7 +49,6 @@ There you will find a lot of things that will help you to extend your server, su [helpers for tests](https://github.com/lenneTech/nest-server/blob/master/src/test/test.helper.ts) - ... - ## Further information ### Running the app @@ -59,3 +70,78 @@ $ npm run start:prod # e2e tests $ npm run test:e2e ``` + +Configuration for testing: +``` +Node interpreter: /user/local/bin/node +Jest package: FULL_PATH_TO_PROJECT_DIR/node_modules/jest +Working directory: FULL_PATH_TO_PROJECT_DIR +Jest options: --config jest-e2e.json --forceExit +``` +see [E2E-Tests.run.xml](.run/E2E-Tests.run.xml) + +## Debugging + +Configuration for debugging is: +``` +Node interpreter: /user/local/bin/node +Node parameters: node_modules/@nestjs/cli/bin/nest.js start --debug --watch +Working directory: FULL_PATH_TO_PROJECT_DIR +JavaScript file: src/main.ts +``` +see [Debug.run.xml](.run/Debug.run.xml) + + +## Test & debug the NestServer package in this project +Use [yalc](https://github.com/wclr/yalc) to include the NestJS server in the project. + +1. clone [NestServer](https://github.com/lenneTech/nest-server): `git clone https://github.com/lenneTech/nest-server.git` +2. go to the nest-server folder (`cd nest-server`), install the packages via `npm i` and start the nest server in watch & yalc mode: `npm run watch` +3. link the nest server live package to this project via `npm run link:nest-server` and start the server: `npm start` +4. unlink the nest-server live package and use the normal package again when you are done: `npm run unlink:nest-server` + +## Deployment with deploy.party + +This project is prepared for deployment with deploy.party. + +Example configuration for deploy.party (productive): + +| Key | Value | +|----------------------|----------------------------------------------------| +| Source | GitLab | +| Repository | my-repo | +| Branch | main | +| Registry | localhost | +| Name | api | +| URL | api.my-domain.com | +| Type | Node | +| Base image | node:20 | +| Custom image command | RUN apt-get install -y tzdata curl | +| | ENV TZ Europe/Berlin | +| Base directory | ./projects/api | +| Install command | npm install | +| Build command | npm run build | +| Start command | npm run dp:prod | +| Healthcheck command | curl --fail http://localhost:3000/meta \|\| exit 1 | +| Port | 3000 | +| Enable SSL | true | + +## Documentation +The API and developer documentation can automatically be generated. + +```bash +# generate and serve documentation +$ npm run docs +``` + +## Update +An update to a new Nest Sever version can be done as follows: + +1. set the new Nest Server version in the package.json under `{dependencies: {"@lenne.tech/nest-server": "NEW_VERSION" }}`. +2. run `npm run update` +3. adjust project according to changes in git history from nest server +4. run tests via `npm run tests:e2e`, build via `npm run build` and start the server with `npm start` to check if everything is working + +Simply compare the current version in the Git history of +[Starter for lenne.Tech Nest Server](https://github.com/lenneTech/nest-server-starter) with the version that was +previously used in the project and adapt your own project accordingly.