@mdgf11/filesystem-lib 2.2.17 → 2.2.19
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/dist/filesystemDocumentMethods.d.ts +13 -0
- package/dist/filesystemDocumentMethods.js +117 -0
- package/dist/filesystemUpdateMethods.d.ts +2 -1
- package/dist/filesystemUpdateMethods.js +18 -6
- package/dist/types.d.ts +14 -1
- package/dist/types.js +6 -2
- package/package.json +1 -1
- package/src/filesystemDocumentMethods.ts +133 -1
- package/src/filesystemUpdateMethods.ts +22 -8
- package/src/types.ts +16 -2
|
@@ -5,6 +5,19 @@ export declare function loadFilesystemDocument(jsonPath: string): FilesystemDocu
|
|
|
5
5
|
export type DocumentFileType = "nlp" | "details" | "pdf" | "docx" | "txt";
|
|
6
6
|
export declare function loadDocumentFile(doc: PartialJurisprudenciaDocument, type: "nlp" | "details"): string;
|
|
7
7
|
export declare function loadDocumentFile(doc: PartialJurisprudenciaDocument, type: "pdf" | "docx" | "txt"): Buffer;
|
|
8
|
+
export declare const ANONIMIZADO_NAME = "Anonimizado";
|
|
9
|
+
/**
|
|
10
|
+
* Converts the anonymized HTML text (and optionally summary) to DOCX and PDF files
|
|
11
|
+
* saved as Anonimizado.docx / Anonimizado.pdf in the document's filesystem directory.
|
|
12
|
+
* Requires pandoc (and xelatex for PDF) to be available on PATH.
|
|
13
|
+
*/
|
|
14
|
+
export declare function saveAnonimizedDocument(doc: PartialJurisprudenciaDocument, textoHtml: string, sumarioHtml?: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Moves the filesystem directory of a document when Área or Data changes.
|
|
17
|
+
* Must be called BEFORE updating the document in Elasticsearch.
|
|
18
|
+
* Also updates Detalhes.json inside the directory and writes a Juris update event.
|
|
19
|
+
*/
|
|
20
|
+
export declare function moveDecision(currentDoc: PartialJurisprudenciaDocument, updateObject: PartialJurisprudenciaDocument): void;
|
|
8
21
|
/** @deprecated use loadDocumentFile(doc, "nlp") instead */
|
|
9
22
|
export declare function loadNlpDocument(jurisprudencia_document: JurisprudenciaDocument): string;
|
|
10
23
|
export declare function hasSelectableText(buffer: Buffer): Promise<boolean>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
1
2
|
import fs from "fs";
|
|
2
3
|
import mammoth from "mammoth";
|
|
4
|
+
import path from "path";
|
|
3
5
|
import { DETAILS_NAME, FILESYSTEM_PATH, ORIGINAL_NAME, ROOT_PATH, SHAREPOINT_COPY_PATH } from "./types.js";
|
|
6
|
+
import { writeDocumentEvent } from "./filesystemUpdateMethods.js";
|
|
4
7
|
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
|
|
5
8
|
export function writeFilesystemDocument(filesystem_document) {
|
|
6
9
|
if (!filesystem_document.content)
|
|
@@ -64,6 +67,120 @@ export function loadDocumentFile(doc, type) {
|
|
|
64
67
|
}
|
|
65
68
|
return fs.readFileSync(`${dirPath}/${ORIGINAL_NAME}.${type}`);
|
|
66
69
|
}
|
|
70
|
+
export const ANONIMIZADO_NAME = "Anonimizado";
|
|
71
|
+
/**
|
|
72
|
+
* Converts the anonymized HTML text (and optionally summary) to DOCX and PDF files
|
|
73
|
+
* saved as Anonimizado.docx / Anonimizado.pdf in the document's filesystem directory.
|
|
74
|
+
* Requires pandoc (and xelatex for PDF) to be available on PATH.
|
|
75
|
+
*/
|
|
76
|
+
export async function saveAnonimizedDocument(doc, textoHtml, sumarioHtml) {
|
|
77
|
+
const dirPath = `${ROOT_PATH}${FILESYSTEM_PATH}${generateFilePath(doc)}`;
|
|
78
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
79
|
+
const bodyHtml = sumarioHtml
|
|
80
|
+
? `<h2>Sumário</h2>${sumarioHtml}<h2>Texto</h2>${textoHtml}`
|
|
81
|
+
: textoHtml;
|
|
82
|
+
const fullHtml = `<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>${bodyHtml}</body></html>`;
|
|
83
|
+
const tmpHtml = path.join(dirPath, `_anonimizado_tmp.html`);
|
|
84
|
+
fs.writeFileSync(tmpHtml, fullHtml, { encoding: "utf-8" });
|
|
85
|
+
try {
|
|
86
|
+
const docxPath = path.join(dirPath, `${ANONIMIZADO_NAME}.docx`);
|
|
87
|
+
const pdfPath = path.join(dirPath, `${ANONIMIZADO_NAME}.pdf`);
|
|
88
|
+
try {
|
|
89
|
+
execFileSync("pandoc", [tmpHtml, "-o", docxPath]);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.error("saveAnonimizedDocument: failed to generate DOCX:", err);
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
execFileSync("pandoc", [tmpHtml, "--pdf-engine=xelatex", "-o", pdfPath]);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
console.error("saveAnonimizedDocument: failed to generate PDF:", err);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
try {
|
|
103
|
+
fs.unlinkSync(tmpHtml);
|
|
104
|
+
}
|
|
105
|
+
catch { /* ignore */ }
|
|
106
|
+
}
|
|
107
|
+
if (doc.UUID) {
|
|
108
|
+
writeDocumentEvent({
|
|
109
|
+
source: "Juris",
|
|
110
|
+
date: new Date().toISOString(),
|
|
111
|
+
uuid: doc.UUID,
|
|
112
|
+
event: "anonimize",
|
|
113
|
+
new_path: dirPath,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Moves the filesystem directory of a document when Área or Data changes.
|
|
119
|
+
* Must be called BEFORE updating the document in Elasticsearch.
|
|
120
|
+
* Also updates Detalhes.json inside the directory and writes a Juris update event.
|
|
121
|
+
*/
|
|
122
|
+
export function moveDecision(currentDoc, updateObject) {
|
|
123
|
+
if (!currentDoc.UUID)
|
|
124
|
+
return;
|
|
125
|
+
const newArea = updateObject.Área;
|
|
126
|
+
const newData = updateObject.Data;
|
|
127
|
+
const areaChanged = newArea?.Show && JSON.stringify(newArea.Show) !== JSON.stringify(currentDoc.Área?.Show);
|
|
128
|
+
const dataChanged = newData && newData !== currentDoc.Data;
|
|
129
|
+
if (!areaChanged && !dataChanged)
|
|
130
|
+
return;
|
|
131
|
+
let oldRelPath;
|
|
132
|
+
try {
|
|
133
|
+
oldRelPath = generateFilePath(currentDoc);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return; // doc missing required metadata
|
|
137
|
+
}
|
|
138
|
+
const oldPath = `${ROOT_PATH}${FILESYSTEM_PATH}${oldRelPath}`;
|
|
139
|
+
if (!fs.existsSync(oldPath))
|
|
140
|
+
return;
|
|
141
|
+
const mergedDoc = {
|
|
142
|
+
...currentDoc,
|
|
143
|
+
...(areaChanged ? { Área: newArea } : {}),
|
|
144
|
+
...(dataChanged ? { Data: newData } : {}),
|
|
145
|
+
};
|
|
146
|
+
let newRelPath;
|
|
147
|
+
try {
|
|
148
|
+
newRelPath = generateFilePath(mergedDoc);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const newPath = `${ROOT_PATH}${FILESYSTEM_PATH}${newRelPath}`;
|
|
154
|
+
if (oldPath === newPath)
|
|
155
|
+
return;
|
|
156
|
+
fs.mkdirSync(path.dirname(newPath), { recursive: true });
|
|
157
|
+
fs.renameSync(oldPath, newPath);
|
|
158
|
+
// Update Detalhes.json with the new path
|
|
159
|
+
const detalhesPath = path.join(newPath, `${DETAILS_NAME}.json`);
|
|
160
|
+
if (fs.existsSync(detalhesPath)) {
|
|
161
|
+
try {
|
|
162
|
+
const detalhes = JSON.parse(fs.readFileSync(detalhesPath, "utf-8"));
|
|
163
|
+
detalhes.file_path = newRelPath;
|
|
164
|
+
detalhes.last_update_date = new Date().toISOString();
|
|
165
|
+
fs.writeFileSync(detalhesPath, JSON.stringify(detalhes, null, 2), { encoding: "utf-8" });
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
console.error("moveDecision: failed to update Detalhes.json:", err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
writeDocumentEvent({
|
|
172
|
+
source: "Juris",
|
|
173
|
+
date: new Date().toISOString(),
|
|
174
|
+
uuid: currentDoc.UUID,
|
|
175
|
+
event: "move",
|
|
176
|
+
old_path: oldPath,
|
|
177
|
+
new_path: newPath,
|
|
178
|
+
changes: {
|
|
179
|
+
...(areaChanged ? { Área: { from: currentDoc.Área?.Show, to: newArea.Show } } : {}),
|
|
180
|
+
...(dataChanged ? { Data: { from: currentDoc.Data, to: newData } } : {}),
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
67
184
|
/** @deprecated use loadDocumentFile(doc, "nlp") instead */
|
|
68
185
|
export function loadNlpDocument(jurisprudencia_document) {
|
|
69
186
|
return loadDocumentFile(jurisprudencia_document, "nlp");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { FilesystemDocument, FilesystemUpdate, SupportedUpdateSources } from "./types.js";
|
|
1
|
+
import { DocumentUpdateEvent, FilesystemDocument, FilesystemUpdate, SupportedUpdateSources } from "./types.js";
|
|
2
2
|
export declare function logDocumentProcessingError(update: FilesystemUpdate, err: string): void;
|
|
3
3
|
export declare function addFileToUpdate(update: FilesystemUpdate, filesystem_document: FilesystemDocument): void;
|
|
4
4
|
export declare function writeFilesystemUpdate(update: FilesystemUpdate, source: SupportedUpdateSources): void;
|
|
5
|
+
export declare function writeDocumentEvent(event: DocumentUpdateEvent): void;
|
|
5
6
|
export declare function loadLastFilesystemUpdate(source: SupportedUpdateSources): FilesystemUpdate;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import { SOURCE_TO_PATH } from "./types.js";
|
|
3
|
+
import { ALL_UPDATE_DIR, SOURCE_TO_PATH } from "./types.js";
|
|
4
4
|
export function logDocumentProcessingError(update, err) {
|
|
5
5
|
update.file_errors.push(err);
|
|
6
6
|
}
|
|
@@ -20,14 +20,26 @@ export function addFileToUpdate(update, filesystem_document) {
|
|
|
20
20
|
export function writeFilesystemUpdate(update, source) {
|
|
21
21
|
update.date_end = new Date();
|
|
22
22
|
let log_path = SOURCE_TO_PATH[source];
|
|
23
|
+
const timestamp = formatUpdateDate(update.date_end);
|
|
23
24
|
fs.mkdirSync(log_path, { recursive: true });
|
|
24
|
-
const updates_file_path = `${log_path}/log_${
|
|
25
|
-
const drive_dir_path = `${log_path}/All`;
|
|
26
|
-
fs.mkdirSync(drive_dir_path, { recursive: true });
|
|
27
|
-
const drive_file_path = `${drive_dir_path}/log_${formatUpdateDate(update.date_end)}.json`;
|
|
25
|
+
const updates_file_path = `${log_path}/log_${timestamp}.json`;
|
|
28
26
|
removeOldUpdate(log_path);
|
|
29
|
-
fs.writeFileSync(drive_file_path, JSON.stringify(update, null, 2), { encoding: "utf-8" });
|
|
30
27
|
fs.writeFileSync(updates_file_path, JSON.stringify(update, null, 2), { encoding: "utf-8" });
|
|
28
|
+
// Write to global All dir (never deleted — full history of all sources)
|
|
29
|
+
fs.mkdirSync(ALL_UPDATE_DIR, { recursive: true });
|
|
30
|
+
fs.writeFileSync(`${ALL_UPDATE_DIR}/log_${source.replace(/[^a-zA-Z0-9]/g, "_")}_${timestamp}.json`, JSON.stringify(update, null, 2), { encoding: "utf-8" });
|
|
31
|
+
}
|
|
32
|
+
export function writeDocumentEvent(event) {
|
|
33
|
+
const timestamp = formatUpdateDate(new Date(event.date));
|
|
34
|
+
const filename = `event_${event.event}_${event.uuid}_${timestamp}.json`;
|
|
35
|
+
const content = JSON.stringify(event, null, 2);
|
|
36
|
+
// Write to source-specific dir (e.g. Updates/Juris/) — keeps all individual events
|
|
37
|
+
const sourceDir = SOURCE_TO_PATH[event.source];
|
|
38
|
+
fs.mkdirSync(sourceDir, { recursive: true });
|
|
39
|
+
fs.writeFileSync(path.join(sourceDir, filename), content, { encoding: "utf-8" });
|
|
40
|
+
// Write to global All dir (full cross-source history)
|
|
41
|
+
fs.mkdirSync(ALL_UPDATE_DIR, { recursive: true });
|
|
42
|
+
fs.writeFileSync(path.join(ALL_UPDATE_DIR, filename), content, { encoding: "utf-8" });
|
|
31
43
|
}
|
|
32
44
|
export function loadLastFilesystemUpdate(source) {
|
|
33
45
|
const empty_update = {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const UpdateSources: readonly ["STJ (Sharepoint)", "DGSI"];
|
|
1
|
+
export declare const UpdateSources: readonly ["STJ (Sharepoint)", "DGSI", "Juris"];
|
|
2
2
|
export type SupportedUpdateSources = typeof UpdateSources[number];
|
|
3
3
|
export declare const ROOT_PATH: string;
|
|
4
4
|
export declare const FILESYSTEM_PATH = "/FileSystem";
|
|
@@ -8,8 +8,12 @@ export declare const ORIGINAL_NAME = "Original";
|
|
|
8
8
|
export declare const LOGS_PATH = "/Updates";
|
|
9
9
|
export declare const SHAREPOINT_LOGS_PATH = "/Updates/Sharepoint";
|
|
10
10
|
export declare const DGSI_LOGS_PATH = "/Updates/DGSI";
|
|
11
|
+
export declare const JURIS_LOGS_PATH = "/Updates/Juris";
|
|
12
|
+
export declare const ALL_LOGS_PATH = "/Updates/All";
|
|
11
13
|
export declare const SHAREPOINT_UPDATE_DIR: string;
|
|
12
14
|
export declare const DGSI_UPDATE_DIR: string;
|
|
15
|
+
export declare const JURIS_UPDATE_DIR: string;
|
|
16
|
+
export declare const ALL_UPDATE_DIR: string;
|
|
13
17
|
export declare const SOURCE_TO_PATH: Record<SupportedUpdateSources, string>;
|
|
14
18
|
export type FilesystemUpdate = {
|
|
15
19
|
updateSource: SupportedUpdateSources;
|
|
@@ -63,3 +67,12 @@ export type FilesystemDocument = {
|
|
|
63
67
|
content?: ContentType[];
|
|
64
68
|
};
|
|
65
69
|
export declare function isSupportedExtension(ext: string): ext is Supported_Content_Extensions;
|
|
70
|
+
export type DocumentUpdateEvent = {
|
|
71
|
+
source: SupportedUpdateSources;
|
|
72
|
+
date: string;
|
|
73
|
+
uuid: string;
|
|
74
|
+
event: "move" | "anonimize" | "edit";
|
|
75
|
+
old_path?: string;
|
|
76
|
+
new_path?: string;
|
|
77
|
+
changes?: Record<string, unknown>;
|
|
78
|
+
};
|
package/dist/types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const UpdateSources = ["STJ (Sharepoint)", "DGSI"];
|
|
1
|
+
export const UpdateSources = ["STJ (Sharepoint)", "DGSI", "Juris"];
|
|
2
2
|
import dotenv from 'dotenv';
|
|
3
3
|
dotenv.config();
|
|
4
4
|
export const ROOT_PATH = process.env['LOCAL_ROOT'] || 'results';
|
|
@@ -9,9 +9,13 @@ export const ORIGINAL_NAME = "Original";
|
|
|
9
9
|
export const LOGS_PATH = "/Updates";
|
|
10
10
|
export const SHAREPOINT_LOGS_PATH = `${LOGS_PATH}/Sharepoint`;
|
|
11
11
|
export const DGSI_LOGS_PATH = `${LOGS_PATH}/DGSI`;
|
|
12
|
+
export const JURIS_LOGS_PATH = `${LOGS_PATH}/Juris`;
|
|
13
|
+
export const ALL_LOGS_PATH = `${LOGS_PATH}/All`;
|
|
12
14
|
export const SHAREPOINT_UPDATE_DIR = `${ROOT_PATH}${SHAREPOINT_LOGS_PATH}`;
|
|
13
15
|
export const DGSI_UPDATE_DIR = `${ROOT_PATH}${DGSI_LOGS_PATH}`;
|
|
14
|
-
export const
|
|
16
|
+
export const JURIS_UPDATE_DIR = `${ROOT_PATH}${JURIS_LOGS_PATH}`;
|
|
17
|
+
export const ALL_UPDATE_DIR = `${ROOT_PATH}${ALL_LOGS_PATH}`;
|
|
18
|
+
export const SOURCE_TO_PATH = { "STJ (Sharepoint)": SHAREPOINT_UPDATE_DIR, "DGSI": DGSI_UPDATE_DIR, "Juris": JURIS_UPDATE_DIR };
|
|
15
19
|
export const SUPPORTED_EXTENSIONS = ["txt", "pdf", "docx", "html", "json"];
|
|
16
20
|
export function isSupportedExtension(ext) {
|
|
17
21
|
return SUPPORTED_EXTENSIONS.includes(ext);
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { JurisprudenciaDocument, PartialJurisprudenciaDocument } from "@stjiris/jurisprudencia-document";
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
2
3
|
import fs from "fs";
|
|
3
4
|
import mammoth from "mammoth";
|
|
4
|
-
import
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { ContentType, Date_Area_Section, DETAILS_NAME, DocumentUpdateEvent, FILESYSTEM_PATH, FilesystemDocument, ORIGINAL_NAME, Retrievable_Metadata, ROOT_PATH, SHAREPOINT_COPY_PATH, Sharepoint_Metadata, SupportedUpdateSources } from "./types.js";
|
|
7
|
+
import { writeDocumentEvent } from "./filesystemUpdateMethods.js";
|
|
5
8
|
import { DescritorOficial } from "./descritores.js";
|
|
6
9
|
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
|
|
7
10
|
|
|
@@ -78,6 +81,135 @@ export function loadDocumentFile(doc: PartialJurisprudenciaDocument, type: Docum
|
|
|
78
81
|
return fs.readFileSync(`${dirPath}/${ORIGINAL_NAME}.${type}`);
|
|
79
82
|
}
|
|
80
83
|
|
|
84
|
+
export const ANONIMIZADO_NAME = "Anonimizado";
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Converts the anonymized HTML text (and optionally summary) to DOCX and PDF files
|
|
88
|
+
* saved as Anonimizado.docx / Anonimizado.pdf in the document's filesystem directory.
|
|
89
|
+
* Requires pandoc (and xelatex for PDF) to be available on PATH.
|
|
90
|
+
*/
|
|
91
|
+
export async function saveAnonimizedDocument(
|
|
92
|
+
doc: PartialJurisprudenciaDocument,
|
|
93
|
+
textoHtml: string,
|
|
94
|
+
sumarioHtml?: string
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
const dirPath = `${ROOT_PATH}${FILESYSTEM_PATH}${generateFilePath(doc)}`;
|
|
97
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
98
|
+
|
|
99
|
+
const bodyHtml = sumarioHtml
|
|
100
|
+
? `<h2>Sumário</h2>${sumarioHtml}<h2>Texto</h2>${textoHtml}`
|
|
101
|
+
: textoHtml;
|
|
102
|
+
|
|
103
|
+
const fullHtml = `<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>${bodyHtml}</body></html>`;
|
|
104
|
+
|
|
105
|
+
const tmpHtml = path.join(dirPath, `_anonimizado_tmp.html`);
|
|
106
|
+
fs.writeFileSync(tmpHtml, fullHtml, { encoding: "utf-8" });
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const docxPath = path.join(dirPath, `${ANONIMIZADO_NAME}.docx`);
|
|
110
|
+
const pdfPath = path.join(dirPath, `${ANONIMIZADO_NAME}.pdf`);
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
execFileSync("pandoc", [tmpHtml, "-o", docxPath]);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
console.error("saveAnonimizedDocument: failed to generate DOCX:", err);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
execFileSync("pandoc", [tmpHtml, "--pdf-engine=xelatex", "-o", pdfPath]);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
console.error("saveAnonimizedDocument: failed to generate PDF:", err);
|
|
122
|
+
}
|
|
123
|
+
} finally {
|
|
124
|
+
try { fs.unlinkSync(tmpHtml); } catch { /* ignore */ }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (doc.UUID) {
|
|
128
|
+
writeDocumentEvent({
|
|
129
|
+
source: "Juris",
|
|
130
|
+
date: new Date().toISOString(),
|
|
131
|
+
uuid: doc.UUID,
|
|
132
|
+
event: "anonimize",
|
|
133
|
+
new_path: dirPath,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Moves the filesystem directory of a document when Área or Data changes.
|
|
140
|
+
* Must be called BEFORE updating the document in Elasticsearch.
|
|
141
|
+
* Also updates Detalhes.json inside the directory and writes a Juris update event.
|
|
142
|
+
*/
|
|
143
|
+
export function moveDecision(
|
|
144
|
+
currentDoc: PartialJurisprudenciaDocument,
|
|
145
|
+
updateObject: PartialJurisprudenciaDocument
|
|
146
|
+
): void {
|
|
147
|
+
if (!currentDoc.UUID) return;
|
|
148
|
+
|
|
149
|
+
const newArea = updateObject.Área as any;
|
|
150
|
+
const newData = updateObject.Data;
|
|
151
|
+
|
|
152
|
+
const areaChanged = newArea?.Show && JSON.stringify(newArea.Show) !== JSON.stringify((currentDoc as any).Área?.Show);
|
|
153
|
+
const dataChanged = newData && newData !== currentDoc.Data;
|
|
154
|
+
|
|
155
|
+
if (!areaChanged && !dataChanged) return;
|
|
156
|
+
|
|
157
|
+
let oldRelPath: string;
|
|
158
|
+
try {
|
|
159
|
+
oldRelPath = generateFilePath(currentDoc);
|
|
160
|
+
} catch {
|
|
161
|
+
return; // doc missing required metadata
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const oldPath = `${ROOT_PATH}${FILESYSTEM_PATH}${oldRelPath}`;
|
|
165
|
+
if (!fs.existsSync(oldPath)) return;
|
|
166
|
+
|
|
167
|
+
const mergedDoc = {
|
|
168
|
+
...currentDoc,
|
|
169
|
+
...(areaChanged ? { Área: newArea } : {}),
|
|
170
|
+
...(dataChanged ? { Data: newData } : {}),
|
|
171
|
+
} as PartialJurisprudenciaDocument;
|
|
172
|
+
|
|
173
|
+
let newRelPath: string;
|
|
174
|
+
try {
|
|
175
|
+
newRelPath = generateFilePath(mergedDoc);
|
|
176
|
+
} catch {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const newPath = `${ROOT_PATH}${FILESYSTEM_PATH}${newRelPath}`;
|
|
181
|
+
if (oldPath === newPath) return;
|
|
182
|
+
|
|
183
|
+
fs.mkdirSync(path.dirname(newPath), { recursive: true });
|
|
184
|
+
fs.renameSync(oldPath, newPath);
|
|
185
|
+
|
|
186
|
+
// Update Detalhes.json with the new path
|
|
187
|
+
const detalhesPath = path.join(newPath, `${DETAILS_NAME}.json`);
|
|
188
|
+
if (fs.existsSync(detalhesPath)) {
|
|
189
|
+
try {
|
|
190
|
+
const detalhes = JSON.parse(fs.readFileSync(detalhesPath, "utf-8"));
|
|
191
|
+
detalhes.file_path = newRelPath;
|
|
192
|
+
detalhes.last_update_date = new Date().toISOString();
|
|
193
|
+
fs.writeFileSync(detalhesPath, JSON.stringify(detalhes, null, 2), { encoding: "utf-8" });
|
|
194
|
+
} catch (err) {
|
|
195
|
+
console.error("moveDecision: failed to update Detalhes.json:", err);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
writeDocumentEvent({
|
|
200
|
+
source: "Juris",
|
|
201
|
+
date: new Date().toISOString(),
|
|
202
|
+
uuid: currentDoc.UUID,
|
|
203
|
+
event: "move",
|
|
204
|
+
old_path: oldPath,
|
|
205
|
+
new_path: newPath,
|
|
206
|
+
changes: {
|
|
207
|
+
...(areaChanged ? { Área: { from: (currentDoc as any).Área?.Show, to: newArea.Show } } : {}),
|
|
208
|
+
...(dataChanged ? { Data: { from: currentDoc.Data, to: newData } } : {}),
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
81
213
|
/** @deprecated use loadDocumentFile(doc, "nlp") instead */
|
|
82
214
|
export function loadNlpDocument(jurisprudencia_document: JurisprudenciaDocument): string {
|
|
83
215
|
return loadDocumentFile(jurisprudencia_document, "nlp");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import { FilesystemDocument, FilesystemUpdate,
|
|
3
|
+
import { ALL_UPDATE_DIR, DocumentUpdateEvent, FilesystemDocument, FilesystemUpdate, SOURCE_TO_PATH, SupportedUpdateSources } from "./types.js";
|
|
4
4
|
|
|
5
5
|
export function logDocumentProcessingError(update: FilesystemUpdate, err: string) {
|
|
6
6
|
update.file_errors.push(err);
|
|
@@ -26,18 +26,32 @@ export function writeFilesystemUpdate(update: FilesystemUpdate, source: Supporte
|
|
|
26
26
|
update.date_end = new Date();
|
|
27
27
|
|
|
28
28
|
let log_path: string = SOURCE_TO_PATH[source];
|
|
29
|
+
const timestamp = formatUpdateDate(update.date_end);
|
|
29
30
|
|
|
30
31
|
fs.mkdirSync(log_path, { recursive: true });
|
|
31
|
-
const updates_file_path = `${log_path}/log_${
|
|
32
|
-
|
|
33
|
-
const drive_dir_path = `${log_path}/All`
|
|
34
|
-
fs.mkdirSync(drive_dir_path, { recursive: true });
|
|
35
|
-
const drive_file_path = `${drive_dir_path}/log_${formatUpdateDate(update.date_end)}.json`;
|
|
32
|
+
const updates_file_path = `${log_path}/log_${timestamp}.json`;
|
|
36
33
|
|
|
37
34
|
removeOldUpdate(log_path);
|
|
38
|
-
|
|
39
|
-
fs.writeFileSync(drive_file_path, JSON.stringify(update, null, 2), { encoding: "utf-8" });
|
|
40
35
|
fs.writeFileSync(updates_file_path, JSON.stringify(update, null, 2), { encoding: "utf-8" });
|
|
36
|
+
|
|
37
|
+
// Write to global All dir (never deleted — full history of all sources)
|
|
38
|
+
fs.mkdirSync(ALL_UPDATE_DIR, { recursive: true });
|
|
39
|
+
fs.writeFileSync(`${ALL_UPDATE_DIR}/log_${source.replace(/[^a-zA-Z0-9]/g, "_")}_${timestamp}.json`, JSON.stringify(update, null, 2), { encoding: "utf-8" });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function writeDocumentEvent(event: DocumentUpdateEvent): void {
|
|
43
|
+
const timestamp = formatUpdateDate(new Date(event.date));
|
|
44
|
+
const filename = `event_${event.event}_${event.uuid}_${timestamp}.json`;
|
|
45
|
+
const content = JSON.stringify(event, null, 2);
|
|
46
|
+
|
|
47
|
+
// Write to source-specific dir (e.g. Updates/Juris/) — keeps all individual events
|
|
48
|
+
const sourceDir = SOURCE_TO_PATH[event.source];
|
|
49
|
+
fs.mkdirSync(sourceDir, { recursive: true });
|
|
50
|
+
fs.writeFileSync(path.join(sourceDir, filename), content, { encoding: "utf-8" });
|
|
51
|
+
|
|
52
|
+
// Write to global All dir (full cross-source history)
|
|
53
|
+
fs.mkdirSync(ALL_UPDATE_DIR, { recursive: true });
|
|
54
|
+
fs.writeFileSync(path.join(ALL_UPDATE_DIR, filename), content, { encoding: "utf-8" });
|
|
41
55
|
}
|
|
42
56
|
|
|
43
57
|
export function loadLastFilesystemUpdate(source: SupportedUpdateSources): FilesystemUpdate {
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
export const UpdateSources = ["STJ (Sharepoint)", "DGSI"] as const;
|
|
2
|
+
export const UpdateSources = ["STJ (Sharepoint)", "DGSI", "Juris"] as const;
|
|
3
3
|
export type SupportedUpdateSources = typeof UpdateSources[number];
|
|
4
4
|
import dotenv from 'dotenv';
|
|
5
5
|
|
|
@@ -13,11 +13,15 @@ export const LOGS_PATH = "/Updates";
|
|
|
13
13
|
|
|
14
14
|
export const SHAREPOINT_LOGS_PATH = `${LOGS_PATH}/Sharepoint`;
|
|
15
15
|
export const DGSI_LOGS_PATH = `${LOGS_PATH}/DGSI`;
|
|
16
|
+
export const JURIS_LOGS_PATH = `${LOGS_PATH}/Juris`;
|
|
17
|
+
export const ALL_LOGS_PATH = `${LOGS_PATH}/All`;
|
|
16
18
|
|
|
17
19
|
export const SHAREPOINT_UPDATE_DIR = `${ROOT_PATH}${SHAREPOINT_LOGS_PATH}`;
|
|
18
20
|
export const DGSI_UPDATE_DIR = `${ROOT_PATH}${DGSI_LOGS_PATH}`;
|
|
21
|
+
export const JURIS_UPDATE_DIR = `${ROOT_PATH}${JURIS_LOGS_PATH}`;
|
|
22
|
+
export const ALL_UPDATE_DIR = `${ROOT_PATH}${ALL_LOGS_PATH}`;
|
|
19
23
|
|
|
20
|
-
export const SOURCE_TO_PATH: Record<SupportedUpdateSources, string> = { "STJ (Sharepoint)": SHAREPOINT_UPDATE_DIR, "DGSI": DGSI_UPDATE_DIR };
|
|
24
|
+
export const SOURCE_TO_PATH: Record<SupportedUpdateSources, string> = { "STJ (Sharepoint)": SHAREPOINT_UPDATE_DIR, "DGSI": DGSI_UPDATE_DIR, "Juris": JURIS_UPDATE_DIR };
|
|
21
25
|
|
|
22
26
|
export type FilesystemUpdate = {
|
|
23
27
|
updateSource: SupportedUpdateSources,
|
|
@@ -65,3 +69,13 @@ export type FilesystemDocument = {
|
|
|
65
69
|
export function isSupportedExtension(ext: string): ext is Supported_Content_Extensions {
|
|
66
70
|
return (SUPPORTED_EXTENSIONS as readonly string[]).includes(ext);
|
|
67
71
|
};
|
|
72
|
+
|
|
73
|
+
export type DocumentUpdateEvent = {
|
|
74
|
+
source: SupportedUpdateSources,
|
|
75
|
+
date: string,
|
|
76
|
+
uuid: string,
|
|
77
|
+
event: "move" | "anonimize" | "edit",
|
|
78
|
+
old_path?: string,
|
|
79
|
+
new_path?: string,
|
|
80
|
+
changes?: Record<string, unknown>
|
|
81
|
+
};
|