create-forgeon 0.0.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.
Files changed (52) hide show
  1. package/README.md +11 -0
  2. package/bin/create-forgeon.mjs +265 -0
  3. package/package.json +16 -0
  4. package/templates/base/.editorconfig +11 -0
  5. package/templates/base/README.md +56 -0
  6. package/templates/base/apps/api/Dockerfile +23 -0
  7. package/templates/base/apps/api/package.json +40 -0
  8. package/templates/base/apps/api/prisma/migrations/0001_init/migration.sql +12 -0
  9. package/templates/base/apps/api/prisma/migrations/migration_lock.toml +1 -0
  10. package/templates/base/apps/api/prisma/schema.prisma +15 -0
  11. package/templates/base/apps/api/prisma/seed.ts +20 -0
  12. package/templates/base/apps/api/src/app.module.ts +34 -0
  13. package/templates/base/apps/api/src/common/dto/echo-query.dto.ts +6 -0
  14. package/templates/base/apps/api/src/common/filters/app-exception.filter.ts +130 -0
  15. package/templates/base/apps/api/src/config/app.config.ts +13 -0
  16. package/templates/base/apps/api/src/health/health.controller.ts +31 -0
  17. package/templates/base/apps/api/src/main.ts +26 -0
  18. package/templates/base/apps/api/src/prisma/prisma.module.ts +9 -0
  19. package/templates/base/apps/api/src/prisma/prisma.service.ts +27 -0
  20. package/templates/base/apps/api/tsconfig.build.json +9 -0
  21. package/templates/base/apps/api/tsconfig.json +9 -0
  22. package/templates/base/apps/web/Dockerfile +13 -0
  23. package/templates/base/apps/web/index.html +13 -0
  24. package/templates/base/apps/web/package.json +23 -0
  25. package/templates/base/apps/web/src/App.tsx +37 -0
  26. package/templates/base/apps/web/src/main.tsx +9 -0
  27. package/templates/base/apps/web/src/styles.css +33 -0
  28. package/templates/base/apps/web/tsconfig.json +18 -0
  29. package/templates/base/apps/web/vite.config.ts +15 -0
  30. package/templates/base/docs/AI/ARCHITECTURE.md +38 -0
  31. package/templates/base/docs/AI/PROJECT.md +32 -0
  32. package/templates/base/docs/AI/TASKS.md +48 -0
  33. package/templates/base/docs/README.md +5 -0
  34. package/templates/base/infra/docker/.env.example +10 -0
  35. package/templates/base/infra/docker/compose.yml +45 -0
  36. package/templates/base/infra/docker/nginx.Dockerfile +16 -0
  37. package/templates/base/infra/nginx/nginx.conf +32 -0
  38. package/templates/base/package.json +24 -0
  39. package/templates/base/packages/core/README.md +4 -0
  40. package/templates/base/packages/core/package.json +14 -0
  41. package/templates/base/packages/core/src/index.ts +1 -0
  42. package/templates/base/packages/core/tsconfig.json +8 -0
  43. package/templates/base/packages/i18n/package.json +19 -0
  44. package/templates/base/packages/i18n/src/forgeon-i18n.module.ts +47 -0
  45. package/templates/base/packages/i18n/src/index.ts +2 -0
  46. package/templates/base/packages/i18n/tsconfig.json +9 -0
  47. package/templates/base/pnpm-workspace.yaml +3 -0
  48. package/templates/base/resources/i18n/en/common.json +5 -0
  49. package/templates/base/resources/i18n/en/validation.json +3 -0
  50. package/templates/base/resources/i18n/uk/common.json +5 -0
  51. package/templates/base/resources/i18n/uk/validation.json +3 -0
  52. package/templates/base/tsconfig.base.json +17 -0
