create-forgeon 0.1.24 → 0.1.26

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 (41) hide show
  1. package/package.json +1 -1
  2. package/src/core/docs.test.mjs +8 -6
  3. package/src/modules/executor.test.mjs +8 -0
  4. package/src/modules/i18n.mjs +19 -1
  5. package/src/presets/i18n.mjs +76 -34
  6. package/templates/base/apps/api/Dockerfile +7 -4
  7. package/templates/base/apps/api/package.json +3 -2
  8. package/templates/base/apps/api/src/app.module.ts +4 -4
  9. package/templates/base/apps/api/src/health/health.controller.ts +41 -8
  10. package/templates/base/apps/api/src/main.ts +6 -8
  11. package/templates/base/apps/web/src/App.tsx +76 -35
  12. package/templates/base/apps/web/src/styles.css +29 -17
  13. package/templates/base/docs/AI/ARCHITECTURE.md +48 -32
  14. package/templates/base/docs/AI/MODULE_CHECKS.md +25 -0
  15. package/templates/base/docs/AI/MODULE_SPEC.md +1 -0
  16. package/templates/base/docs/AI/PROJECT.md +27 -16
  17. package/templates/base/docs/AI/TASKS.md +8 -7
  18. package/templates/base/docs/AI/VALIDATION.md +6 -1
  19. package/templates/base/docs/README.md +1 -0
  20. package/templates/base/packages/core/README.md +1 -0
  21. package/templates/base/packages/core/src/errors/core-exception.filter.ts +11 -3
  22. package/templates/base/packages/core/src/index.ts +1 -0
  23. package/templates/base/packages/core/src/validation/core-validation.pipe.ts +56 -0
  24. package/templates/base/packages/core/src/validation/index.ts +1 -0
  25. package/templates/base/packages/db-prisma/README.md +9 -0
  26. package/templates/base/packages/db-prisma/package.json +20 -0
  27. package/templates/base/packages/db-prisma/src/db-prisma-config.loader.ts +18 -0
  28. package/templates/base/packages/db-prisma/src/db-prisma-config.service.ts +12 -0
  29. package/templates/base/packages/db-prisma/src/db-prisma-env.schema.ts +17 -0
  30. package/templates/base/packages/db-prisma/src/db-prisma.module.ts +13 -0
  31. package/templates/base/packages/db-prisma/src/index.ts +5 -0
  32. package/templates/base/{apps/api/src/prisma → packages/db-prisma/src}/prisma.service.ts +24 -27
  33. package/templates/base/packages/db-prisma/tsconfig.json +9 -0
  34. package/templates/base/resources/i18n/en/common.json +3 -0
  35. package/templates/base/resources/i18n/uk/common.json +3 -0
  36. package/templates/docs-fragments/AI_ARCHITECTURE/20_env_base.md +1 -1
  37. package/templates/docs-fragments/AI_ARCHITECTURE/30_default_db.md +9 -7
  38. package/templates/docs-fragments/AI_ARCHITECTURE/32_scope_freeze.md +6 -5
  39. package/templates/docs-fragments/AI_PROJECT/20_structure_base.md +2 -1
  40. package/templates/module-presets/i18n/apps/web/src/App.tsx +63 -22
  41. package/templates/base/apps/api/src/prisma/prisma.module.ts +0 -9
@@ -5,10 +5,9 @@ import * as i18nWeb from '@forgeon/i18n-web';
5
5
  import type { I18nLocale } from '@forgeon/i18n-web';
6
6
  import './styles.css';
7
7
 
