v0.4.8
This commit is contained in:
parent
52ae21cb57
commit
770fb33bb0
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "WEB: Vite (Chrome)",
|
"name": "WEB: Vite (Chrome)",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-server",
|
"name": "@erp/factuges-server",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsup src/index.ts --config tsup.config.ts",
|
"build": "tsup src/index.ts --config tsup.config.ts",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-web",
|
"name": "@erp/factuges-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host --clearScreen false",
|
"dev": "vite --host --clearScreen false",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/auth",
|
"name": "@erp/auth",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/core",
|
"name": "@erp/core",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
|
|
||||||
export class DocumentStorageKeyFactory {
|
export class DocumentStorageKeyFactory {
|
||||||
static fromMetadataRecord(metadata: Record<string, unknown>): string {
|
static fromMetadataRecord(metadata: Record<string, unknown>): {
|
||||||
return createHash("sha256").update(JSON.stringify(metadata)).digest("hex");
|
paths: string[];
|
||||||
|
storageKey: string;
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
paths: [String(metadata.companySlug), String(metadata.documentType)],
|
||||||
|
storageKey: createHash("sha256").update(JSON.stringify(metadata)).digest("hex"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export interface IDocumentStorage {
|
|||||||
* - Best-effort
|
* - Best-effort
|
||||||
* - Nunca lanza (errores se gestionan internamente)
|
* - Nunca lanza (errores se gestionan internamente)
|
||||||
*/
|
*/
|
||||||
existsKeyStorage(storageKey: string): Promise<Boolean>;
|
existsKeyStorage(storageKey: string, paths: string[]): Promise<Boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recupera un documento guardado.
|
* Recupera un documento guardado.
|
||||||
@ -17,7 +17,7 @@ export interface IDocumentStorage {
|
|||||||
* - Best-effort
|
* - Best-effort
|
||||||
* - Nunca lanza (errores se gestionan internamente)
|
* - Nunca lanza (errores se gestionan internamente)
|
||||||
*/
|
*/
|
||||||
readDocument(storageKey: string): Promise<IDocument | null>;
|
readDocument(storageKey: string, paths: string[]): Promise<IDocument | null>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persiste un documento generado.
|
* Persiste un documento generado.
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|
||||||
|
import { buildSafePath } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DocumentStorageKeyFactory,
|
DocumentStorageKeyFactory,
|
||||||
type IDocument,
|
type IDocument,
|
||||||
@ -15,11 +17,15 @@ import {
|
|||||||
* - No afecta al flujo del caso de uso
|
* - No afecta al flujo del caso de uso
|
||||||
*/
|
*/
|
||||||
export class FilesystemDocumentStorage implements IDocumentStorage {
|
export class FilesystemDocumentStorage implements IDocumentStorage {
|
||||||
public constructor(private readonly basePath: string) {}
|
public constructor(private readonly docRootPath: string) {}
|
||||||
|
|
||||||
|
async existsKeyStorage(storageKey: string, paths: string[]): Promise<Boolean> {
|
||||||
|
// Ejemplo: .../signed-documents/770c138fc58548f72029c1ed4f3670e94be4cc7a0fab9f7f0b84d0aef77f43ae
|
||||||
|
// paths: => [".../signed-documents"],
|
||||||
|
// storageKey: => 770c138fc58548f72029c1ed4f3670e94be4cc7a0fab9f7f0b84d0aef77f43ae
|
||||||
|
|
||||||
async existsKeyStorage(storageKey: string): Promise<Boolean> {
|
|
||||||
try {
|
try {
|
||||||
const dir = this.resolveDirFromStorageKey(storageKey);
|
const dir = this.resolveDir(storageKey, paths);
|
||||||
return (await stat(dir)).isDirectory();
|
return (await stat(dir)).isDirectory();
|
||||||
} catch {
|
} catch {
|
||||||
// Consistente con saveDocument: best-effort
|
// Consistente con saveDocument: best-effort
|
||||||
@ -27,12 +33,12 @@ export class FilesystemDocumentStorage implements IDocumentStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async readDocument(storageKey: string) {
|
async readDocument(storageKey: string, paths: string[]) {
|
||||||
try {
|
try {
|
||||||
const dir = this.resolveDirFromStorageKey(storageKey);
|
const dir = this.resolveDir(storageKey, paths);
|
||||||
|
|
||||||
const payload = await readFile(path.join(dir, "document.bin"));
|
const payload = await readFile(path.join(dir, "document.bin"));
|
||||||
const metaRaw = JSON.parse(await readFile(path.join(dir, "document.meta.json"), "utf-8"));
|
const metaRaw = await readFile(path.join(dir, "document.meta.json"), "utf-8");
|
||||||
|
|
||||||
const meta = JSON.parse(metaRaw) as {
|
const meta = JSON.parse(metaRaw) as {
|
||||||
mimeType: string;
|
mimeType: string;
|
||||||
@ -78,15 +84,15 @@ export class FilesystemDocumentStorage implements IDocumentStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private resolveDirFromMetadataRecord(metadataRecord: Record<string, unknown>): string {
|
private resolveDirFromMetadataRecord(metadataRecord: Record<string, unknown>): string {
|
||||||
/**
|
const { paths, storageKey } = DocumentStorageKeyFactory.fromMetadataRecord(metadataRecord);
|
||||||
* El storage NO decide claves semánticas.
|
|
||||||
* Se limita a generar un path técnico estable.
|
return this.resolveDir(storageKey, paths);
|
||||||
*/
|
|
||||||
const storageKey = DocumentStorageKeyFactory.fromMetadataRecord(metadataRecord);
|
|
||||||
return this.resolveDirFromStorageKey(storageKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveDirFromStorageKey(storageKey: string): string {
|
private resolveDir(storageKey: string, paths: string[]): string {
|
||||||
return path.join(this.basePath, storageKey);
|
return buildSafePath({
|
||||||
|
basePath: this.docRootPath,
|
||||||
|
segments: [...paths, storageKey],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customer-invoices",
|
"name": "@erp/customer-invoices",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -21,23 +21,25 @@ export class IssuedInvoiceSignedDocumentCachePreProcessor implements IDocumentPr
|
|||||||
async tryResolve(metadata: IDocumentMetadata): Promise<IDocument | null> {
|
async tryResolve(metadata: IDocumentMetadata): Promise<IDocument | null> {
|
||||||
const metadataRecord = metadata as unknown as Record<string, unknown>;
|
const metadataRecord = metadata as unknown as Record<string, unknown>;
|
||||||
try {
|
try {
|
||||||
const storageKey = DocumentStorageKeyFactory.fromMetadataRecord(metadataRecord);
|
const { paths, storageKey } = DocumentStorageKeyFactory.fromMetadataRecord(metadataRecord);
|
||||||
|
|
||||||
if (!storageKey) {
|
if (!storageKey) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const exists = await this.docStorage.existsKeyStorage(storageKey);
|
const exists = await this.docStorage.existsKeyStorage(storageKey, paths);
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const document = await this.docStorage.readDocument(storageKey);
|
logger.info(`✅ Found Server cached document for key ${storageKey}`);
|
||||||
|
|
||||||
|
const document = await this.docStorage.readDocument(storageKey, paths);
|
||||||
|
|
||||||
if (!this.isValid(document)) {
|
if (!this.isValid(document)) {
|
||||||
logger.warn(`Storage key ${storageKey} not exists!`, {
|
logger.warn(`Corrupted or invalid cached document for key ${storageKey}`, {
|
||||||
lable: "IssuedInvoiceSignedDocumentCachePreProcessor",
|
label: "IssuedInvoiceSignedDocumentCachePreProcessor",
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customers",
|
"name": "@erp/customers",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/doc-numbering",
|
"name": "@erp/doc-numbering",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-criteria",
|
"name": "@repo/rdx-criteria",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-ddd",
|
"name": "@repo/rdx-ddd",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-logger",
|
"name": "@repo/rdx-logger",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-utils",
|
"name": "@repo/rdx-utils",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user