@@ -0,0 +1,31 @@
1
+ import { Controller, Get, Optional, Query } from '@nestjs/common';
2
+ import { I18nService } from 'nestjs-i18n';
3
+ import { EchoQueryDto } from '../common/dto/echo-query.dto';
4
+
5
+ @Controller('health')
6
+ export class HealthController {
7
+ constructor(@Optional() private readonly i18n?: I18nService) {}
8
+
9
+ @Get()
10
+ getHealth(@Query('lang') lang?: string) {
11
+ return {
12
+ status: 'ok',
13
+ message: this.translate('common.ok', lang),
14
+ };
15
+ }
16
+
17
+ @Get('echo')
18
+ getEcho(@Query() query: EchoQueryDto) {
19
+ return { value: query.value };
20
+ }
21
+
22
+ private translate(key: string, lang?: string): string {
23
+ if (!this.i18n) {
24
+ if (key === 'common.ok') return 'OK';
25
+ return key;
26
+ }
27
+
28
+ const value = this.i18n.t(key, { lang, defaultValue: key });
29
+ return typeof value === 'string' ? value : key;
30
+ }
31
+ }
@@ -0,0 +1,26 @@
1
+ import 'reflect-metadata';
2
+ import { ValidationPipe } from '@nestjs/common';
3
+ import { ConfigService } from '@nestjs/config';
4
+ import { NestFactory } from '@nestjs/core';
5
+ import { AppModule } from './app.module';
6
+ import { AppExceptionFilter } from './common/filters/app-exception.filter';
7
+
8
+ async function bootstrap() {
9
+ const app = await NestFactory.create(AppModule);
10
+
11
+ app.setGlobalPrefix('api');
12
+ app.useGlobalPipes(
13
+ new ValidationPipe({
14
+ whitelist: true,
15
+ transform: true,
16
+ }),
17
+ );
18
+ app.useGlobalFilters(app.get(AppExceptionFilter));
19
+
20
+ const configService = app.get(ConfigService);
21
+ const port = configService.get<number>('app.port') ?? 3000;
22
+
23
+ await app.listen(port);
24
+ }
25
+
26
+ bootstrap();
@@ -0,0 +1,9 @@
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 {}
@@ -0,0 +1,27 @@
1
+ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
2
+ import { PrismaClient } from '@prisma/client';
3
+
4
+ @Injectable()
5
+ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
6
+ constructor() {
7
+ const databaseUrl =
8
+ process.env.DATABASE_URL ??
9
+ 'postgresql://postgres:postgres@localhost:5432/app?schema=public';
10
+
11
+ super({
12
+ datasources: {
13
+ db: {
14
+ url: databaseUrl,
15
+ },
16
+ },
17
+ });
18
+ }
19
+
20
+ async onModuleInit(): Promise<void> {
21
+ await this.$connect();
22
+ }
23
+
24
+ async onModuleDestroy(): Promise<void> {
25
+ await this.$disconnect();
26
+ }
27
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src/**/*.ts"],
8
+ "exclude": ["**/*.spec.ts", "test", "dist", "node_modules"]
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src/**/*.ts", "prisma/**/*.ts"],
8
+ "exclude": ["dist", "node_modules"]
9
+ }
@@ -0,0 +1,13 @@
1
+ FROM node:20-alpine
2
+ WORKDIR /app
3
+ RUN corepack enable
4
+
5
+ COPY package.json pnpm-workspace.yaml ./
6
+ COPY apps/web/package.json apps/web/package.json
7
+ RUN pnpm install --frozen-lockfile=false
8
+
9
+ COPY apps/web apps/web
10
+ WORKDIR /app/apps/web
11
+ RUN pnpm build
12
+
13
+ CMD ["pnpm", "preview", "--host", "0.0.0.0", "--port", "5173"]
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Forgeon Web</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
13
+
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@forgeon/web",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^18.3.1",
13
+ "react-dom": "^18.3.1"
14
+ },
15
+ "devDependencies": {
16
+ "@types/react": "^18.3.3",
17
+ "@types/react-dom": "^18.3.0",
18
+ "@vitejs/plugin-react": "^4.3.1",
19
+ "typescript": "^5.7.3",
20
+ "vite": "^5.4.11"
21
+ }
22
+ }
23
+
@@ -0,0 +1,37 @@
1
+ import { useState } from 'react';
2
+ import './styles.css';
3
+
4
+ type HealthResponse = {
5
+ status: string;
6
+ message: string;
7
+ };
8
+
9
+ export default function App() {
10
+ const [data, setData] = useState<HealthResponse | null>(null);
11
+ const [error, setError] = useState<string | null>(null);
12
+
13
+ const checkApi = async () => {
14
+ setError(null);
15
+ try {
16
+ const response = await fetch('/api/health');
17
+ if (!response.ok) {
18
+ throw new Error(`HTTP ${response.status}`);
19
+ }
20
+ const payload = (await response.json()) as HealthResponse;
21
+ setData(payload);
22
+ } catch (err) {
23
+ setError(err instanceof Error ? err.message : 'Unknown error');
24
+ }
25
+ };
26
+
27
+ return (
28
+ <main className="page">
29
+ <h1>Forgeon Fullstack Scaffold</h1>
30
+ <p>Default frontend preset: React + Vite + TypeScript.</p>
31
+ <button onClick={checkApi}>Check API health</button>
32
+ {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : null}
33
+ {error ? <p className="error">{error}</p> : null}
34
+ </main>
35
+ );
36
+ }
37
+
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import App from './App';
4
+
5
+ ReactDOM.createRoot(document.getElementById('root')!).render(
6
+ <React.StrictMode>
7
+ <App />
8
+ </React.StrictMode>,
9
+ );
@@ -0,0 +1,33 @@
1
+ :root {
2
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
3
+ }
4
+
5
+ body {
6
+ margin: 0;
7
+ background: #f8fafc;
8
+ color: #0f172a;
9
+ }
10
+
11
+ .page {
12
+ max-width: 720px;
13
+ margin: 3rem auto;
14
+ padding: 0 1rem;
15
+ }
16
+
17
+ button {
18
+ padding: 0.6rem 1rem;
19
+ border: 0;
20
+ border-radius: 0.5rem;
21
+ cursor: pointer;
22
+ }
23
+
24
+ pre {
25
+ background: #e2e8f0;
26
+ padding: 1rem;
27
+ border-radius: 0.5rem;
28
+ overflow: auto;
29
+ }
30
+
31
+ .error {
32
+ color: #b91c1c;
33
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": false,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "strict": true,
15
+ "types": ["vite/client"]
16
+ },
17
+ "include": ["src"]
18
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ server: {
7
+ port: 5173,
8
+ proxy: {
9
+ '/api': {
10
+ target: 'http://localhost:3000',
11
+ changeOrigin: true,
12
+ },
13
+ },
14
+ },
15
+ });
@@ -0,0 +1,38 @@
1
+ # ARCHITECTURE
2
+
3
+ ## Monorepo Layout
4
+
5
+ - `apps/*` - deployable apps
6
+ - `packages/*` - reusable modules/presets
7
+ - `infra/*` - runtime infrastructure
8
+ - `resources/*` - static assets (translations)
9
+
10
+ ## Environment Flags
11
+
12
+ - `PORT` - API port (default 3000)
13
+ - `DATABASE_URL` - Prisma Postgres connection
14
+ - `I18N_ENABLED` - toggles i18n package wiring
15
+ - `I18N_DEFAULT_LANG` - default language
16
+ - `I18N_FALLBACK_LANG` - fallback language
17
+
18
+ ## Default DB Stack
19
+
20
+ Current default is Prisma + Postgres.
21
+
22
+ - Prisma schema and migrations live in `apps/api/prisma`
23
+ - DB access is encapsulated via `PrismaModule` (`apps/api/src/prisma`)
24
+
25
+ ## Future DB Presets (Not Implemented Yet)
26
+
27
+ A future preset can switch DB by:
28
+ 1. Replacing `PrismaModule` with another DB module package (for example Mongo package).
29
+ 2. Updating `infra/docker/compose.yml` DB service.
30
+ 3. Updating `DATABASE_URL` and related env keys.
31
+ 4. Keeping app-level services dependent only on repository/data-access abstractions.
32
+
33
+ ## Future Feature Modules
34
+
35
+ Reusable features should be added as workspace packages and imported by apps as needed:
36
+
37
+ - `packages/core` for shared backend primitives
38
+ - Additional packages for auth presets, guards, queues, mailers, etc.
@@ -0,0 +1,32 @@
1
+ # PROJECT
2
+
3
+ ## What This Repository Is
4
+
5
+ A canonical fullstack monorepo scaffold intended to be reused as a project starter.
6
+
7
+ ## Structure
8
+
9
+ - `apps/api` - NestJS backend
10
+ - `apps/web` - frontend scaffold (default React + Vite + TS)
11
+ - `packages/core` - shared backend core placeholder
12
+ - `packages/i18n` - reusable nestjs-i18n integration package
13
+ - `infra` - Docker Compose + Nginx
14
+ - `resources/i18n` - translation dictionaries
15
+ - `docs` - documentation and AI workflow prompts
16
+
17
+ ## Run Modes
18
+
19
+ ### Dev mode
20
+
21
+ ```bash
22
+ pnpm install
23
+ pnpm dev
24
+ ```
25
+
26
+ ### Docker mode
27
+
28
+ ```bash
29
+ docker compose --env-file infra/docker/.env.example -f infra/docker/compose.yml up --build
30
+ ```
31
+
32
+ The API uses Prisma and expects `DATABASE_URL` from env.
@@ -0,0 +1,48 @@
1
+ # TASKS
2
+
3
+ ## Feature Discovery Matrix
4
+
5
+ ```text
6
+ Scan this monorepo and build a backend feature matrix by app/package.
7
+ Use only evidence from code and dependencies.
8
+ Output:
9
+ 1) taxonomy by category
10
+ 2) feature comparison table
11
+ 3) common core
12
+ 4) unique features
13
+ 5) architectural inconsistencies
14
+ Include file references for every feature.
15
+ ```
16
+
17
+ ## Add Module Package
18
+
19
+ ```text
20
+ Create a new reusable package under packages/ for <feature-name>.
21
+ Requirements:
22
+ - minimal API
23
+ - NestJS-compatible module
24
+ - docs in package README
25
+ - wire into apps/api conditionally via env flag
26
+ - keep backward compatibility
27
+ ```
28
+
29
+ ## Refactor Core
30
+
31
+ ```text
32
+ Move shared backend logic from apps/api into packages/core.
33
+ Do not change behavior.
34
+ Update imports, package dependencies, and docs.
35
+ Run build checks and show changed files.
36
+ ```
37
+
38
+ ## Generate Preset
39
+
40
+ ```text
41
+ Create a new preset flow for create-forgeon:
42
+ - add new flag(s)
43
+ - update interactive questions
44
+ - update generated files
45
+ - keep defaults: Prisma + Postgres, React + Vite + TS
46
+ - update docs/AI/ARCHITECTURE.md
47
+ ```
48
+
@@ -0,0 +1,5 @@
1
+ # Documentation Index
2
+
3
+ - `AI/PROJECT.md` - project overview and run modes
4
+ - `AI/ARCHITECTURE.md` - monorepo design and extension model
5
+ - `AI/TASKS.md` - ready-to-use Codex prompts
@@ -0,0 +1,10 @@
1
+ POSTGRES_USER=postgres
2
+ POSTGRES_PASSWORD=postgres
3
+ POSTGRES_DB=app
4
+
5
+ PORT=3000
6
+ DATABASE_URL=postgresql://postgres:postgres@db:5432/app?schema=public
7
+
8
+ I18N_ENABLED=true
9
+ I18N_DEFAULT_LANG=en
10
+ I18N_FALLBACK_LANG=en
@@ -0,0 +1,45 @@
1
+ services:
2
+ db:
3
+ image: postgres:16-alpine
4
+ restart: unless-stopped
5
+ environment:
6
+ POSTGRES_USER: ${POSTGRES_USER}
7
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
8
+ POSTGRES_DB: ${POSTGRES_DB}
9
+ ports:
10
+ - "5432:5432"
11
+ volumes:
12
+ - db_data:/var/lib/postgresql/data
13
+ healthcheck:
14
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
15
+ interval: 10s
16
+ timeout: 5s
17
+ retries: 10
18
+
19
+ api:
20
+ build:
21
+ context: ../..
22
+ dockerfile: apps/api/Dockerfile
23
+ restart: unless-stopped
24
+ environment:
25
+ PORT: ${PORT}
26
+ DATABASE_URL: ${DATABASE_URL}
27
+ I18N_ENABLED: ${I18N_ENABLED}
28
+ I18N_DEFAULT_LANG: ${I18N_DEFAULT_LANG}
29
+ I18N_FALLBACK_LANG: ${I18N_FALLBACK_LANG}
30
+ depends_on:
31
+ db:
32
+ condition: service_healthy
33
+
34
+ nginx:
35
+ build:
36
+ context: ../..
37
+ dockerfile: infra/docker/nginx.Dockerfile
38
+ restart: unless-stopped
39
+ depends_on:
40
+ - api
41
+ ports:
42
+ - "8080:80"
43
+
44
+ volumes:
45
+ db_data:
@@ -0,0 +1,16 @@
1
+ FROM node:20-alpine AS web-builder
2
+
3
+ WORKDIR /app
4
+ RUN corepack enable
5
+
6
+ COPY package.json pnpm-workspace.yaml ./
7
+ COPY apps/web/package.json apps/web/package.json
8
+ RUN pnpm install --frozen-lockfile=false
9
+
10
+ COPY apps/web apps/web
11
+ WORKDIR /app/apps/web
12
+ RUN pnpm build
13
+
14
+ FROM nginx:1.27-alpine
15
+ COPY infra/nginx/nginx.conf /etc/nginx/nginx.conf
16
+ COPY --from=web-builder /app/apps/web/dist /usr/share/nginx/html
@@ -0,0 +1,32 @@
1
+ worker_processes auto;
2
+
3
+ events {
4
+ worker_connections 1024;
5
+ }
6
+
7
+ http {
8
+ include /etc/nginx/mime.types;
9
+ default_type application/octet-stream;
10
+ sendfile on;
11
+
12
+ server {
13
+ listen 80;
14
+ server_name _;
15
+
16
+ root /usr/share/nginx/html;
17
+ index index.html;
18
+
19
+ location /api/ {
20
+ proxy_pass http://api:3000/api/;
21
+ proxy_http_version 1.1;
22
+ proxy_set_header Host $host;
23
+ proxy_set_header X-Real-IP $remote_addr;
24
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
25
+ proxy_set_header X-Forwarded-Proto $scheme;
26
+ }
27
+
28
+ location / {
29
+ try_files $uri /index.html;
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "forgeon",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "packageManager": "pnpm@10.0.0",
6
+ "scripts": {
7
+ "dev": "pnpm --parallel --filter @forgeon/api --filter @forgeon/web dev",
8
+ "build": "pnpm -r build",
9
+ "postinstall": "pnpm --filter @forgeon/api prisma:generate",
10
+ "create:forgeon": "node scripts/create-forgeon.mjs",
11
+ "docker:up": "docker compose --env-file infra/docker/.env.example -f infra/docker/compose.yml up --build",
12
+ "docker:down": "docker compose -f infra/docker/compose.yml down -v"
13
+ },
14
+ "pnpm": {
15
+ "onlyBuiltDependencies": [
16
+ "@nestjs/core",
17
+ "@prisma/client",
18
+ "@prisma/engines",
19
+ "esbuild",
20
+ "prisma"
21
+ ]
22
+ }
23
+ }
24
+
@@ -0,0 +1,4 @@
1
+ # @forgeon/core
2
+
3
+ Placeholder package for shared backend modules (auth guards, config helpers, etc.).
4
+
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@forgeon/core",
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
+ "typescript": "^5.7.3"
12
+ }
13
+ }
14
+
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src/**/*.ts"]
8
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@forgeon/i18n",
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
+ "@nestjs/common": "^11.0.1",
12
+ "nestjs-i18n": "^10.5.1"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^22.10.7",
16
+ "typescript": "^5.7.3"
17
+ }
18
+ }
19
+
@@ -0,0 +1,47 @@
1
+ import { DynamicModule, Module } from '@nestjs/common';
2
+ import {
3
+ AcceptLanguageResolver,
4
+ I18nJsonLoader,
5
+ I18nModule,
6
+ QueryResolver,
7
+ } from 'nestjs-i18n';
8
+ import { join } from 'path';
9
+
10
+ export interface ForgeonI18nOptions {
11
+ enabled: boolean;
12
+ defaultLang: string;
13
+ fallbackLang: string;
14
+ path?: string;
15
+ }
16
+
17
+ @Module({})
18
+ export class ForgeonI18nModule {
19
+ static register(options: ForgeonI18nOptions): DynamicModule {
20
+ if (!options.enabled) {
21
+ return { module: ForgeonI18nModule };
22
+ }
23
+
24
+ const translationsPath =
25
+ options.path ?? join(process.cwd(), 'resources', 'i18n');
26
+
27
+ return {
28
+ module: ForgeonI18nModule,
29
+ imports: [
30
+ I18nModule.forRoot({
31
+ fallbackLanguage: options.fallbackLang,
32
+ loader: I18nJsonLoader,
33
+ loaderOptions: {
34
+ path: translationsPath,
35
+ watch: false,
36
+ },
37
+ resolvers: [
38
+ { use: AcceptLanguageResolver, options: { matchType: 'strict-loose' } },
39
+ { use: QueryResolver, options: ['lang'] },
40
+ ],
41
+ }),
42
+ ],
43
+ exports: [I18nModule],
44
+ };
45
+ }
46
+ }
47
+
@@ -0,0 +1,2 @@
1
+ export * from './forgeon-i18n.module';
2
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "types": ["node"]
7
+ },
8
+ "include": ["src/**/*.ts"]
9
+ }
@@ -0,0 +1,3 @@
1
+ packages:
2
+ - apps/*
3
+ - packages/*