hybridtm 0.7.1 → 0.9.0

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 (84) hide show
  1. package/README.md +32 -11
  2. package/dist/backupHandler.d.ts +60 -0
  3. package/dist/backupHandler.js +335 -0
  4. package/dist/backupHandler.js.map +1 -0
  5. package/dist/backupReader.d.ts +26 -0
  6. package/dist/backupReader.js +55 -0
  7. package/dist/backupReader.js.map +1 -0
  8. package/dist/batchImporter.d.ts +1 -1
  9. package/dist/batchImporter.js +4 -3
  10. package/dist/batchImporter.js.map +1 -1
  11. package/dist/cli/backupCommand.d.ts +15 -0
  12. package/dist/cli/backupCommand.js +49 -0
  13. package/dist/cli/backupCommand.js.map +1 -0
  14. package/dist/cli/cliUtils.d.ts +2 -1
  15. package/dist/cli/cliUtils.js +23 -10
  16. package/dist/cli/cliUtils.js.map +1 -1
  17. package/dist/cli/createCommand.d.ts +5 -3
  18. package/dist/cli/createCommand.js +33 -28
  19. package/dist/cli/createCommand.js.map +1 -1
  20. package/dist/cli/hybridtmCli.d.ts +1 -1
  21. package/dist/cli/hybridtmCli.js +35 -15
  22. package/dist/cli/hybridtmCli.js.map +1 -1
  23. package/dist/cli/importCommand.d.ts +11 -3
  24. package/dist/cli/importCommand.js +75 -78
  25. package/dist/cli/importCommand.js.map +1 -1
  26. package/dist/cli/matchCommand.d.ts +17 -3
  27. package/dist/cli/matchCommand.js +99 -129
  28. package/dist/cli/matchCommand.js.map +1 -1
  29. package/dist/cli/registryCommands.d.ts +8 -5
  30. package/dist/cli/registryCommands.js +63 -61
  31. package/dist/cli/registryCommands.js.map +1 -1
  32. package/dist/cli/restoreCommand.d.ts +18 -0
  33. package/dist/cli/restoreCommand.js +100 -0
  34. package/dist/cli/restoreCommand.js.map +1 -0
  35. package/dist/cli/serveCommand.d.ts +17 -0
  36. package/dist/cli/serveCommand.js +87 -0
  37. package/dist/cli/serveCommand.js.map +1 -0
  38. package/dist/cli/stopCommand.d.ts +15 -0
  39. package/dist/cli/stopCommand.js +73 -0
  40. package/dist/cli/stopCommand.js.map +1 -0
  41. package/dist/hybridtm.d.ts +11 -4
  42. package/dist/hybridtm.js +308 -89
  43. package/dist/hybridtm.js.map +1 -1
  44. package/dist/hybridtmFactory.d.ts +1 -1
  45. package/dist/hybridtmFactory.js +6 -1
  46. package/dist/hybridtmFactory.js.map +1 -1
  47. package/dist/importOptions.d.ts +5 -5
  48. package/dist/importOptions.js +11 -11
  49. package/dist/importOptions.js.map +1 -1
  50. package/dist/index.d.ts +4 -1
  51. package/dist/index.js +4 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/langEntry.d.ts +1 -1
  54. package/dist/langEntry.js +1 -1
  55. package/dist/match.d.ts +1 -1
  56. package/dist/match.js +1 -1
  57. package/dist/matchQuality.d.ts +1 -1
  58. package/dist/matchQuality.js +1 -1
  59. package/dist/pendingEntry.d.ts +1 -1
  60. package/dist/pendingEntry.js +1 -1
  61. package/dist/searchFilters.d.ts +1 -1
  62. package/dist/searchFilters.js +1 -1
  63. package/dist/server/hybridtmServer.d.ts +40 -0
  64. package/dist/server/hybridtmServer.js +527 -0
  65. package/dist/server/hybridtmServer.js.map +1 -0
  66. package/dist/server/hybridtmServerMain.d.ts +12 -0
  67. package/dist/server/hybridtmServerMain.js +18 -0
  68. package/dist/server/hybridtmServerMain.js.map +1 -0
  69. package/dist/tmxHandler.d.ts +2 -1
  70. package/dist/tmxHandler.js +13 -7
  71. package/dist/tmxHandler.js.map +1 -1
  72. package/dist/tmxReader.d.ts +1 -1
  73. package/dist/tmxReader.js +4 -4
  74. package/dist/tmxReader.js.map +1 -1
  75. package/dist/utils.d.ts +28 -2
  76. package/dist/utils.js +163 -2
  77. package/dist/utils.js.map +1 -1
  78. package/dist/xliffHandler.d.ts +1 -2
  79. package/dist/xliffHandler.js +34 -30
  80. package/dist/xliffHandler.js.map +1 -1
  81. package/dist/xliffReader.d.ts +1 -1
  82. package/dist/xliffReader.js +4 -4
  83. package/dist/xliffReader.js.map +1 -1
  84. package/package.json +5 -4