8
- type HealthResponse = {
9
- status: string;
10
- message: string;
11
- i18n: string;
8
+ type ProbeResult = {
9
+ statusCode: number;
10
+ body: unknown;
12
11
  };
13
12
 
14
13
  function localeLabelKey(locale: I18nLocale): string {
@@ -19,8 +18,11 @@ export default function App() {
19
18
  const { t } = useTranslation(['common']);
20
19
  const { I18N_LOCALES, getInitialLocale, persistLocale, toLangQuery } = i18nWeb;
21
20
  const [locale, setLocale] = useState<I18nLocale>(getInitialLocale);
22
- const [data, setData] = useState<HealthResponse | null>(null);
23
- const [error, setError] = useState<string | null>(null);
21
+ const [healthResult, setHealthResult] = useState<ProbeResult | null>(null);
22
+ const [errorProbeResult, setErrorProbeResult] = useState<ProbeResult | null>(null);
23
+ const [validationProbeResult, setValidationProbeResult] = useState<ProbeResult | null>(null);
24
+ const [dbProbeResult, setDbProbeResult] = useState<ProbeResult | null>(null);
25
+ const [networkError, setNetworkError] = useState<string | null>(null);
24
26
 
25
27
  const changeLocale = (nextLocale: I18nLocale) => {
26
28
  setLocale(nextLocale);
@@ -28,24 +30,49 @@ export default function App() {
28
30
  void i18n.changeLanguage(nextLocale);
29
31
  };
30
32
 
31
- const checkApi = async () => {
32
- setError(null);
33
+ const requestProbe = async (path: string, init?: RequestInit): Promise<ProbeResult> => {
34
+ const response = await fetch(`/api${path}${toLangQuery(locale)}`, {
35
+ ...init,
36
+ headers: {
37
+ ...(init?.headers ?? {}),
38
+ 'Accept-Language': locale,
39
+ },
40
+ });
41
+
42
+ let body: unknown = null;
43
+ try {
44
+ body = await response.json();
45
+ } catch {
46
+ body = { message: 'Non-JSON response' };
47
+ }
48
+
49
+ return {
50
+ statusCode: response.status,
51
+ body,
52
+ };
53
+ };
54
+
55
+ const runProbe = async (
56
+ setter: (value: ProbeResult | null) => void,
57
+ path: string,
58
+ init?: RequestInit,
59
+ ) => {
60
+ setNetworkError(null);
33
61
  try {
34
- const response = await fetch(`/api/health${toLangQuery(locale)}`, {
35
- headers: {
36
- 'Accept-Language': locale,
37
- },
38
- });
39
- if (!response.ok) {
40
- throw new Error(`HTTP ${response.status}`);
41
- }
42
- const payload = (await response.json()) as HealthResponse;
43
- setData(payload);
62
+ const result = await requestProbe(path, init);
63
+ setter(result);
44
64
  } catch (err) {
45
- setError(err instanceof Error ? err.message : 'Unknown error');
65
+ setNetworkError(err instanceof Error ? err.message : 'Unknown error');
46
66
  }
47
67
  };
48
68
 
69
+ const renderResult = (title: string, result: ProbeResult | null) => (
70
+ <section>
71
+ <h3>{title}</h3>
72
+ {result ? <pre>{JSON.stringify(result, null, 2)}</pre> : null}
73
+ </section>
74
+ );
75
+
49
76
  return (
50
77
  <main className="page">
51
78
  <h1>Forgeon Fullstack Scaffold</h1>
@@ -62,9 +89,23 @@ export default function App() {
62
89
  </option>
63
90
  ))}
64
91
  </select>
65
- <button onClick={checkApi}>{t('common:checkApiHealth')}</button>
66
- {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : null}
67
- {error ? <p className="error">{error}</p> : null}
92
+ <div className="actions">
93
+ <button onClick={() => runProbe(setHealthResult, '/health')}>{t('common:checkApiHealth')}</button>
94
+ <button onClick={() => runProbe(setErrorProbeResult, '/health/error')}>
95
+ {t('common:checkErrorEnvelope')}
96
+ </button>
97
+ <button onClick={() => runProbe(setValidationProbeResult, '/health/validation')}>
98
+ {t('common:checkValidation')}
99
+ </button>
100
+ <button onClick={() => runProbe(setDbProbeResult, '/health/db', { method: 'POST' })}>
101
+ {t('common:checkDatabase')}
102
+ </button>
103
+ </div>
104
+ {renderResult('Health response', healthResult)}
105
+ {renderResult('Error probe response', errorProbeResult)}
106
+ {renderResult('Validation probe response', validationProbeResult)}
107
+ {renderResult('DB probe response', dbProbeResult)}
108
+ {networkError ? <p className="error">{networkError}</p> : null}
68
109
  </main>
69
110
  );
70
111
  }
@@ -1,9 +0,0 @@
1
- import { Global, Module } from '@nestjs/common';
2
- import { PrismaService } from './prisma.service';
3
-
4
- @Global()
5
- @Module({
6
- providers: [PrismaService],
7
- exports: [PrismaService],
8
- })
9
- export class PrismaModule {}