@koalarx/nest 4.0.3 → 4.0.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.
@@ -26,6 +26,7 @@ import {
26
26
  resolveProjectFeatures
27
27
  } from "../../utils/install-module.js";
28
28
  import { fixLintConfig } from "./fix-lint-config.js";
29
+ import { finalizeNewProjectSetup } from "../../utils/install-workspace-config.js";
29
30
  async function promptAuthStrategies(template) {
30
31
  const isCrud = template === Template.CRUD_SAMPLE;
31
32
  return assertNotCancel(await p.multiselect({
@@ -180,6 +181,8 @@ export async function runNew(args = []) {
180
181
  auth: authStrategies,
181
182
  features
182
183
  });
184
+ spinner.message("Configurando workspace (.vscode e .env)...");
185
+ finalizeNewProjectSetup(project.name, project.packageManager);
183
186
  spinner.stop("Projeto criado com sucesso!");
184
187
  const projectFeatures = resolveProjectFeatures(features, authStrategies);
185
188
  const extrasSummary = [
@@ -196,7 +199,8 @@ export async function runNew(args = []) {
196
199
  `${color.bold("Gerenciador:")} ${project.packageManager}`,
197
200
  `${color.bold("Autenticação:")} ${formatAuthStrategies(authStrategies)}`,
198
201
  `${color.bold("Extras:")} ${extrasSummary || color.dim("nenhum")}`,
199
- `${color.dim("Depois:")} cd ${project.name} && kl-nest add <feature>`
202
+ `${color.dim("Depois:")} cd ${project.name} && ${project.packageManager} start`,
203
+ `${color.dim("Extras:")} kl-nest add <feature>`
200
204
  ].join(`
201
205
  `), "Resumo");
202
206
  }
@@ -5,6 +5,13 @@ import {
5
5
  resolveNewProjectOptions
6
6
  } from "./domain.js";
7
7
  import { resolveProjectFeatures } from "../utils/install-module.js";
8
+ export const WORKSPACE_SETUP_PATHS = [
9
+ ".vscode/launch.json",
10
+ ".vscode/settings.json",
11
+ ".vscode/tasks.json",
12
+ ".vscode/extensions.json",
13
+ ".env"
14
+ ];
8
15
  export const CORE_REQUIRED_PATHS = [
9
16
  "src/core/env.ts",
10
17
  "src/host/main.ts",
@@ -165,7 +172,7 @@ export function buildProjectExpectation(template, auth, features) {
165
172
  };
166
173
  }
167
174
  export function requiredPathsForExpectation(expectation) {
168
- const paths = [...CORE_REQUIRED_PATHS];
175
+ const paths = [...CORE_REQUIRED_PATHS, ...WORKSPACE_SETUP_PATHS];
169
176
  if (expectation.template === Template.CRUD_SAMPLE) {
170
177
  paths.push(...CRUD_TEMPLATE_REQUIRED_PATHS);
171
178
  }
@@ -0,0 +1,79 @@
1
+ import { cpSync, existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { getSourceCodePath } from "./get-source-code-path.js";
4
+ import { resolveProjectPath } from "./resolve-project-path.js";
5
+ const PACKAGE_MANAGER_COMMAND = {
6
+ bun: "bun",
7
+ npm: "npm",
8
+ pnpm: "pnpm"
9
+ };
10
+ export function projectNameToSnakeCase(projectName) {
11
+ const baseName = path.isAbsolute(projectName) ? path.basename(projectName) : projectName;
12
+ return baseName.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").replace(/__+/g, "_").toLowerCase().replace(/^_+|_+$/g, "");
13
+ }
14
+ function patchDatabaseUrl(content, databaseName) {
15
+ if (!/^DATABASE_URL=/m.test(content)) {
16
+ return content;
17
+ }
18
+ return content.replace(/^(DATABASE_URL=.+\/)([^/\r\n]+)(\s*)$/m, `$1${databaseName}$3`);
19
+ }
20
+ function patchJsonFile(filePath, patch) {
21
+ const content = readFileSync(filePath, "utf8");
22
+ const json = JSON.parse(content);
23
+ patch(json);
24
+ writeFileSync(filePath, `${JSON.stringify(json, null, 2)}
25
+ `);
26
+ }
27
+ function runScriptCommand(packageManager, script) {
28
+ return `${PACKAGE_MANAGER_COMMAND[packageManager]} run ${script}`;
29
+ }
30
+ export function installWorkspaceConfig(projectName, packageManager) {
31
+ const projectRoot = resolveProjectPath(projectName);
32
+ const sourceVscode = path.join(getSourceCodePath(), ".vscode");
33
+ const targetVscode = path.join(projectRoot, ".vscode");
34
+ cpSync(sourceVscode, targetVscode, { recursive: true });
35
+ const pmCommand = PACKAGE_MANAGER_COMMAND[packageManager];
36
+ patchJsonFile(path.join(targetVscode, "launch.json"), (launch) => {
37
+ const config = launch.configurations[0];
38
+ config.runtimeExecutable = pmCommand;
39
+ config.runtimeArgs = ["run", "start:debug"];
40
+ config.cwd = "${workspaceFolder}";
41
+ });
42
+ patchJsonFile(path.join(targetVscode, "tasks.json"), (tasks) => {
43
+ for (const task of tasks.tasks) {
44
+ if (task.command.includes("start:dev")) {
45
+ task.command = runScriptCommand(packageManager, "start:dev");
46
+ } else if (task.command.includes("test")) {
47
+ task.command = runScriptCommand(packageManager, "test");
48
+ } else if (task.command.includes("migration:run")) {
49
+ task.command = runScriptCommand(packageManager, "migration:run");
50
+ }
51
+ task.options = { cwd: "${workspaceFolder}" };
52
+ }
53
+ });
54
+ patchJsonFile(path.join(targetVscode, "settings.json"), (settings) => {
55
+ settings["npm.packageManager"] = packageManager;
56
+ });
57
+ const gitignoreSource = path.join(getSourceCodePath(), ".gitignore");
58
+ if (existsSync(gitignoreSource)) {
59
+ cpSync(gitignoreSource, path.join(projectRoot, ".gitignore"), {
60
+ force: true
61
+ });
62
+ }
63
+ }
64
+ export function createEnvFromExample(projectName) {
65
+ const projectRoot = resolveProjectPath(projectName);
66
+ const examplePath = path.join(projectRoot, ".env.example");
67
+ const envPath = path.join(projectRoot, ".env");
68
+ if (!existsSync(examplePath)) {
69
+ return;
70
+ }
71
+ const databaseName = projectNameToSnakeCase(projectName);
72
+ const envContent = patchDatabaseUrl(readFileSync(examplePath, "utf8"), databaseName);
73
+ writeFileSync(examplePath, envContent);
74
+ writeFileSync(envPath, envContent);
75
+ }
76
+ export function finalizeNewProjectSetup(projectName, packageManager) {
77
+ installWorkspaceConfig(projectName, packageManager);
78
+ createEnvFromExample(projectName);
79
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "recommendations": [
3
+ "esbenp.prettier-vscode",
4
+ "dbaeumer.vscode-eslint",
5
+ "PKief.material-icon-theme"
6
+ ]
7
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "type": "node",
6
+ "request": "launch",
7
+ "name": "NestJS Debug",
8
+ "runtimeExecutable": "bun",
9
+ "runtimeArgs": ["run", "start:debug"],
10
+ "cwd": "${workspaceFolder}",
11
+ "autoAttachChildProcesses": true,
12
+ "restart": true,
13
+ "console": "integratedTerminal"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "material-icon-theme.activeIconPack": "nest",
3
+ "editor.fontFamily": "Fira Code",
4
+ "editor.fontSize": 15,
5
+ "editor.fontLigatures": true,
6
+ "workbench.startupEditor": "newUntitledFile",
7
+ "js/ts.suggest.autoImports": true,
8
+ "js/ts.updateImportsOnFileMove.enabled": "always",
9
+ "editor.rulers": [80, 120],
10
+ "extensions.ignoreRecommendations": true,
11
+ "files.associations": {
12
+ ".env.*": "dotenv",
13
+ ".prettierrc": "json"
14
+ },
15
+ "editor.parameterHints.enabled": false,
16
+ "editor.renderLineHighlight": "gutter",
17
+ "editor.lineHeight": 26,
18
+ "editor.suggestSelection": "first",
19
+ "explorer.confirmDelete": false,
20
+ "workbench.editor.labelFormat": "short",
21
+ "editor.acceptSuggestionOnCommitCharacter": false,
22
+ "explorer.compactFolders": false,
23
+ "git.enableSmartCommit": true,
24
+ "explorer.confirmDragAndDrop": false,
25
+ "terminal.integrated.fontSize": 14,
26
+ "breadcrumbs.enabled": true,
27
+ "editor.tabSize": 2,
28
+ "workbench.iconTheme": "material-icon-theme",
29
+ "material-icon-theme.languages.associations": {
30
+ "dotenv": "tune"
31
+ },
32
+ "material-icon-theme.files.associations": {
33
+ "*.e2e-spec.ts": "test-js",
34
+ "*.dto.ts": "diff",
35
+ "*.handler.ts": "esbuild",
36
+ "*.request.ts": "log",
37
+ "*.schema.ts": "scheme",
38
+ "*.response.ts": "conduct",
39
+ "*.validator.ts": "commitlint"
40
+ },
41
+ "material-icon-theme.folders.associations": {
42
+ "entities": "class",
43
+ "migrations": "tools",
44
+ "schemas": "class",
45
+ "domain": "class",
46
+ "infra": "app",
47
+ "dtos": "typescript",
48
+ "repositories": "mappings"
49
+ },
50
+ "[javascript]": {
51
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
52
+ "editor.formatOnSave": true,
53
+ "editor.codeActionsOnSave": {
54
+ "source.fixAll.eslint": "explicit"
55
+ }
56
+ },
57
+ "[typescript]": {
58
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
59
+ "editor.formatOnSave": true,
60
+ "editor.codeActionsOnSave": {
61
+ "source.fixAll.eslint": "explicit"
62
+ }
63
+ },
64
+ "prettier.documentSelectors": ["**/*.ts", "**/*.tsx", "**/*.js"],
65
+ "npm.scriptExplorerAction": "run",
66
+ "npm.packageManager": "bun",
67
+ "editor.wordWrap": "on",
68
+ "editor.wrappingIndent": "indent",
69
+ "eslint.workingDirectories": [{ "mode": "auto" }],
70
+ "eslint.validate": [
71
+ "javascript",
72
+ "javascriptreact",
73
+ "typescript",
74
+ "typescriptreact"
75
+ ],
76
+ "files.eol": "\n"
77
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "type": "shell",
6
+ "command": "bun run start:dev",
7
+ "options": {
8
+ "cwd": "${workspaceFolder}"
9
+ },
10
+ "group": {
11
+ "kind": "build",
12
+ "isDefault": true
13
+ },
14
+ "isBackground": true,
15
+ "problemMatcher": [],
16
+ "label": "Start API (dev)",
17
+ "detail": "nest start --watch"
18
+ },
19
+ {
20
+ "type": "shell",
21
+ "command": "bun run test",
22
+ "options": {
23
+ "cwd": "${workspaceFolder}"
24
+ },
25
+ "group": "test",
26
+ "label": "Run tests"
27
+ },
28
+ {
29
+ "type": "shell",
30
+ "command": "bun run migration:run",
31
+ "options": {
32
+ "cwd": "${workspaceFolder}"
33
+ },
34
+ "label": "Run migrations"
35
+ }
36
+ ]
37
+ }
@@ -1,17 +1,34 @@
1
1
  import { DATA_SOURCE_PROVIDER_TOKEN } from '@/infra/database/data-source-factory';
2
2
  import { Inject, Injectable } from '@nestjs/common';
3
- import { TypeOrmHealthIndicator } from '@nestjs/terminus';
3
+ import {
4
+ HealthIndicatorResult,
5
+ HealthIndicatorService,
6
+ } from '@nestjs/terminus';
4
7
  import { DataSource } from 'typeorm';
5
8
 
6
9
  @Injectable()
7
10
  export class DatabaseIndicator {
8
11
  constructor(
9
- private readonly typeOrm: TypeOrmHealthIndicator,
12
+ private readonly healthIndicatorService: HealthIndicatorService,
10
13
  @Inject(DATA_SOURCE_PROVIDER_TOKEN)
11
14
  private readonly dataSource: DataSource,
12
15
  ) {}
13
16
 
14
- isHealthy() {
15
- return this.typeOrm.pingCheck('db', { connection: this.dataSource });
17
+ async isHealthy(): Promise<HealthIndicatorResult> {
18
+ const indicator = this.healthIndicatorService.check('db');
19
+
20
+ try {
21
+ if (!this.dataSource.isInitialized) {
22
+ return indicator.down({ message: 'DataSource not initialized' });
23
+ }
24
+
25
+ await this.dataSource.query('SELECT 1');
26
+
27
+ return indicator.up();
28
+ } catch (error) {
29
+ const message = error instanceof Error ? error.message : String(error);
30
+
31
+ return indicator.down({ message });
32
+ }
16
33
  }
17
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koalarx/nest",
3
- "version": "4.0.3",
3
+ "version": "4.0.5",
4
4
  "description": "CLI para criar APIs NestJS com arquitetura DDD — copia módulos prontos para o seu repositório.",
5
5
  "license": "MIT",
6
6
  "type": "module",