create-forgeon 0.1.2 → 0.1.6
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/README.md +19 -17
- package/bin/create-forgeon.mjs +22 -22
- package/package.json +1 -1
- package/src/cli/add-help.mjs +12 -12
- package/src/cli/add-options.mjs +54 -54
- package/src/cli/add-options.test.mjs +24 -24
- package/src/cli/help.mjs +20 -20
- package/src/cli/options.mjs +121 -121
- package/src/cli/options.test.mjs +41 -41
- package/src/cli/prompt-select.mjs +94 -94
- package/src/cli/prompt-select.test.mjs +148 -148
- package/src/constants.mjs +13 -13
- package/src/core/docs.mjs +128 -128
- package/src/core/docs.test.mjs +91 -91
- package/src/core/install.mjs +14 -14
- package/src/core/scaffold.mjs +48 -45
- package/src/core/validate.mjs +12 -12
- package/src/core/validate.test.mjs +73 -73
- package/src/databases/index.mjs +26 -26
- package/src/frameworks/index.mjs +32 -32
- package/src/infrastructure/proxy.mjs +12 -12
- package/src/modules/docs.mjs +70 -70
- package/src/modules/executor.mjs +39 -21
- package/src/modules/executor.test.mjs +95 -45
- package/src/modules/i18n.mjs +283 -0
- package/src/modules/registry.mjs +43 -35
- package/src/presets/i18n.mjs +228 -180
- package/src/presets/index.mjs +2 -2
- package/src/presets/proxy.mjs +32 -32
- package/src/run-add-module.mjs +47 -47
- package/src/run-create-forgeon.mjs +72 -72
- package/src/utils/fs.mjs +26 -26
- package/src/utils/values.mjs +20 -20
- package/templates/base/.dockerignore +7 -7
- package/templates/base/.editorconfig +11 -11
- package/templates/base/README.md +46 -46
- package/templates/base/apps/api/Dockerfile +24 -24
- package/templates/base/apps/api/package.json +39 -39
- package/templates/base/apps/api/prisma/migrations/0001_init/migration.sql +11 -11
- package/templates/base/apps/api/prisma/schema.prisma +14 -14
- package/templates/base/apps/api/prisma/seed.ts +19 -19
- package/templates/base/apps/api/src/app.module.ts +32 -32
- package/templates/base/apps/api/src/common/dto/echo-query.dto.ts +5 -5
- package/templates/base/apps/api/src/common/filters/app-exception.filter.ts +129 -129
- package/templates/base/apps/api/src/config/app.config.ts +12 -12
- package/templates/base/apps/api/src/health/health.controller.ts +30 -30
- package/templates/base/apps/api/src/main.ts +25 -25
- package/templates/base/apps/api/src/prisma/prisma.module.ts +8 -8
- package/templates/base/apps/api/src/prisma/prisma.service.ts +26 -26
- package/templates/base/apps/api/tsconfig.build.json +8 -8
- package/templates/base/apps/api/tsconfig.json +8 -8
- package/templates/base/apps/web/Dockerfile +12 -12
- package/templates/base/apps/web/index.html +11 -11
- package/templates/base/apps/web/package.json +21 -21
- package/templates/base/apps/web/src/App.tsx +35 -35
- package/templates/base/apps/web/src/main.tsx +8 -8
- package/templates/base/apps/web/src/styles.css +32 -32
- package/templates/base/apps/web/tsconfig.json +17 -17
- package/templates/base/apps/web/vite.config.ts +14 -14
- package/templates/base/docs/AI/ARCHITECTURE.md +37 -37
- package/templates/base/docs/AI/MODULE_SPEC.md +56 -56
- package/templates/base/docs/AI/PROJECT.md +31 -31
- package/templates/base/docs/AI/TASKS.md +57 -57
- package/templates/base/docs/README.md +6 -6
- package/templates/base/infra/caddy/Caddyfile +15 -15
- package/templates/base/infra/docker/.env.example +9 -9
- package/templates/base/infra/docker/caddy.Dockerfile +15 -15
- package/templates/base/infra/docker/compose.caddy.yml +44 -44
- package/templates/base/infra/docker/compose.nginx.yml +44 -44
- package/templates/base/infra/docker/compose.none.yml +37 -37
- package/templates/base/infra/docker/compose.yml +44 -44
- package/templates/base/infra/docker/nginx.Dockerfile +15 -15
- package/templates/base/infra/nginx/nginx.conf +31 -31
- package/templates/base/package.json +23 -23
- package/templates/base/packages/core/README.md +2 -2
- package/templates/base/packages/core/package.json +13 -13
- package/templates/base/packages/core/tsconfig.json +7 -7
- package/templates/base/packages/i18n/package.json +18 -18
- package/templates/base/packages/i18n/src/forgeon-i18n.module.ts +45 -45
- package/templates/base/packages/i18n/tsconfig.json +8 -8
- package/templates/base/pnpm-workspace.yaml +2 -2
- package/templates/base/resources/i18n/en/common.json +4 -4
- package/templates/base/resources/i18n/en/validation.json +2 -2
- package/templates/base/resources/i18n/uk/common.json +4 -4
- package/templates/base/resources/i18n/uk/validation.json +2 -2
- package/templates/base/tsconfig.base.json +16 -16
- package/templates/docs-fragments/AI_ARCHITECTURE/00_title.md +1 -1
- package/templates/docs-fragments/AI_ARCHITECTURE/10_layout_base.md +6 -6
- package/templates/docs-fragments/AI_ARCHITECTURE/11_layout_infra.md +1 -1
- package/templates/docs-fragments/AI_ARCHITECTURE/12_layout_i18n_resources.md +1 -1
- package/templates/docs-fragments/AI_ARCHITECTURE/20_env_base.md +4 -4
- package/templates/docs-fragments/AI_ARCHITECTURE/21_env_i18n.md +3 -3
- package/templates/docs-fragments/AI_ARCHITECTURE/30_default_db.md +7 -7
- package/templates/docs-fragments/AI_ARCHITECTURE/31_docker_runtime.md +5 -5
- package/templates/docs-fragments/AI_ARCHITECTURE/32_scope_freeze.md +5 -5
- package/templates/docs-fragments/AI_ARCHITECTURE/40_docs_generation.md +9 -9
- package/templates/docs-fragments/AI_ARCHITECTURE/50_extension_points.md +8 -8
- package/templates/docs-fragments/AI_PROJECT/00_title.md +1 -1
- package/templates/docs-fragments/AI_PROJECT/10_what_is.md +3 -3
- package/templates/docs-fragments/AI_PROJECT/20_structure_base.md +5 -5
- package/templates/docs-fragments/AI_PROJECT/21_structure_i18n.md +2 -0
- package/templates/docs-fragments/AI_PROJECT/22_structure_docker.md +1 -1
- package/templates/docs-fragments/AI_PROJECT/23_structure_docs.md +1 -1
- package/templates/docs-fragments/AI_PROJECT/30_run_dev.md +8 -8
- package/templates/docs-fragments/AI_PROJECT/31_run_docker.md +5 -5
- package/templates/docs-fragments/AI_PROJECT/32_proxy_notes.md +5 -5
- package/templates/docs-fragments/AI_PROJECT/32_proxy_notes_none.md +5 -5
- package/templates/docs-fragments/AI_PROJECT/33_i18n_notes.md +2 -0
- package/templates/docs-fragments/AI_PROJECT/40_change_boundaries_base.md +3 -3
- package/templates/docs-fragments/AI_PROJECT/41_change_boundaries_docker.md +1 -1
- package/templates/docs-fragments/README/00_title.md +3 -3
- package/templates/docs-fragments/README/10_stack.md +8 -8
- package/templates/docs-fragments/README/20_quick_start_dev_intro.md +6 -6
- package/templates/docs-fragments/README/21_quick_start_dev_db_docker.md +4 -4
- package/templates/docs-fragments/README/21_quick_start_dev_db_local.md +1 -1
- package/templates/docs-fragments/README/22_quick_start_dev_outro.md +7 -7
- package/templates/docs-fragments/README/30_quick_start_docker.md +7 -7
- package/templates/docs-fragments/README/30_quick_start_docker_none.md +9 -9
- package/templates/docs-fragments/README/31_proxy_preset_caddy.md +9 -9
- package/templates/docs-fragments/README/31_proxy_preset_nginx.md +8 -8
- package/templates/docs-fragments/README/31_proxy_preset_none.md +6 -6
- package/templates/docs-fragments/README/32_prisma_container_start.md +5 -5
- package/templates/docs-fragments/README/40_i18n.md +14 -8
- package/templates/docs-fragments/README/90_next_steps.md +7 -7
- package/templates/module-fragments/i18n/00_title.md +5 -0
- package/templates/module-fragments/i18n/10_overview.md +9 -0
- package/templates/module-fragments/i18n/20_scope.md +7 -0
- package/templates/module-fragments/i18n/90_status_implemented.md +3 -0
- package/templates/module-fragments/jwt-auth/00_title.md +1 -1
- package/templates/module-fragments/jwt-auth/10_overview.md +6 -6
- package/templates/module-fragments/jwt-auth/20_scope.md +7 -7
- package/templates/module-fragments/jwt-auth/90_status_planned.md +3 -3
- package/templates/module-fragments/queue/00_title.md +1 -1
- package/templates/module-fragments/queue/10_overview.md +6 -6
- package/templates/module-fragments/queue/20_scope.md +7 -7
- package/templates/module-fragments/queue/90_status_planned.md +3 -3
- package/templates/module-presets/i18n/apps/web/src/App.tsx +61 -0
- package/templates/module-presets/i18n/packages/i18n-contracts/package.json +14 -0
- package/templates/module-presets/i18n/packages/i18n-contracts/src/index.ts +7 -0
- package/templates/module-presets/i18n/packages/i18n-contracts/tsconfig.json +8 -0
- package/templates/module-presets/i18n/packages/i18n-web/package.json +17 -0
- package/templates/module-presets/i18n/packages/i18n-web/src/index.ts +50 -0
- package/templates/module-presets/i18n/packages/i18n-web/tsconfig.json +8 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
## Next Steps
|
|
2
|
-
|
|
3
|
-
- Backend entrypoint: `apps/api/src/main.ts`
|
|
4
|
-
- Frontend entrypoint: `apps/web/src/main.tsx`
|
|
5
|
-
- Project docs index: `docs/README.md`
|
|
6
|
-
- AI workflow docs: `docs/AI/*`
|
|
7
|
-
- Module contract spec: `docs/AI/MODULE_SPEC.md`
|
|
1
|
+
## Next Steps
|
|
2
|
+
|
|
3
|
+
- Backend entrypoint: `apps/api/src/main.ts`
|
|
4
|
+
- Frontend entrypoint: `apps/web/src/main.tsx`
|
|
5
|
+
- Project docs index: `docs/README.md`
|
|
6
|
+
- AI workflow docs: `docs/AI/*`
|
|
7
|
+
- Module contract spec: `docs/AI/MODULE_SPEC.md`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
Adds optional i18n support across backend and frontend.
|
|
4
|
+
|
|
5
|
+
Included parts:
|
|
6
|
+
- `@forgeon/i18n` (NestJS i18n integration package)
|
|
7
|
+
- `@forgeon/i18n-contracts` (shared locale/query constants)
|
|
8
|
+
- `@forgeon/i18n-web` (React-side locale helpers)
|
|
9
|
+
- `resources/i18n/*` dictionaries (`en`, `uk`)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
## Applied Scope
|
|
2
|
+
|
|
3
|
+
- API module wiring (`AppModule`, config, filter, health endpoint translation)
|
|
4
|
+
- API package/deps/scripts updates
|
|
5
|
+
- Docker env + compose i18n env keys
|
|
6
|
+
- Frontend language selector in `apps/web/src/App.tsx`
|
|
7
|
+
- Frontend package/deps/scripts updates for i18n helpers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
# MODULE: {{MODULE_LABEL}}
|
|
1
|
+
# MODULE: {{MODULE_LABEL}}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
## Overview
|
|
2
|
-
|
|
3
|
-
- Id: `{{MODULE_ID}}`
|
|
4
|
-
- Category: `{{MODULE_CATEGORY}}`
|
|
5
|
-
- Status: {{MODULE_STATUS}}
|
|
6
|
-
- Description: {{MODULE_DESCRIPTION}}
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
- Id: `{{MODULE_ID}}`
|
|
4
|
+
- Category: `{{MODULE_CATEGORY}}`
|
|
5
|
+
- Status: {{MODULE_STATUS}}
|
|
6
|
+
- Description: {{MODULE_DESCRIPTION}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
## Scope (Planned)
|
|
2
|
-
|
|
3
|
-
Planned implementation target:
|
|
4
|
-
|
|
5
|
-
1. Add reusable auth package wiring under `packages/*`.
|
|
6
|
-
2. Add NestJS guard + strategy integration in `apps/api`.
|
|
7
|
-
3. Add env docs and usage examples.
|
|
1
|
+
## Scope (Planned)
|
|
2
|
+
|
|
3
|
+
Planned implementation target:
|
|
4
|
+
|
|
5
|
+
1. Add reusable auth package wiring under `packages/*`.
|
|
6
|
+
2. Add NestJS guard + strategy integration in `apps/api`.
|
|
7
|
+
3. Add env docs and usage examples.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
## Current State
|
|
2
|
-
|
|
3
|
-
This module is registered but not implemented yet.
|
|
1
|
+
## Current State
|
|
2
|
+
|
|
3
|
+
This module is registered but not implemented yet.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
# MODULE: {{MODULE_LABEL}}
|
|
1
|
+
# MODULE: {{MODULE_LABEL}}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
## Overview
|
|
2
|
-
|
|
3
|
-
- Id: `{{MODULE_ID}}`
|
|
4
|
-
- Category: `{{MODULE_CATEGORY}}`
|
|
5
|
-
- Status: {{MODULE_STATUS}}
|
|
6
|
-
- Description: {{MODULE_DESCRIPTION}}
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
- Id: `{{MODULE_ID}}`
|
|
4
|
+
- Category: `{{MODULE_CATEGORY}}`
|
|
5
|
+
- Status: {{MODULE_STATUS}}
|
|
6
|
+
- Description: {{MODULE_DESCRIPTION}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
## Scope (Planned)
|
|
2
|
-
|
|
3
|
-
Planned implementation target:
|
|
4
|
-
|
|
5
|
-
1. Add queue package preset (worker + producer abstractions).
|
|
6
|
-
2. Wire module imports and config in `apps/api`.
|
|
7
|
-
3. Document runtime and deployment notes.
|
|
1
|
+
## Scope (Planned)
|
|
2
|
+
|
|
3
|
+
Planned implementation target:
|
|
4
|
+
|
|
5
|
+
1. Add queue package preset (worker + producer abstractions).
|
|
6
|
+
2. Wire module imports and config in `apps/api`.
|
|
7
|
+
3. Document runtime and deployment notes.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
## Current State
|
|
2
|
-
|
|
3
|
-
This module is registered but not implemented yet.
|
|
1
|
+
## Current State
|
|
2
|
+
|
|
3
|
+
This module is registered but not implemented yet.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import * as i18nWeb from '@forgeon/i18n-web';
|
|
3
|
+
import type { I18nLocale } from '@forgeon/i18n-web';
|
|
4
|
+
import './styles.css';
|
|
5
|
+
|
|
6
|
+
type HealthResponse = {
|
|
7
|
+
status: string;
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default function App() {
|
|
12
|
+
const { I18N_LOCALES, getInitialLocale, persistLocale, toLangQuery } = i18nWeb;
|
|
13
|
+
const [locale, setLocale] = useState<I18nLocale>(getInitialLocale);
|
|
14
|
+
const [data, setData] = useState<HealthResponse | null>(null);
|
|
15
|
+
const [error, setError] = useState<string | null>(null);
|
|
16
|
+
|
|
17
|
+
const changeLocale = (nextLocale: I18nLocale) => {
|
|
18
|
+
setLocale(nextLocale);
|
|
19
|
+
persistLocale(nextLocale);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const checkApi = async () => {
|
|
23
|
+
setError(null);
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(`/api/health${toLangQuery(locale)}`, {
|
|
26
|
+
headers: {
|
|
27
|
+
'Accept-Language': locale,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error(`HTTP ${response.status}`);
|
|
32
|
+
}
|
|
33
|
+
const payload = (await response.json()) as HealthResponse;
|
|
34
|
+
setData(payload);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<main className="page">
|
|
42
|
+
<h1>Forgeon Fullstack Scaffold</h1>
|
|
43
|
+
<p>Default frontend preset: React + Vite + TypeScript.</p>
|
|
44
|
+
<label htmlFor="language">Language:</label>
|
|
45
|
+
<select
|
|
46
|
+
id="language"
|
|
47
|
+
value={locale}
|
|
48
|
+
onChange={(event) => changeLocale(event.target.value as I18nLocale)}
|
|
49
|
+
>
|
|
50
|
+
{I18N_LOCALES.map((item) => (
|
|
51
|
+
<option key={item} value={item}>
|
|
52
|
+
{item}
|
|
53
|
+
</option>
|
|
54
|
+
))}
|
|
55
|
+
</select>
|
|
56
|
+
<button onClick={checkApi}>Check API health</button>
|
|
57
|
+
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : null}
|
|
58
|
+
{error ? <p className="error">{error}</p> : null}
|
|
59
|
+
</main>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forgeon/i18n-contracts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -p tsconfig.json"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@types/node": "^22.10.7",
|
|
12
|
+
"typescript": "^5.7.3"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forgeon/i18n-web",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -p tsconfig.json"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@forgeon/i18n-contracts": "workspace:*"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/node": "^22.10.7",
|
|
15
|
+
"typescript": "^5.7.3"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
I18N_DEFAULT_LANG,
|
|
3
|
+
I18N_LOCALES,
|
|
4
|
+
LANG_QUERY_PARAM,
|
|
5
|
+
type I18nLocale,
|
|
6
|
+
} from '@forgeon/i18n-contracts';
|
|
7
|
+
|
|
8
|
+
const LOCALE_STORAGE_KEY = 'forgeon.locale';
|
|
9
|
+
|
|
10
|
+
type StorageLike = {
|
|
11
|
+
getItem: (key: string) => string | null;
|
|
12
|
+
setItem: (key: string, value: string) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function getStorage(): StorageLike | undefined {
|
|
16
|
+
if (typeof globalThis !== 'object' || globalThis === null) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const candidate = (globalThis as { localStorage?: StorageLike }).localStorage;
|
|
21
|
+
if (!candidate || typeof candidate.getItem !== 'function' || typeof candidate.setItem !== 'function') {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return candidate;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isSupportedLocale(value: string): value is I18nLocale {
|
|
29
|
+
return I18N_LOCALES.includes(value as I18nLocale);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getInitialLocale(): I18nLocale {
|
|
33
|
+
const storage = getStorage();
|
|
34
|
+
const stored = storage?.getItem(LOCALE_STORAGE_KEY);
|
|
35
|
+
if (stored && isSupportedLocale(stored)) {
|
|
36
|
+
return stored;
|
|
37
|
+
}
|
|
38
|
+
return I18N_DEFAULT_LANG;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function persistLocale(locale: I18nLocale): void {
|
|
42
|
+
const storage = getStorage();
|
|
43
|
+
storage?.setItem(LOCALE_STORAGE_KEY, locale);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function toLangQuery(locale: I18nLocale): string {
|
|
47
|
+
return `?${LANG_QUERY_PARAM}=${encodeURIComponent(locale)}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { I18N_LOCALES, type I18nLocale };
|