package/README.md CHANGED
@@ -1,15 +1,17 @@
1
1
  # HybridTM
2
2
 
3
- HybridTM is a semantic translation memory engine that stores bilingual content in LanceDB and scores matches by combining semantic embeddings (Xenova/Transformers.js) with the built-in MatchQuality fuzzy metric.
3
+ HybridTM is a semantic translation memory engine that stores bilingual content in LanceDB and scores matches by combining semantic embeddings (Hugging Face Transformers.js) with the built-in MatchQuality fuzzy metric.
4
4
 
5
5
  ## Highlights
6
6
 
7
7
  - Imports XLIFF 2.x, TMX 1.4b, and SDLTM files, preserving metadata, notes, and custom properties
8
- - Generates semantic vectors with any Xenova-compatible text model (default: `HybridTM.QUALITY_MODEL`, LaBSE)
8
+ - Generates semantic vectors with any Transformers.js-compatible text model — ships three ready-to-use presets (`compact`/`standard`/`large`, default: `HybridTM.LARGE_MODEL`) plus support for bringing your own model id (see [Choosing an embedding model](#choosing-an-embedding-model))
9
9
  - Provides `semanticTranslationSearch`, `semanticSearch`, and `concordanceSearch` APIs with metadata-aware filtering
10
10
  - Streams data into LanceDB through a JSONL-based batch importer to keep memory usage predictable
11
11
  - Prevents duplicate segments by rewriting entries with deterministic IDs (`fileId:unitId:segmentIndex:lang`)
12
- - Ships a `hybridtm` command-line tool for creating instances, importing files, and enriching XLIFF files with TM match candidates from the shell
12
+ - Backs up any instance to a single format-agnostic XML file and restores it into an existing or brand-new instance, optionally under a different embedding model
13
+ - Ships a `hybridtm` command-line tool for creating instances, importing files, backing up/restoring data, and enriching XLIFF files with TM match candidates from the shell
14
+ - Runs as a JSON-over-HTTP server too (`hybridtm serve`, or embed `HybridTMServer` directly), for CAT tool and editor integrations that want to keep an instance and its loaded model open across many requests, with ticketed handling for long-running imports and matches, and a `storeXliffUnit` command for persisting a single confirmed unit as the user works
13
15
 
14
16
  Models download automatically the first time you initialize an instance and are cached in the standard Hugging Face directory.
15
17
 
@@ -36,7 +38,7 @@ const DB_PATH = path.resolve('.hybridtm', INSTANCE_NAME + '.lancedb');
36
38
 
37
39
  function getOrCreateTM(): HybridTM {
38
40
  return HybridTMFactory.getInstance(INSTANCE_NAME)
39
- ?? HybridTMFactory.createInstance(INSTANCE_NAME, DB_PATH, HybridTM.QUALITY_MODEL);
41
+ ?? HybridTMFactory.createInstance(INSTANCE_NAME, DB_PATH, HybridTM.LARGE_MODEL);
40
42
  }
41
43
 
42
44
  async function main(): Promise<void> {
@@ -73,6 +75,25 @@ await tm.importSDLTM('./translations/legacy.sdltm');
73
75
 
74
76
  `semanticTranslationSearch` automatically pairs every source hit with its matching target segment (same `fileId`, `unitId`, and `segmentIndex`), making the output ready for CAT integrations.
75
77
 
78
+ ## Choosing an embedding model
79
+
80
+ HybridTM ships three ready-to-use presets, but it is **not limited to them** — the `modelName` constructor argument (and the CLI's `-model` flag) accepts *any* Hugging Face `feature-extraction`-compatible model id, so you can bring your own (e.g. `-model intfloat/multilingual-e5-large`) if none of the presets fit.
81
+
82
+ | Preset | Constant | Model | Dimensions |
83
+ | --- | --- | --- | --- |
84
+ | `compact` | `HybridTM.COMPACT_MODEL` | `Xenova/multilingual-e5-small` | 384 |
85
+ | `standard` | `HybridTM.STANDARD_MODEL` | `Xenova/paraphrase-multilingual-MiniLM-L12-v2` | 384 |
86
+ | `large` (default) | `HybridTM.LARGE_MODEL` | `onnx-community/gte-multilingual-base` | 768 |
87
+
88
+ The names describe model **size/footprint**, not a quality ranking — an internal benchmark across English, Spanish, Japanese, and Finnish content found no preset winning on every language: `standard` led on English/Spanish/Japanese while matching or beating `large` on accuracy, `large` was the clear leader specifically on Finnish (a highly inflected language), and `compact` had the smallest footprint but never won outright on accuracy in that test. This is because HybridTM's translation matching pairs source and target segments by `fileId`/`unitId`/`segmentIndex` structure, not by comparing embeddings across languages — so model choice mostly affects how well a model clusters semantically similar text *within* the language you search in, and that can vary a lot by language family and script.
89
+
90
+ Practical guidance:
91
+
92
+ - **Unsure, or mostly Western European languages?** Start with `standard` — smallest footprint tier, and it matched or beat `large` in our tests while being faster.
93
+ - **Morphologically rich languages** (e.g. Finnish, other Uralic or heavily case-inflected languages)? `large` is worth its extra latency and storage — it was the clear leader there.
94
+ - **Memory/disk is the binding constraint?** `compact` is the smallest option, but treat it as a deliberate tradeoff, not a safe default — it trailed on accuracy in every language we tested.
95
+ - Our benchmark was small (dozens of queries per language, a handful of language pairs) — informative, not exhaustive. If model choice matters a lot for your deployment, benchmark with your own representative content and target languages using `semanticSearch`/`semanticTranslationSearch` before committing, especially for languages we didn't test.
96
+
76
97
  ## Command-line interface
77
98
 
78
99
  Installing HybridTM globally also adds a `hybridtm` command:
@@ -80,9 +101,11 @@ Installing HybridTM globally also adds a `hybridtm` command:
80
101
  ```bash
81
102
  npm install -g hybridtm
82
103
 
83
- hybridtm create -name project -path ./project.lancedb
84
- hybridtm import -name project -file ./translations/project.xlf
85
- hybridtm match -name project -file ./new-content.xlf -output ./new-content.matches.xlf
104
+ hybridtm create -name project -path ./project.lancedb
105
+ hybridtm import -name project -file ./translations/project.xlf
106
+ hybridtm match -name project -file ./new-content.xlf -similarity 60 -output ./new-content.matches.xlf
107
+ hybridtm backup -name project -file ./project-backup.xml
108
+ hybridtm restore -file ./project-backup.xml -name project
86
109
  hybridtm list
87
110
  hybridtm remove -name project
88
111
  ```
@@ -99,6 +122,8 @@ see [05 · Command-Line Interface](docs/05-command-line-interface.md).
99
122
  - [03 · Search and Filtering](docs/03-search-and-filtering.md)
100
123
  - [04 · Sample Scenarios](docs/04-sample-scenarios.md)
101
124
  - [05 · Command-Line Interface](docs/05-command-line-interface.md)
125
+ - [06 · Backup and Restore](docs/06-backup-and-restore.md)
126
+ - [07 · HTTP Server](docs/07-http-server.md)
102
127
 
103
128
  Each guide is short and task-oriented, so you can jump directly to the workflow you need.
104
129
 
@@ -125,14 +150,10 @@ If you copy `samples/` elsewhere, update `samples/package.json` so the `hybridtm
125
150
  - `dist/` – compiled JavaScript and declarations (`npm run build`)
126
151
  - `docs/` – task-focused tutorials referenced above
127
152
  - `samples/` – standalone TypeScript project with runnable workflows
128
- - `models/` – local cache for pre-downloaded Xenova models (optional)
129
153
 
130
154
  ## Development
131
155
 
132
156
  - `npm run build` – compile TypeScript to `dist/`
133
- - `node dist/tmxtest.js` and `node dist/xlifftest.js` – regression checks for the TMX and XLIFF importers (run after building)
134
-
135
- Contributions should include unit or integration coverage when you touch importer or search logic. Use `HybridTMFactory.removeInstance(name)` to clean up any throwaway databases you create during manual tests.
136
157
 
137
158
  ## License
138
159
 
@@ -0,0 +1,60 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse Public License v1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { Catalog, ContentHandler, Grammar, XMLAttribute } from "typesxml";
13
+ export declare class BackupHandler implements ContentHandler {
14
+ private writeStream;
15
+ private readonly completionPromise;
16
+ private entryCount;
17
+ private name;
18
+ private model;
19
+ private date;
20
+ private inEntry;
21
+ private stack;
22
+ private entryChildren;
23
+ private entryLanguage;
24
+ private entryFileId;
25
+ private entryOriginal;
26
+ private entryUnitId;
27
+ private entrySegmentIndex;
28
+ private entrySegmentCount;
29
+ constructor(tempFilePath: string);
30
+ getEntryCount(): number;
31
+ waitForCompletion(): Promise<void>;
32
+ getBackupName(): string;
33
+ getBackupModel(): string;
34
+ getBackupDate(): string;
35
+ setGrammar(grammar: Grammar | undefined): void;
36
+ getGrammar(): Grammar | undefined;
37
+ initialize(): void;
38
+ setCatalog(catalog: Catalog): void;
39
+ startDocument(): void;
40
+ endDocument(): void;
41
+ xmlDeclaration(version: string, encoding: string, standalone: string | undefined): void;
42
+ startElement(name: string, atts: Array<XMLAttribute>): void;
43
+ endElement(name: string): void;
44
+ internalSubset(declaration: string): void;
45
+ characters(ch: string): void;
46
+ ignorableWhitespace(ch: string): void;
47
+ comment(ch: string): void;
48
+ processingInstruction(target: string, data: string): void;
49
+ startCDATA(): void;
50
+ endCDATA(): void;
51
+ startDTD(name: string, publicId: string, systemId: string): void;
52
+ endDTD(): void;
53
+ skippedEntity(name: string): void;
54
+ getCurrentText(): string;
55
+ private emitEntry;
56
+ private parseMetadataElement;
57
+ private parseSegmentElement;
58
+ private parseOptionalNumber;
59
+ private parseNumber;
60
+ }
@@ -0,0 +1,335 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse Public License v1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { createWriteStream } from "node:fs";
13
+ import { XMLElement } from "typesxml";
14
+ export class BackupHandler {
15
+ writeStream;
16
+ completionPromise;
17
+ entryCount = 0;
18
+ name = '';
19
+ model = '';
20
+ date = '';
21
+ inEntry = false;
22
+ stack = [];
23
+ entryChildren = [];
24
+ entryLanguage = '';
25
+ entryFileId = '';
26
+ entryOriginal = '';
27
+ entryUnitId = '';
28
+ entrySegmentIndex = 0;
29
+ entrySegmentCount = 1;
30
+ constructor(tempFilePath) {
31
+ this.writeStream = createWriteStream(tempFilePath, { encoding: 'utf8' });
32
+ this.completionPromise = new Promise((resolve, reject) => {
33
+ this.writeStream.once('finish', resolve);
34
+ this.writeStream.once('error', reject);
35
+ });
36
+ }
37
+ getEntryCount() {
38
+ return this.entryCount;
39
+ }
40
+ waitForCompletion() {
41
+ return this.completionPromise;
42
+ }
43
+ getBackupName() {
44
+ return this.name;
45
+ }
46
+ getBackupModel() {
47
+ return this.model;
48
+ }
49
+ getBackupDate() {
50
+ return this.date;
51
+ }
52
+ setGrammar(grammar) {
53
+ // do nothing
54
+ }
55
+ getGrammar() {
56
+ return undefined;
57
+ }
58
+ initialize() {
59
+ this.stack = [];
60
+ this.entryChildren = [];
61
+ this.inEntry = false;
62
+ }
63
+ setCatalog(catalog) {
64
+ // do nothing
65
+ }
66
+ startDocument() {
67
+ // do nothing
68
+ }
69
+ endDocument() {
70
+ this.writeStream.end();
71
+ }
72
+ xmlDeclaration(version, encoding, standalone) {
73
+ // do nothing
74
+ }
75
+ startElement(name, atts) {
76
+ if ('backup' === name) {
77
+ const element = new XMLElement(name);
78
+ atts.forEach((att) => element.setAttribute(att));
79
+ this.name = element.getAttribute('name')?.getValue() ?? '';
80
+ this.model = element.getAttribute('model')?.getValue() ?? '';
81
+ this.date = element.getAttribute('date')?.getValue() ?? '';
82
+ return;
83
+ }
84
+ if ('entry' === name) {
85
+ const element = new XMLElement(name);
86
+ atts.forEach((att) => element.setAttribute(att));
87
+ this.inEntry = true;
88
+ this.stack = [];
89
+ this.entryChildren = [];
90
+ this.entryLanguage = element.getAttribute('language')?.getValue() ?? '';
91
+ this.entryFileId = element.getAttribute('fileId')?.getValue() ?? '';
92
+ this.entryOriginal = element.getAttribute('original')?.getValue() ?? '';
93
+ this.entryUnitId = element.getAttribute('unitId')?.getValue() ?? '';
94
+ this.entrySegmentIndex = this.parseNumber(element.getAttribute('segmentIndex')?.getValue(), 0);
95
+ this.entrySegmentCount = this.parseNumber(element.getAttribute('segmentCount')?.getValue(), 1);
96
+ return;
97
+ }
98
+ if (!this.inEntry) {
99
+ return;
100
+ }
101
+ const element = new XMLElement(name);
102
+ atts.forEach((att) => element.setAttribute(att));
103
+ if (this.stack.length > 0) {
104
+ this.stack[this.stack.length - 1].addElement(element);
105
+ }
106
+ this.stack.push(element);
107
+ }
108
+ endElement(name) {
109
+ if ('backup' === name) {
110
+ return;
111
+ }
112
+ if ('entry' === name) {
113
+ this.emitEntry();
114
+ this.inEntry = false;
115
+ this.stack = [];
116
+ this.entryChildren = [];
117
+ return;
118
+ }
119
+ if (!this.inEntry) {
120
+ return;
121
+ }
122
+ const finished = this.stack.pop();
123
+ if (finished && this.stack.length === 0) {
124
+ this.entryChildren.push(finished);
125
+ }
126
+ }
127
+ internalSubset(declaration) {
128
+ // do nothing
129
+ }
130
+ characters(ch) {
131
+ if (!this.inEntry || this.stack.length === 0) {
132
+ return;
133
+ }
134
+ this.stack[this.stack.length - 1].addString(ch);
135
+ }
136
+ ignorableWhitespace(ch) {
137
+ this.characters(ch);
138
+ }
139
+ comment(ch) {
140
+ // do nothing
141
+ }
142
+ processingInstruction(target, data) {
143
+ // do nothing
144
+ }
145
+ startCDATA() {
146
+ // do nothing
147
+ }
148
+ endCDATA() {
149
+ // do nothing
150
+ }
151
+ startDTD(name, publicId, systemId) {
152
+ // do nothing
153
+ }
154
+ endDTD() {
155
+ // do nothing
156
+ }
157
+ skippedEntity(name) {
158
+ // do nothing
159
+ }
160
+ getCurrentText() {
161
+ return '';
162
+ }
163
+ emitEntry() {
164
+ const pureTextElement = this.entryChildren.find((child) => child.getName() === 'pureText');
165
+ const elementWrapper = this.entryChildren.find((child) => child.getName() === 'element');
166
+ const metadataElement = this.entryChildren.find((child) => child.getName() === 'metadata');
167
+ if (!pureTextElement || !elementWrapper) {
168
+ return;
169
+ }
170
+ const innerElements = elementWrapper.getChildren();
171
+ if (innerElements.length === 0) {
172
+ return;
173
+ }
174
+ const jsonEntry = {
175
+ language: this.entryLanguage,
176
+ fileId: this.entryFileId,
177
+ original: this.entryOriginal,
178
+ unitId: this.entryUnitId,
179
+ pureText: pureTextElement.getText(),
180
+ element: innerElements[0].toString(),
181
+ segmentIndex: this.entrySegmentIndex,
182
+ segmentCount: this.entrySegmentCount
183
+ };
184
+ if (metadataElement) {
185
+ const metadata = this.parseMetadataElement(metadataElement);
186
+ if (Object.keys(metadata).length > 0) {
187
+ jsonEntry.metadata = metadata;
188
+ }
189
+ }
190
+ this.writeStream.write(JSON.stringify(jsonEntry) + '\n');
191
+ this.entryCount++;
192
+ }
193
+ parseMetadataElement(metadataElement) {
194
+ const metadata = {};
195
+ const childText = (childName) => {
196
+ const child = metadataElement.getChild(childName);
197
+ if (!child) {
198
+ return undefined;
199
+ }
200
+ const text = child.getText();
201
+ return text.length > 0 ? text : undefined;
202
+ };
203
+ const state = childText('state');
204
+ const validStates = ['initial', 'translated', 'reviewed', 'final'];
205
+ if (state && validStates.includes(state)) {
206
+ metadata.state = state;
207
+ }
208
+ const subState = childText('subState');
209
+ if (subState) {
210
+ metadata.subState = subState;
211
+ }
212
+ const quality = this.parseOptionalNumber(childText('quality'));
213
+ if (quality !== undefined) {
214
+ metadata.quality = quality;
215
+ }
216
+ const creationDate = childText('creationDate');
217
+ if (creationDate) {
218
+ metadata.creationDate = creationDate;
219
+ }
220
+ const creationId = childText('creationId');
221
+ if (creationId) {
222
+ metadata.creationId = creationId;
223
+ }
224
+ const changeDate = childText('changeDate');
225
+ if (changeDate) {
226
+ metadata.changeDate = changeDate;
227
+ }
228
+ const changeId = childText('changeId');
229
+ if (changeId) {
230
+ metadata.changeId = changeId;
231
+ }
232
+ const creationTool = childText('creationTool');
233
+ if (creationTool) {
234
+ metadata.creationTool = creationTool;
235
+ }
236
+ const creationToolVersion = childText('creationToolVersion');
237
+ if (creationToolVersion) {
238
+ metadata.creationToolVersion = creationToolVersion;
239
+ }
240
+ const context = childText('context');
241
+ if (context) {
242
+ metadata.context = context;
243
+ }
244
+ const usageCount = this.parseOptionalNumber(childText('usageCount'));
245
+ if (usageCount !== undefined) {
246
+ metadata.usageCount = usageCount;
247
+ }
248
+ const lastUsageDate = childText('lastUsageDate');
249
+ if (lastUsageDate) {
250
+ metadata.lastUsageDate = lastUsageDate;
251
+ }
252
+ const notesElement = metadataElement.getChild('notes');
253
+ if (notesElement) {
254
+ const notes = notesElement.getChildren()
255
+ .filter((child) => child.getName() === 'note')
256
+ .map((child) => child.getText())
257
+ .filter((text) => text.length > 0);
258
+ if (notes.length > 0) {
259
+ metadata.notes = notes;
260
+ }
261
+ }
262
+ const propertiesElement = metadataElement.getChild('properties');
263
+ if (propertiesElement) {
264
+ const properties = {};
265
+ propertiesElement.getChildren().forEach((child) => {
266
+ if (child.getName() === 'property') {
267
+ const key = child.getAttribute('name')?.getValue();
268
+ if (key && key.length > 0) {
269
+ properties[key] = child.getText();
270
+ }
271
+ }
272
+ });
273
+ if (Object.keys(properties).length > 0) {
274
+ metadata.properties = properties;
275
+ }
276
+ }
277
+ const segmentElement = metadataElement.getChild('segment');
278
+ if (segmentElement) {
279
+ const segment = this.parseSegmentElement(segmentElement);
280
+ if (Object.keys(segment).length > 0) {
281
+ metadata.segment = segment;
282
+ }
283
+ }
284
+ return metadata;
285
+ }
286
+ parseSegmentElement(segmentElement) {
287
+ const segment = {};
288
+ const attr = (attrName) => segmentElement.getAttribute(attrName)?.getValue();
289
+ const provider = attr('provider');
290
+ if (provider) {
291
+ segment.provider = provider;
292
+ }
293
+ const fileHash = attr('fileHash');
294
+ if (fileHash) {
295
+ segment.fileHash = fileHash;
296
+ }
297
+ const fileId = attr('fileId');
298
+ if (fileId) {
299
+ segment.fileId = fileId;
300
+ }
301
+ const unitId = attr('unitId');
302
+ if (unitId) {
303
+ segment.unitId = unitId;
304
+ }
305
+ const segmentId = attr('segmentId');
306
+ if (segmentId) {
307
+ segment.segmentId = segmentId;
308
+ }
309
+ const segmentKey = attr('segmentKey');
310
+ if (segmentKey) {
311
+ segment.segmentKey = segmentKey;
312
+ }
313
+ const segmentIndex = this.parseOptionalNumber(attr('segmentIndex'));
314
+ if (segmentIndex !== undefined) {
315
+ segment.segmentIndex = segmentIndex;
316
+ }
317
+ const segmentCount = this.parseOptionalNumber(attr('segmentCount'));
318
+ if (segmentCount !== undefined) {
319
+ segment.segmentCount = segmentCount;
320
+ }
321
+ return segment;
322
+ }
323
+ parseOptionalNumber(value) {
324
+ if (!value) {
325
+ return undefined;
326
+ }
327
+ const parsed = Number(value);
328
+ return Number.isNaN(parsed) ? undefined : parsed;
329
+ }
330
+ parseNumber(value, fallback) {
331
+ const parsed = this.parseOptionalNumber(value);
332
+ return parsed !== undefined ? parsed : fallback;
333
+ }
334
+ }
335
+ //# sourceMappingURL=backupHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backupHandler.js","sourceRoot":"","sources":["../ts/backupHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse Public License v1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { SAXParser } from "typesxml";
13
+ import { BackupHandler } from './backupHandler.js';
14
+ export declare class BackupReader {
15
+ parser: SAXParser;
16
+ filePath: string;
17
+ handler: BackupHandler;
18
+ jsonlTempPath: string;
19
+ constructor(filePath: string);
20
+ parse(): Promise<void>;
21
+ getTempFilePath(): string;
22
+ getEntryCount(): number;
23
+ getBackupName(): string;
24
+ getBackupModel(): string;
25
+ getBackupDate(): string;
26
+ }
@@ -0,0 +1,55 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse Public License v1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { tmpdir } from "node:os";
13
+ import { join } from 'node:path';
14
+ import { SAXParser } from "typesxml";
15
+ import { BackupHandler } from './backupHandler.js';
16
+ export class BackupReader {
17
+ parser;
18
+ filePath;
19
+ handler;
20
+ jsonlTempPath;
21
+ constructor(filePath) {
22
+ this.filePath = filePath;
23
+ const tempDir = tmpdir();
24
+ const tempFileName = 'backup_' + Date.now() + '_' + Math.random().toString(36).substring(7) + '.jsonl';
25
+ this.jsonlTempPath = join(tempDir, tempFileName);
26
+ this.parser = new SAXParser();
27
+ this.handler = new BackupHandler(this.jsonlTempPath);
28
+ this.parser.setContentHandler(this.handler);
29
+ }
30
+ async parse() {
31
+ try {
32
+ this.parser.parseFile(this.filePath);
33
+ await this.handler.waitForCompletion();
34
+ }
35
+ catch (error) {
36
+ throw error instanceof Error ? error : new Error(String(error));
37
+ }
38
+ }
39
+ getTempFilePath() {
40
+ return this.jsonlTempPath;
41
+ }
42
+ getEntryCount() {
43
+ return this.handler.getEntryCount();
44
+ }
45
+ getBackupName() {
46
+ return this.handler.getBackupName();
47
+ }
48
+ getBackupModel() {
49
+ return this.handler.getBackupModel();
50
+ }
51
+ getBackupDate() {
52
+ return this.handler.getBackupDate();
53
+ }
54
+ }
55
+ //# sourceMappingURL=backupReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backupReader.js","sourceRoot":"","sources":["../ts/backupReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;iFAUiF;AAEjF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,OAAO,YAAY;IAErB,MAAM,CAAY;IAClB,QAAQ,CAAS;IACjB,OAAO,CAAgB;IACvB,aAAa,CAAS;IAEtB,YAAY,QAAgB;QACxB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;QACzB,MAAM,YAAY,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;QACvG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,KAAK;QACP,IAAI,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,CAAC;IACL,CAAC;IAED,eAAe;QACX,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,aAAa;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC;IAED,aAAa;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC;IAED,cAAc;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,CAAC;IAED,aAAa;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC;CACJ"}
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) 2025-2026 Maxprograms.
3
3
  *
4
4
  * This program and the accompanying materials
5
- * are made available under the terms of the Eclipse License 1.0
5
+ * are made available under the terms of the Eclipse Public License v1.0
6
6
  * which accompanies this distribution, and is available at
7
7
  * https://www.eclipse.org/org/documents/epl-v10.html
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) 2025-2026 Maxprograms.
3
3
  *
4
4
  * This program and the accompanying materials
5
- * are made available under the terms of the Eclipse License 1.0
5
+ * are made available under the terms of the Eclipse Public License v1.0
6
6
  * which accompanies this distribution, and is available at
7
7
  * https://www.eclipse.org/org/documents/epl-v10.html
8
8
  *
@@ -101,13 +101,14 @@ export class BatchImporter {
101
101
  console.log('Total entries imported: ' + totalProcessed.toLocaleString());
102
102
  console.log('Total time: ' + minutes + 'm ' + seconds + 's');
103
103
  console.log('Average rate: ' + avgRate.toFixed(1) + ' entries/sec');
104
- // Clean up the temporary file
105
- await this.cleanup();
106
104
  }
107
105
  catch (err) {
108
106
  console.error('Error during batch import:', err);
109
107
  throw err;
110
108
  }
109
+ finally {
110
+ await this.cleanup();
111
+ }
111
112
  }
112
113
  parseMetadata(metadata) {
113
114
  if (!metadata || typeof metadata !== 'object') {