feat: update TypeScript configurations and add frontend testing documentation

This commit is contained in:
David Arranz 2026-08-19 10:39:15 +02:00
parent 080dcaaa61
commit 01fba79e38
31 changed files with 254 additions and 58 deletions

View File

@ -2,6 +2,7 @@
"extends": "@repo/typescript-config/express.json", "extends": "@repo/typescript-config/express.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"noEmit": true, "noEmit": true,
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"lib": ["ES2022"], "lib": ["ES2022"],

View File

@ -1,5 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
}, },
@ -16,6 +17,7 @@
"isolatedModules": true, "isolatedModules": true,
"moduleDetection": "force", "moduleDetection": "force",
"noEmit": true, "noEmit": true,
"ignoreDeprecations": "6.0",
"jsx": "react-jsx", "jsx": "react-jsx",
/* Linting */ /* Linting */

View File

@ -2,6 +2,8 @@
"files": [], "files": [],
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }], "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"ignoreDeprecations": "6.0",
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,
"paths": { "paths": {

View File

@ -53,6 +53,7 @@ Este directorio reúne la documentación técnica, operativa y de apoyo del ERP.
- [README de `modules/auth`](../modules/auth/README.md) - [README de `modules/auth`](../modules/auth/README.md)
- [API pública de selección y alta rápida de clientes](./customers/customer-selection-and-quick-create.md) - [API pública de selección y alta rápida de clientes](./customers/customer-selection-and-quick-create.md)
- [Tests HTTP backend](./testing/backend-http-integration.md) - [Tests HTTP backend](./testing/backend-http-integration.md)
- [Harness frontend con `node:test`](./testing/frontend-node-test.md)
#### Guías y estándares #### Guías y estándares

View File

@ -0,0 +1,76 @@
# Tests frontend con `node:test`
El harness frontend vigente del ERP usa:
- `node:test` como runner
- `tsx` como transpiler
- renderizado en Node puro
- `react-dom/server` para tests React sin DOM real
No existe infraestructura activa de `vitest`, `jest`, `jsdom` ni `happy-dom` en el monorepo.
## Requisitos
Ejecuta los tests en Ubuntu desde la raíz del repo:
```bash
cd /home/rodax/Documentos/uecko-erp
node --version
pnpm --version
```
El runtime esperado del repo es Node `>= 24`.
## Comandos canónicos
### Test React individual
```bash
cd /home/rodax/Documentos/uecko-erp
pnpm test:frontend -- modules/customer-invoices/src/web/proformas/update/ui/components/proforma-update-help-popover.test.tsx
```
### Tests frontend de un módulo
```bash
cd /home/rodax/Documentos/uecko-erp
pnpm test:frontend -- modules/customer-invoices/src/web/**/*.test.tsx
```
### Tests frontend de `apps/web`
```bash
cd /home/rodax/Documentos/uecko-erp
pnpm test:frontend -- apps/web/src/**/*.test.tsx
```
### Test TypeScript puro
```bash
cd /home/rodax/Documentos/uecko-erp
pnpm test:unit -- packages/rdx-utils/src/helpers/__tests__/maybe.test.ts
```
## Mocking
Los tests frontend que necesitan mocks de módulos deben usar `mock.module()` de `node:test`.
Eso obliga a ejecutar el runner con:
```bash
node --experimental-test-module-mocks --import tsx --test
```
Por eso el script oficial es `pnpm test:frontend`.
## Qué no hacer
- No ejecutar tests React con `pnpm dlx tsx --test` si el test usa `mock.module()`.
- No asumir `jsdom` o `@testing-library/react` si el test actual solo necesita SSR.
- No importar barrels amplios si el test solo necesita un componente o helper local.
## Criterios prácticos
- Usa `pnpm test:unit` para tests `.ts` o `.tsx` que no dependan de `mock.module()`.
- Usa `pnpm test:frontend` cuando el test React necesite `mock.module()`.
- Si un componente necesita traducciones, mockea `../../../../i18n` o el helper local antes de arrancar el `manifest` del módulo.

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/auth/*": ["./src/*"] "@erp/auth/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/catalogs/*": ["./src/*"] "@erp/catalogs/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/companies/*": ["./src/*"] "@erp/companies/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/core/*": ["./src/*"] "@erp/core/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
import assert from "node:assert/strict"; import assert from "node:assert/strict";
import test from "node:test"; import test from "node:test";
import { UtcDate } from "@repo/rdx-ddd";
import { Maybe, Result } from "@repo/rdx-utils"; import { Maybe, Result } from "@repo/rdx-utils";
import { SequelizeIssuedInvoiceV2DomainMapper } from "./sequelize-issued-invoice-v2-domain.mapper"; import { SequelizeIssuedInvoiceV2DomainMapper } from "./sequelize-issued-invoice-v2-domain.mapper";
@ -25,7 +26,9 @@ type PaymentTermRoundTripReadResult = {
}; };
const buildMapper = () => { const buildMapper = () => {
const mapper = new SequelizeIssuedInvoiceV2DomainMapper({} as never) as unknown as { const mapper = new SequelizeIssuedInvoiceV2DomainMapper({
taxCatalog: {},
} as never) as unknown as {
_itemsMapper: { _itemsMapper: {
mapToPersistenceArray: () => ReturnType<typeof Result.ok<[]>>; mapToPersistenceArray: () => ReturnType<typeof Result.ok<[]>>;
}; };
@ -267,6 +270,82 @@ test("rehidrata el snapshot persistido histórico sin depender del catálogo viv
]); ]);
}); });
test("normaliza verifactu_effective_at Date a YYYY-MM-DD al rehidratar", () => {
const mapper = buildMapper();
const raw = {
verifactu_effective_at: new Date("2027-01-12T00:00:00.000Z"),
} as {
verifactu_effective_at: Date;
};
const result = mapper.mapToDomain.bind(mapper) as unknown;
assert.ok(result);
const effectiveAt = mapper as unknown as {
_mapAttributesToDomain: (
source: unknown,
params: { errors: Array<{ message: string; path: string; value?: unknown }> }
) => { hasVerifactuSnapshots: boolean };
};
const errors: Array<{ message: string; path: string; value?: unknown }> = [];
const attributes = effectiveAt._mapAttributesToDomain(
{
id: "11111111-1111-4111-8111-111111111111",
company_id: "22222222-2222-4222-8222-222222222222",
customer_id: "33333333-3333-4333-8333-333333333333",
source_proforma_id: "44444444-4444-4444-8444-444444444444",
document_series_id: null,
status: "issued",
invoice_series_code: "F26",
invoice_number: "173",
invoice_reference: "F260173",
invoice_date: "2026-08-18",
operation_date: "2026-08-06",
language_code: "es",
currency_code: "EUR",
reference: null,
description: "Factura emitida",
notes: null,
payment_term_id: null,
payment_term_name: null,
payment_term_description: null,
payment_term_snapshot_json: null,
payment_method_id: "55555555-5555-4555-8555-555555555555",
payment_method_name: "Transferencia",
payment_method_description: "Transferencia",
tax_regime_code: "04",
tax_regime_description: "04: Régimen especial del oro de inversión.",
subtotal_amount_value: 10000,
items_discount_amount_value: 0,
global_discount_percentage_value: 0,
global_discount_amount_value: 0,
total_discount_amount_value: 0,
taxable_amount_value: 10000,
iva_amount_value: 2100,
rec_amount_value: 0,
retention_amount_value: 0,
taxes_amount_value: 2100,
total_amount_value: 12100,
verifactu_profile_status: "obligated_with_verifactu",
uses_verifactu: true,
verifactu_effective_at: raw.verifactu_effective_at,
},
{ errors }
) as {
hasVerifactuSnapshots: boolean;
};
assert.equal(attributes.hasVerifactuSnapshots, true);
const utcDateResult = UtcDate.createFromISO(
raw.verifactu_effective_at.toISOString().slice(0, 10)
);
assert.equal(utcDateResult.isSuccess, true);
assert.equal(utcDateResult.data.toPrimitive(), "2027-01-12");
assert.deepEqual(errors, []);
});
test("rechaza snapshots persistidos inconsistentes de payment term", () => { test("rechaza snapshots persistidos inconsistentes de payment term", () => {
const mapper = buildMapper(); const mapper = buildMapper();

View File

@ -24,8 +24,8 @@ import {
InvoiceSerie, InvoiceSerie,
InvoiceStatus, InvoiceStatus,
InvoiceTaxRegime, InvoiceTaxRegime,
IssuedInvoiceFiscalClassification,
IssuedInvoice, IssuedInvoice,
IssuedInvoiceFiscalClassification,
IssuedInvoiceItems, IssuedInvoiceItems,
IssuedInvoiceTaxes, IssuedInvoiceTaxes,
IssuedInvoiceVerifactuPolicy, IssuedInvoiceVerifactuPolicy,
@ -268,8 +268,6 @@ export class SequelizeIssuedInvoiceV2DomainMapper extends SequelizeDomainMapper<
params?: MapperParamsType params?: MapperParamsType
): Result<IssuedInvoice, Error> { ): Result<IssuedInvoice, Error> {
try { try {
console.debug(raw);
const errors: ValidationErrorDetail[] = []; const errors: ValidationErrorDetail[] = [];
const attributes = this._mapAttributesToDomain(raw, { errors, ...params }); const attributes = this._mapAttributesToDomain(raw, { errors, ...params });
const recipientResult = this._recipientMapper.mapToDomain(raw, { const recipientResult = this._recipientMapper.mapToDomain(raw, {
@ -338,13 +336,16 @@ export class SequelizeIssuedInvoiceV2DomainMapper extends SequelizeDomainMapper<
const effectiveAt = extractOrPushError( const effectiveAt = extractOrPushError(
maybeFromNullableResult(raw.verifactu_effective_at, (value) => maybeFromNullableResult(raw.verifactu_effective_at, (value) =>
UtcDate.createFromISO(value instanceof Date ? value.toISOString() : String(value)) UtcDate.createFromISO(
value instanceof Date ? value.toISOString().slice(0, 10) : String(value).slice(0, 10)
)
), ),
"verifactu_effective_at", "verifactu_effective_at",
errors errors
); );
if (errors.length > 0) { if (errors.length > 0) {
console.error(errors);
return Result.fail( return Result.fail(
new ValidationErrorCollection("Issued invoice V2 mapping failed [mapToDomain]", errors) new ValidationErrorCollection("Issued invoice V2 mapping failed [mapToDomain]", errors)
); );
@ -481,10 +482,10 @@ export class SequelizeIssuedInvoiceV2DomainMapper extends SequelizeDomainMapper<
tax_regime_code: source.taxRegime.code, tax_regime_code: source.taxRegime.code,
tax_regime_description: source.taxRegime.description, tax_regime_description: source.taxRegime.description,
operation_qualification_code: source.fiscalClassification.isSome() operation_qualification_code: source.fiscalClassification.isSome()
? source.fiscalClassification.unwrap().operationQualificationCode.getOrUndefined() ?? null ? (source.fiscalClassification.unwrap().operationQualificationCode.getOrUndefined() ?? null)
: null, : null,
exemption_reason_code: source.fiscalClassification.isSome() exemption_reason_code: source.fiscalClassification.isSome()
? source.fiscalClassification.unwrap().exemptionReasonCode.getOrUndefined() ?? null ? (source.fiscalClassification.unwrap().exemptionReasonCode.getOrUndefined() ?? null)
: null, : null,
verifactu_profile_status: source.verifactuPolicy.isSome() verifactu_profile_status: source.verifactuPolicy.isSome()
? source.verifactuPolicy.unwrap().profileStatus ? source.verifactuPolicy.unwrap().profileStatus
@ -493,7 +494,7 @@ export class SequelizeIssuedInvoiceV2DomainMapper extends SequelizeDomainMapper<
? source.verifactuPolicy.unwrap().usesVerifactu ? source.verifactuPolicy.unwrap().usesVerifactu
: null, : null,
verifactu_effective_at: source.verifactuPolicy.isSome() verifactu_effective_at: source.verifactuPolicy.isSome()
? source.verifactuPolicy.unwrap().effectiveAt.getOrUndefined()?.toDate() ?? null ? (source.verifactuPolicy.unwrap().effectiveAt.getOrUndefined()?.toDate() ?? null)
: null, : null,
subtotal_amount_value: source.subtotalAmount.value, subtotal_amount_value: source.subtotalAmount.value,
subtotal_amount_scale: source.subtotalAmount.scale, subtotal_amount_scale: source.subtotalAmount.scale,
@ -528,11 +529,12 @@ export class SequelizeIssuedInvoiceV2DomainMapper extends SequelizeDomainMapper<
} }
private mapPaymentTerm(raw: IssuedInvoiceModel): Result<Maybe<InvoicePaymentTerm>, Error> { private mapPaymentTerm(raw: IssuedInvoiceModel): Result<Maybe<InvoicePaymentTerm>, Error> {
const hasAnyPaymentTermData = const hasAnyPaymentTermData = !(
!isNullishOrEmpty(raw.payment_term_id) || isNullishOrEmpty(raw.payment_term_id) &&
!isNullishOrEmpty(raw.payment_term_name) || isNullishOrEmpty(raw.payment_term_name) &&
!isNullishOrEmpty(raw.payment_term_description) || isNullishOrEmpty(raw.payment_term_description) &&
!isNullishOrEmpty(raw.payment_term_snapshot_json); isNullishOrEmpty(raw.payment_term_snapshot_json)
);
if (!hasAnyPaymentTermData) { if (!hasAnyPaymentTermData) {
return Result.ok(Maybe.none()); return Result.ok(Maybe.none());
@ -600,16 +602,19 @@ export class SequelizeIssuedInvoiceV2DomainMapper extends SequelizeDomainMapper<
return Result.ok(Maybe.some(paymentTermResult.data)); return Result.ok(Maybe.some(paymentTermResult.data));
} }
private parsePaymentTermSnapshotJson(source: string): Result<{ private parsePaymentTermSnapshotJson(source: string): Result<
version: 1; {
dueRules: Array<{ version: 1;
dueDays: string; dueRules: Array<{
percentage: { dueDays: string;
value: string; percentage: {
scale: number; value: string;
}; scale: number;
}>; };
}, Error> { }>;
},
Error
> {
try { try {
const parsed = JSON.parse(source) as { const parsed = JSON.parse(source) as {
version?: unknown; version?: unknown;

View File

@ -5,14 +5,14 @@ import { useTranslation as useI18NextTranslation } from "react-i18next";
import enResources from "../common/locales/en.json"; import enResources from "../common/locales/en.json";
import esResources from "../common/locales/es.json"; import esResources from "../common/locales/es.json";
import { MODULE_NAME } from "./manifest"; import { CUSTOMER_INVOICES_MODULE_NAME } from "./module-name";
/** /**
* Registra dinámicamente las traducciones del módulo. * Registra dinámicamente las traducciones del módulo.
*/ */
export const ensureModuleTranslations = () => { export const ensureModuleTranslations = () => {
registerTranslations(MODULE_NAME, "en", enResources); registerTranslations(CUSTOMER_INVOICES_MODULE_NAME, "en", enResources);
registerTranslations(MODULE_NAME, "es", esResources); registerTranslations(CUSTOMER_INVOICES_MODULE_NAME, "es", esResources);
}; };
/** /**
@ -23,13 +23,13 @@ export const ensureModuleTranslations = () => {
*/ */
export const useTranslation = () => { export const useTranslation = () => {
// Asegura los bundles del módulo al montar (idempotente) // Asegura los bundles del módulo al montar (idempotente)
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation> // biome-ignore lint/correctness/useExhaustiveDependencies: i18n es un singleton estable del runtime compartido
useEffect(() => { useEffect(() => {
ensureModuleTranslations(); ensureModuleTranslations();
}, [i18n]); }, [i18n]);
// Hook con namespace // Hook con namespace
return useI18NextTranslation(MODULE_NAME, { return useI18NextTranslation(CUSTOMER_INVOICES_MODULE_NAME, {
i18n, i18n,
}); });
}; };

View File

@ -2,8 +2,9 @@ import type { IModuleClient, ModuleClientParams } from "@erp/core/client";
import { CustomerInvoiceRoutes } from "./customer-invoice-routes"; import { CustomerInvoiceRoutes } from "./customer-invoice-routes";
import { ensureModuleTranslations } from "./i18n"; import { ensureModuleTranslations } from "./i18n";
import { CUSTOMER_INVOICES_MODULE_NAME } from "./module-name";
export const MODULE_NAME = "CustomerInvoices"; export const MODULE_NAME = CUSTOMER_INVOICES_MODULE_NAME;
const MODULE_VERSION = "1.0.0"; const MODULE_VERSION = "1.0.0";
ensureModuleTranslations(); ensureModuleTranslations();

View File

@ -0,0 +1 @@
export const CUSTOMER_INVOICES_MODULE_NAME = "CustomerInvoices";

View File

@ -56,6 +56,18 @@ test("conecta la alta rápida directa y la alta rápida desde selector con callb
}, },
}); });
mock.module("@repo/rdx-ui/helpers", {
namedExports: {
showErrorToast: () => undefined,
},
});
mock.module("@repo/shadcn-ui/components", {
namedExports: {
Badge: ({ children }: { children?: ReactNode }) => children ?? null,
},
});
mock.module("react-hook-form", { mock.module("react-hook-form", {
namedExports: { namedExports: {
FormProvider: ({ children }: { children: ReactNode }) => children, FormProvider: ({ children }: { children: ReactNode }) => children,
@ -76,6 +88,12 @@ test("conecta la alta rápida directa y la alta rápida desde selector con callb
}, },
}); });
mock.module("../../../list/ui/components", {
namedExports: {
ProformaStatusBadge: () => null,
},
});
mock.module("../../controllers/use-update-proforma-page-controller", { mock.module("../../controllers/use-update-proforma-page-controller", {
namedExports: { namedExports: {
useUpdateProformaPageController: () => ({ useUpdateProformaPageController: () => ({

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/customer-invoices/*": ["./src/*"], "@erp/customer-invoices/*": ["./src/*"],
"@erp/identity/*": ["../identity/src/*"] "@erp/identity/*": ["../identity/src/*"]

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/customers/*": ["./src/*"], "@erp/customers/*": ["./src/*"],
"@erp/identity/*": ["../identity/src/*"] "@erp/identity/*": ["../identity/src/*"]

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/document-series/*": ["./src/*"] "@erp/document-series/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/factuges/*": ["./src/*"], "@erp/factuges/*": ["./src/*"],
"@erp/identity/*": ["../identity/src/*"] "@erp/identity/*": ["../identity/src/*"]

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/identity/*": ["./src/*"] "@erp/identity/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/supplier-invoices/*": ["./src/*"] "@erp/supplier-invoices/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@erp/suppliers/*": ["./src/*"] "@erp/suppliers/*": ["./src/*"]
}, },

View File

@ -24,6 +24,8 @@
"format:check": "biome format .", "format:check": "biome format .",
"check": "biome check .", "check": "biome check .",
"check:write": "biome check --write .", "check:write": "biome check --write .",
"test:frontend": "node --experimental-test-module-mocks --import tsx --test",
"test:unit": "node --import tsx --test",
"typecheck": "tsc -p tsconfig.json --noEmit" "typecheck": "tsc -p tsconfig.json --noEmit"
}, },
"devDependencies": { "devDependencies": {
@ -38,6 +40,7 @@
"plop": "^4.0.5", "plop": "^4.0.5",
"rimraf": "^6.1.3", "rimraf": "^6.1.3",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsx": "^4.21.0",
"tailwindcss": "^4.2.2", "tailwindcss": "^4.2.2",
"turbo": "^2.9.14", "turbo": "^2.9.14",
"typescript": "6.0.2" "typescript": "6.0.2"

View File

@ -1,6 +1,7 @@
{ {
"extends": "@repo/typescript-config/react-library.json", "extends": "@repo/typescript-config/react-library.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"@repo/rdx-ui/*": ["./src/*"] "@repo/rdx-ui/*": ["./src/*"]
}, },

View File

@ -1,6 +1,7 @@
{ {
"extends": "@repo/typescript-config/buildless.json", "extends": "@repo/typescript-config/buildless.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"types": ["node"], "types": ["node"],
"rootDir": "src", "rootDir": "src",
"paths": { "paths": {

View File

@ -1,6 +1,7 @@
{ {
"extends": "@repo/typescript-config/react-library.json", "extends": "@repo/typescript-config/react-library.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"module": "node16", "module": "node16",
"target": "esnext", "target": "esnext",
"moduleResolution": "node16", "moduleResolution": "node16",

View File

@ -19,6 +19,7 @@
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"moduleDetection": "force", "moduleDetection": "force",
"ignoreDeprecations": "6.0",
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"target": "ES2022" "target": "ES2022"

View File

@ -6,6 +6,7 @@
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"ignoreDeprecations": "6.0",
"importsNotUsedAsValues": "remove", "importsNotUsedAsValues": "remove",
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,

View File

@ -2,34 +2,18 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"display": "Root", "display": "Root",
"compilerOptions": { "compilerOptions": {
"baseUrl": "../..",
"ignoreDeprecations": "6.0",
"paths": { "paths": {
"@erp/core/*": [ "@erp/core/*": ["modules/core/src/*"],
"modules/core/src/*" "@erp/auth/*": ["modules/auth/src/*"],
], "@erp/companies/*": ["modules/companies/src/*"],
"@erp/auth/*": [ "@erp/identity/*": ["modules/identity/src/*"],
"modules/auth/src/*" "@erp/catalogs/*": ["modules/catalogs/src/*"],
], "@erp/customers/*": ["modules/customers/src/*"],
"@erp/companies/*": [ "@erp/customer-invoices/*": ["modules/customer-invoices/src/*"],
"modules/companies/src/*" "@erp/factuges/*": ["modules/factuges/src/*"],
], "@erp/document-series/*": ["modules/document-series/src/*"]
"@erp/identity/*": [
"modules/identity/src/*"
],
"@erp/catalogs/*": [
"modules/catalogs/src/*"
],
"@erp/customers/*": [
"modules/customers/src/*"
],
"@erp/customer-invoices/*": [
"modules/customer-invoices/src/*"
],
"@erp/factuges/*": [
"modules/factuges/src/*"
],
"@erp/document-series/*": [
"modules/document-series/src/*"
]
}, },
"target": "ES2021", "target": "ES2021",
"module": "CommonJS", "module": "CommonJS",

View File

@ -44,6 +44,9 @@ importers:
ts-node: ts-node:
specifier: ^10.9.2 specifier: ^10.9.2
version: 10.9.2(@types/node@25.9.1)(typescript@6.0.2) version: 10.9.2(@types/node@25.9.1)(typescript@6.0.2)
tsx:
specifier: ^4.21.0
version: 4.21.0
turbo: turbo:
specifier: ^2.9.14 specifier: ^2.9.14
version: 2.9.14 version: 2.9.14

View File

@ -1,4 +1,8 @@
{ {
"extends": "@repo/typescript-config/root.json", "extends": "@repo/typescript-config/root.json",
"compilerOptions": {
"ignoreDeprecations": "6.0",
"jsx": "react-jsx"
},
"include": ["apps", "modules", "packages"] "include": ["apps", "modules", "packages"]
} }