@willwade/aac-processors 0.1.21 → 0.2.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 (87) hide show
  1. package/README.md +3 -2
  2. package/dist/browser/processors/applePanelsProcessor.js +24 -24
  3. package/dist/browser/processors/astericsGridProcessor.js +22 -24
  4. package/dist/browser/processors/dotProcessor.js +6 -10
  5. package/dist/browser/processors/gridset/helpers.js +33 -30
  6. package/dist/browser/processors/gridset/symbolExtractor.js +2 -2
  7. package/dist/browser/processors/gridset/symbolSearch.js +22 -22
  8. package/dist/browser/processors/gridset/symbols.js +14 -14
  9. package/dist/browser/processors/gridsetProcessor.js +7 -7
  10. package/dist/browser/processors/obfProcessor.js +54 -47
  11. package/dist/browser/processors/opmlProcessor.js +6 -10
  12. package/dist/browser/processors/snap/helpers.js +34 -30
  13. package/dist/browser/processors/snapProcessor.js +28 -28
  14. package/dist/browser/processors/touchchatProcessor.js +24 -25
  15. package/dist/browser/utilities/analytics/history.js +24 -18
  16. package/dist/browser/utilities/analytics/metrics/comparison.js +16 -16
  17. package/dist/browser/utilities/analytics/metrics/vocabulary.js +2 -2
  18. package/dist/browser/utilities/analytics/reference/browser.js +16 -16
  19. package/dist/browser/utilities/analytics/reference/index.js +25 -24
  20. package/dist/browser/utils/io.js +29 -25
  21. package/dist/browser/utils/sqlite.js +5 -5
  22. package/dist/browser/utils/zip.js +2 -4
  23. package/dist/browser/validation/gridsetValidator.js +2 -2
  24. package/dist/browser/validation/obfValidator.js +2 -2
  25. package/dist/browser/validation/snapValidator.js +3 -3
  26. package/dist/browser/validation/touchChatValidator.js +3 -3
  27. package/dist/cli/index.js +19 -16
  28. package/dist/core/baseProcessor.d.ts +1 -1
  29. package/dist/processors/applePanelsProcessor.js +24 -24
  30. package/dist/processors/astericsGridProcessor.d.ts +4 -4
  31. package/dist/processors/astericsGridProcessor.js +22 -24
  32. package/dist/processors/dotProcessor.js +6 -10
  33. package/dist/processors/excelProcessor.d.ts +3 -3
  34. package/dist/processors/excelProcessor.js +10 -13
  35. package/dist/processors/gridset/helpers.d.ts +9 -9
  36. package/dist/processors/gridset/helpers.js +33 -30
  37. package/dist/processors/gridset/symbolExtractor.d.ts +1 -1
  38. package/dist/processors/gridset/symbolExtractor.js +2 -2
  39. package/dist/processors/gridset/symbolSearch.d.ts +10 -10
  40. package/dist/processors/gridset/symbolSearch.js +22 -22
  41. package/dist/processors/gridset/symbols.d.ts +3 -3
  42. package/dist/processors/gridset/symbols.js +14 -14
  43. package/dist/processors/gridsetProcessor.d.ts +2 -2
  44. package/dist/processors/gridsetProcessor.js +7 -7
  45. package/dist/processors/obfProcessor.d.ts +2 -2
  46. package/dist/processors/obfProcessor.js +54 -47
  47. package/dist/processors/obfsetProcessor.js +1 -2
  48. package/dist/processors/opmlProcessor.js +6 -10
  49. package/dist/processors/snap/helpers.d.ts +8 -8
  50. package/dist/processors/snap/helpers.js +34 -30
  51. package/dist/processors/snapProcessor.d.ts +2 -2
  52. package/dist/processors/snapProcessor.js +28 -28
  53. package/dist/processors/touchchatProcessor.d.ts +2 -2
  54. package/dist/processors/touchchatProcessor.js +24 -25
  55. package/dist/types/aac.d.ts +2 -2
  56. package/dist/utilities/analytics/history.d.ts +8 -8
  57. package/dist/utilities/analytics/history.js +24 -18
  58. package/dist/utilities/analytics/index.d.ts +1 -1
  59. package/dist/utilities/analytics/index.js +3 -2
  60. package/dist/utilities/analytics/metrics/comparison.d.ts +1 -1
  61. package/dist/utilities/analytics/metrics/comparison.js +16 -16
  62. package/dist/utilities/analytics/metrics/vocabulary.d.ts +1 -1
  63. package/dist/utilities/analytics/metrics/vocabulary.js +2 -2
  64. package/dist/utilities/analytics/reference/browser.d.ts +9 -9
  65. package/dist/utilities/analytics/reference/browser.js +16 -16
  66. package/dist/utilities/analytics/reference/index.d.ts +21 -21
  67. package/dist/utilities/analytics/reference/index.js +25 -24
  68. package/dist/utilities/symbolTools.d.ts +5 -5
  69. package/dist/utilities/symbolTools.js +10 -8
  70. package/dist/utils/io.d.ts +11 -11
  71. package/dist/utils/io.js +29 -25
  72. package/dist/utils/sqlite.d.ts +1 -1
  73. package/dist/utils/sqlite.js +5 -5
  74. package/dist/utils/zip.js +2 -4
  75. package/dist/validation/applePanelsValidator.js +7 -6
  76. package/dist/validation/astericsValidator.js +2 -2
  77. package/dist/validation/dotValidator.js +2 -2
  78. package/dist/validation/excelValidator.js +2 -2
  79. package/dist/validation/gridsetValidator.js +2 -2
  80. package/dist/validation/index.js +2 -2
  81. package/dist/validation/obfValidator.js +2 -2
  82. package/dist/validation/obfsetValidator.js +2 -2
  83. package/dist/validation/opmlValidator.js +2 -2
  84. package/dist/validation/snapValidator.js +3 -3
  85. package/dist/validation/touchChatValidator.js +3 -3
  86. package/docs/BROWSER_USAGE.md +0 -40
  87. package/package.json +1 -1
@@ -26,9 +26,9 @@ const io_1 = require("../../utils/io");
26
26
  * @param pixFilePath - Path to .pix file
27
27
  * @returns Search index
28
28
  */
29
- function parsePixFile(pixFilePath, fileAdapter = io_1.defaultFileAdapter) {
29
+ async function parsePixFile(pixFilePath, fileAdapter = io_1.defaultFileAdapter) {
30
30
  const { readTextFromInput, basename } = fileAdapter;
31
- const content = readTextFromInput(pixFilePath);
31
+ const content = await readTextFromInput(pixFilePath);
32
32
  const library = basename(pixFilePath, '.pix');
33
33
  const searchTerms = new Map();
34
34
  const filenames = new Map();
@@ -55,18 +55,18 @@ function parsePixFile(pixFilePath, fileAdapter = io_1.defaultFileAdapter) {
55
55
  * @param options - Search options
56
56
  * @returns Map of library name to search index
57
57
  */
58
- function loadSearchIndexes(options = {}, fileAdapter = io_1.defaultFileAdapter) {
58
+ async function loadSearchIndexes(options = {}, fileAdapter = io_1.defaultFileAdapter) {
59
59
  const { listDir, pathExists, join, basename } = fileAdapter;
60
60
  const { grid3Path, locale = 'en-GB', libraries: specifiedLibs } = options;
61
61
  if (!grid3Path) {
62
62
  throw new Error('grid3Path is required for symbol search');
63
63
  }
64
64
  const searchIndexesDir = join(grid3Path, 'Locale', locale, 'symbolsearch');
65
- if (!pathExists(searchIndexesDir)) {
65
+ if (!(await pathExists(searchIndexesDir))) {
66
66
  throw new Error(`Symbol search directory not found: ${searchIndexesDir}`);
67
67
  }
68
68
  const indexes = new Map();
69
- const files = listDir(searchIndexesDir);
69
+ const files = await listDir(searchIndexesDir);
70
70
  for (const file of files) {
71
71
  if (!file.endsWith('.pix')) {
72
72
  continue;
@@ -80,7 +80,7 @@ function loadSearchIndexes(options = {}, fileAdapter = io_1.defaultFileAdapter)
80
80
  }
81
81
  try {
82
82
  const pixFilePath = join(searchIndexesDir, file);
83
- const index = parsePixFile(pixFilePath);
83
+ const index = await parsePixFile(pixFilePath);
84
84
  indexes.set(libraryName, index);
85
85
  }
86
86
  catch (error) {
@@ -95,8 +95,8 @@ function loadSearchIndexes(options = {}, fileAdapter = io_1.defaultFileAdapter)
95
95
  * @param options - Search options
96
96
  * @returns Array of search results
97
97
  */
98
- function searchSymbols(searchTerm, options = {}) {
99
- const indexes = loadSearchIndexes(options);
98
+ async function searchSymbols(searchTerm, options = {}) {
99
+ const indexes = await loadSearchIndexes(options);
100
100
  const results = [];
101
101
  const lowerSearchTerm = searchTerm.toLowerCase().trim();
102
102
  const limit = options.limit || 100;
@@ -149,8 +149,8 @@ function searchSymbols(searchTerm, options = {}) {
149
149
  * @param options - Search options
150
150
  * @returns Symbol filename or undefined
151
151
  */
152
- function getSymbolFilename(searchTerm, library, options = {}) {
153
- const indexes = loadSearchIndexes({
152
+ async function getSymbolFilename(searchTerm, library, options = {}) {
153
+ const indexes = await loadSearchIndexes({
154
154
  ...options,
155
155
  libraries: [library],
156
156
  });
@@ -167,8 +167,8 @@ function getSymbolFilename(searchTerm, library, options = {}) {
167
167
  * @param options - Search options
168
168
  * @returns Display name or undefined
169
169
  */
170
- function getSymbolDisplayName(symbolFilename, library, options = {}) {
171
- const indexes = loadSearchIndexes({
170
+ async function getSymbolDisplayName(symbolFilename, library, options = {}) {
171
+ const indexes = await loadSearchIndexes({
172
172
  ...options,
173
173
  libraries: [library],
174
174
  });
@@ -184,8 +184,8 @@ function getSymbolDisplayName(symbolFilename, library, options = {}) {
184
184
  * @param options - Search options
185
185
  * @returns Array of search terms
186
186
  */
187
- function getAllSearchTerms(library, options = {}) {
188
- const indexes = loadSearchIndexes({
187
+ async function getAllSearchTerms(library, options = {}) {
188
+ const indexes = await loadSearchIndexes({
189
189
  ...options,
190
190
  libraries: [library],
191
191
  });
@@ -201,8 +201,8 @@ function getAllSearchTerms(library, options = {}) {
201
201
  * @param options - Search options
202
202
  * @returns Array of suggested terms
203
203
  */
204
- function getSearchSuggestions(partialTerm, options = {}) {
205
- const indexes = loadSearchIndexes(options);
204
+ async function getSearchSuggestions(partialTerm, options = {}) {
205
+ const indexes = await loadSearchIndexes(options);
206
206
  const suggestions = new Set();
207
207
  const lowerPartial = partialTerm.toLowerCase().trim();
208
208
  for (const index of indexes.values()) {
@@ -220,8 +220,8 @@ function getSearchSuggestions(partialTerm, options = {}) {
220
220
  * @param options - Search options
221
221
  * @returns Array of full symbol references
222
222
  */
223
- function searchSymbolsWithReferences(searchTerm, options = {}) {
224
- const results = searchSymbols(searchTerm, options);
223
+ async function searchSymbolsWithReferences(searchTerm, options = {}) {
224
+ const results = await searchSymbols(searchTerm, options);
225
225
  return results.map((r) => `[${r.library}]${r.symbolFilename}`);
226
226
  }
227
227
  /**
@@ -229,8 +229,8 @@ function searchSymbolsWithReferences(searchTerm, options = {}) {
229
229
  * @param options - Search options
230
230
  * @returns Map of library name to symbol count
231
231
  */
232
- function countLibrarySymbols(options = {}) {
233
- const indexes = loadSearchIndexes(options);
232
+ async function countLibrarySymbols(options = {}) {
233
+ const indexes = await loadSearchIndexes(options);
234
234
  const counts = new Map();
235
235
  for (const [libraryName, index] of indexes.entries()) {
236
236
  counts.set(libraryName, index.searchTerms.size);
@@ -242,8 +242,8 @@ function countLibrarySymbols(options = {}) {
242
242
  * @param options - Search options
243
243
  * @returns Statistics about available symbols
244
244
  */
245
- function getSymbolSearchStats(options = {}) {
246
- const indexes = loadSearchIndexes(options);
245
+ async function getSymbolSearchStats(options = {}) {
246
+ const indexes = await loadSearchIndexes(options);
247
247
  const stats = {
248
248
  totalLibraries: indexes.size,
249
249
  totalSymbols: 0,
@@ -94,7 +94,7 @@ export declare function isSymbolReference(reference: string): boolean;
94
94
  * Get the default Grid 3 installation path for the current platform
95
95
  * @returns Default Grid 3 path or empty string if not found
96
96
  */
97
- export declare function getDefaultGrid3Path(fileAdapter?: FileAdapter): string;
97
+ export declare function getDefaultGrid3Path(fileAdapter?: FileAdapter): Promise<string>;
98
98
  /**
99
99
  * Get the Symbol Libraries directory path
100
100
  * Contains .symbols ZIP archives with actual image files
@@ -115,14 +115,14 @@ export declare function getSymbolSearchIndexesDir(grid3Path: string, locale?: st
115
115
  * @param options - Resolution options
116
116
  * @returns Array of symbol library information
117
117
  */
118
- export declare function getAvailableSymbolLibraries(options?: SymbolResolutionOptions, fileAdapter?: FileAdapter): SymbolLibraryInfo[];
118
+ export declare function getAvailableSymbolLibraries(options?: SymbolResolutionOptions, fileAdapter?: FileAdapter): Promise<SymbolLibraryInfo[]>;
119
119
  /**
120
120
  * Check if a symbol library exists
121
121
  * @param libraryName - Name of the library (e.g., 'widgit', 'tawasl')
122
122
  * @param options - Resolution options
123
123
  * @returns Symbol library info or undefined if not found
124
124
  */
125
- export declare function getSymbolLibraryInfo(libraryName: string, options?: SymbolResolutionOptions, fileAdapter?: FileAdapter): SymbolLibraryInfo | undefined;
125
+ export declare function getSymbolLibraryInfo(libraryName: string, options?: SymbolResolutionOptions, fileAdapter?: FileAdapter): Promise<SymbolLibraryInfo | undefined>;
126
126
  /**
127
127
  * Resolve a symbol reference to extract the actual image data
128
128
  * @param reference - Symbol reference like "[tawasl]/above bw.png"
@@ -114,12 +114,12 @@ function isSymbolReference(reference) {
114
114
  * Get the default Grid 3 installation path for the current platform
115
115
  * @returns Default Grid 3 path or empty string if not found
116
116
  */
117
- function getDefaultGrid3Path(fileAdapter) {
117
+ async function getDefaultGrid3Path(fileAdapter) {
118
118
  const { pathExists } = fileAdapter ?? io_1.defaultFileAdapter;
119
119
  const platform = (typeof process !== 'undefined' && process.platform ? process.platform : 'unknown');
120
120
  const defaultPath = DEFAULT_GRID3_PATHS[platform] || '';
121
121
  try {
122
- if (defaultPath && pathExists(defaultPath)) {
122
+ if (defaultPath && (await pathExists(defaultPath))) {
123
123
  return defaultPath;
124
124
  }
125
125
  // Try to find Grid 3 in common locations
@@ -131,7 +131,7 @@ function getDefaultGrid3Path(fileAdapter) {
131
131
  '/opt/smartbox/grid3',
132
132
  ];
133
133
  for (const testPath of commonPaths) {
134
- if (pathExists(testPath)) {
134
+ if (await pathExists(testPath)) {
135
135
  return testPath;
136
136
  }
137
137
  }
@@ -167,22 +167,22 @@ function getSymbolSearchIndexesDir(grid3Path, locale = exports.DEFAULT_LOCALE, f
167
167
  * @param options - Resolution options
168
168
  * @returns Array of symbol library information
169
169
  */
170
- function getAvailableSymbolLibraries(options = {}, fileAdapter) {
170
+ async function getAvailableSymbolLibraries(options = {}, fileAdapter) {
171
171
  const { pathExists, getFileSize, listDir, join, basename } = fileAdapter ?? io_1.defaultFileAdapter;
172
- const grid3Path = options.grid3Path || options.symbolDir || getDefaultGrid3Path();
172
+ const grid3Path = options.grid3Path || options.symbolDir || (await getDefaultGrid3Path());
173
173
  if (!grid3Path) {
174
174
  return [];
175
175
  }
176
176
  const symbolsDir = getSymbolLibrariesDir(grid3Path, fileAdapter);
177
- if (!pathExists(symbolsDir)) {
177
+ if (!(await pathExists(symbolsDir))) {
178
178
  return [];
179
179
  }
180
180
  const libraries = [];
181
- const files = listDir(symbolsDir);
181
+ const files = await listDir(symbolsDir);
182
182
  for (const file of files) {
183
183
  if (file.endsWith('.symbols')) {
184
184
  const fullPath = join(symbolsDir, file);
185
- const size = getFileSize(fullPath);
185
+ const size = await getFileSize(fullPath);
186
186
  const libraryName = basename(file, '.symbols');
187
187
  libraries.push({
188
188
  name: libraryName,
@@ -201,9 +201,9 @@ function getAvailableSymbolLibraries(options = {}, fileAdapter) {
201
201
  * @param options - Resolution options
202
202
  * @returns Symbol library info or undefined if not found
203
203
  */
204
- function getSymbolLibraryInfo(libraryName, options = {}, fileAdapter) {
204
+ async function getSymbolLibraryInfo(libraryName, options = {}, fileAdapter) {
205
205
  const { pathExists, getFileSize, join } = fileAdapter ?? io_1.defaultFileAdapter;
206
- const grid3Path = options.grid3Path || options.symbolDir || getDefaultGrid3Path();
206
+ const grid3Path = options.grid3Path || options.symbolDir || (await getDefaultGrid3Path());
207
207
  if (!grid3Path) {
208
208
  return undefined;
209
209
  }
@@ -217,8 +217,8 @@ function getSymbolLibraryInfo(libraryName, options = {}, fileAdapter) {
217
217
  ];
218
218
  for (const file of variations) {
219
219
  const fullPath = join(symbolsDir, file);
220
- if (pathExists(fullPath)) {
221
- const size = getFileSize(fullPath);
220
+ if (await pathExists(fullPath)) {
221
+ const size = await getFileSize(fullPath);
222
222
  return {
223
223
  name: libraryName,
224
224
  pixFile: fullPath,
@@ -245,7 +245,7 @@ async function resolveSymbolReference(reference, options = {}, fileAdapter = io_
245
245
  error: 'Invalid symbol reference format',
246
246
  };
247
247
  }
248
- const grid3Path = options.grid3Path || getDefaultGrid3Path();
248
+ const grid3Path = options.grid3Path || (await getDefaultGrid3Path());
249
249
  if (!grid3Path) {
250
250
  return {
251
251
  reference: parsed,
@@ -253,7 +253,7 @@ async function resolveSymbolReference(reference, options = {}, fileAdapter = io_
253
253
  error: 'Grid 3 installation not found. Please specify grid3Path.',
254
254
  };
255
255
  }
256
- const libraryInfo = getSymbolLibraryInfo(parsed.library, { grid3Path });
256
+ const libraryInfo = await getSymbolLibraryInfo(parsed.library, { grid3Path });
257
257
  if (!libraryInfo || !libraryInfo.exists) {
258
258
  return {
259
259
  reference: parsed,
@@ -30,7 +30,7 @@ declare class GridsetProcessor extends BaseProcessor {
30
30
  * This method uses shared translation utilities that work across all AAC formats.
31
31
  *
32
32
  * @param filePathOrBuffer - Path to gridset file or buffer
33
- * @returns Array of symbol information for LLM processing
33
+ * @returns Promise resolving to symbol information for LLM processing
34
34
  */
35
35
  extractSymbolsForLLM(filePathOrBuffer: string | Buffer): Promise<ButtonForTranslation[]>;
36
36
  /**
@@ -43,7 +43,7 @@ declare class GridsetProcessor extends BaseProcessor {
43
43
  * @param llmTranslations - Array of LLM translations with symbol info
44
44
  * @param outputPath - Where to save the translated gridset
45
45
  * @param options - Translation options (e.g., allowPartial for testing)
46
- * @returns Buffer of the translated gridset
46
+ * @returns Promise resolving to a buffer of the translated gridset
47
47
  */
48
48
  processLLMTranslations(filePathOrBuffer: string | Buffer, llmTranslations: LLMLTranslationResult[], outputPath: string, options?: {
49
49
  allowPartial?: boolean;
@@ -401,7 +401,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
401
401
  const tree = new treeStructure_1.AACTree();
402
402
  let zipResult;
403
403
  try {
404
- const zipInput = readBinaryFromInput(filePathOrBuffer);
404
+ const zipInput = await readBinaryFromInput(filePathOrBuffer);
405
405
  zipResult = await this.options.zipAdapter(zipInput);
406
406
  }
407
407
  catch (error) {
@@ -1745,7 +1745,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1745
1745
  });
1746
1746
  // Save the translated tree and return its content
1747
1747
  await this.saveFromTree(tree, outputPath);
1748
- return readBinaryFromInput(outputPath);
1748
+ return await readBinaryFromInput(outputPath);
1749
1749
  }
1750
1750
  /**
1751
1751
  * Extract symbol information from a gridset for LLM-based translation.
@@ -1754,7 +1754,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1754
1754
  * This method uses shared translation utilities that work across all AAC formats.
1755
1755
  *
1756
1756
  * @param filePathOrBuffer - Path to gridset file or buffer
1757
- * @returns Array of symbol information for LLM processing
1757
+ * @returns Promise resolving to symbol information for LLM processing
1758
1758
  */
1759
1759
  async extractSymbolsForLLM(filePathOrBuffer) {
1760
1760
  const tree = await this.loadIntoTree(filePathOrBuffer);
@@ -1784,7 +1784,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1784
1784
  * @param llmTranslations - Array of LLM translations with symbol info
1785
1785
  * @param outputPath - Where to save the translated gridset
1786
1786
  * @param options - Translation options (e.g., allowPartial for testing)
1787
- * @returns Buffer of the translated gridset
1787
+ * @returns Promise resolving to a buffer of the translated gridset
1788
1788
  */
1789
1789
  async processLLMTranslations(filePathOrBuffer, llmTranslations, outputPath, options) {
1790
1790
  const { readBinaryFromInput } = this.options.fileAdapter;
@@ -1826,7 +1826,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1826
1826
  });
1827
1827
  // Save and return
1828
1828
  await this.saveFromTree(tree, outputPath);
1829
- return readBinaryFromInput(outputPath);
1829
+ return await readBinaryFromInput(outputPath);
1830
1830
  }
1831
1831
  async saveFromTree(tree, outputPath) {
1832
1832
  const files = [];
@@ -1835,7 +1835,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1835
1835
  if (Object.keys(tree.pages).length === 0) {
1836
1836
  // Create empty zip for empty tree
1837
1837
  const zipBuffer = await zip.writeFiles([]);
1838
- writeBinaryToPath(outputPath, zipBuffer);
1838
+ await writeBinaryToPath(outputPath, zipBuffer);
1839
1839
  return;
1840
1840
  }
1841
1841
  // Collect all unique styles from pages and buttons
@@ -2145,7 +2145,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
2145
2145
  });
2146
2146
  // Write the zip file
2147
2147
  const zipBuffer = await zip.writeFiles(files);
2148
- writeBinaryToPath(outputPath, zipBuffer);
2148
+ await writeBinaryToPath(outputPath, zipBuffer);
2149
2149
  }
2150
2150
  // Helper method to calculate column definitions based on page layout
2151
2151
  calculateColumnDefinitions(page) {
@@ -46,7 +46,7 @@ declare class ObfProcessor extends BaseProcessor {
46
46
  * This method uses shared translation utilities that work across all AAC formats.
47
47
  *
48
48
  * @param filePathOrBuffer - Path to OBF/OBZ file or buffer
49
- * @returns Array of symbol information for LLM processing
49
+ * @returns Promise resolving to symbol information for LLM processing
50
50
  */
51
51
  extractSymbolsForLLM(filePathOrBuffer: ProcessorInput): Promise<ButtonForTranslation[]>;
52
52
  /**
@@ -59,7 +59,7 @@ declare class ObfProcessor extends BaseProcessor {
59
59
  * @param llmTranslations - Array of LLM translations with symbol info
60
60
  * @param outputPath - Where to save the translated OBF/OBZ file
61
61
  * @param options - Translation options (e.g., allowPartial for testing)
62
- * @returns Buffer of the translated OBF/OBZ file
62
+ * @returns Promise resolving to a buffer of the translated OBF/OBZ file
63
63
  */
64
64
  processLLMTranslations(filePathOrBuffer: ProcessorInput, llmTranslations: LLMLTranslationResult[], outputPath: string, options?: {
65
65
  allowPartial?: boolean;
@@ -6,7 +6,6 @@ const treeStructure_1 = require("../core/treeStructure");
6
6
  const idGenerator_1 = require("../utilities/analytics/utils/idGenerator");
7
7
  const translationProcessor_1 = require("../utilities/translation/translationProcessor");
8
8
  const io_1 = require("../utils/io");
9
- const zip_1 = require("../utils/zip");
10
9
  const OBF_FORMAT_VERSION = 'open-board-0.1';
11
10
  /**
12
11
  * Map OBF hidden value to AAC standard visibility
@@ -66,35 +65,42 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
66
65
  if (this.imageCache.has(imageId)) {
67
66
  return this.imageCache.get(imageId) ?? null;
68
67
  }
69
- if (!this.zipFile || !images) {
68
+ if (!images)
70
69
  return null;
71
- }
72
70
  // Find the image metadata
73
71
  const imageData = images.find((img) => img.id === imageId);
74
72
  if (!imageData) {
75
73
  return null;
76
74
  }
77
- // Try to get the image file from the ZIP
78
- // Images are typically stored in an 'images' folder or root
79
- const possiblePaths = [
80
- imageData.path, // Explicit path if provided
81
- `images/${imageData.filename || imageId}`, // Standard images folder
82
- imageData.id, // Just the ID
83
- ].filter(Boolean);
84
- for (const imagePath of possiblePaths) {
85
- try {
86
- const buffer = await this.zipFile.readFile(imagePath);
87
- if (buffer) {
88
- const contentType = imageData.content_type ||
89
- this.getMimeTypeFromFilename(imagePath);
90
- const dataUrl = `data:${contentType};base64,${(0, io_1.encodeBase64)(buffer)}`;
91
- this.imageCache.set(imageId, dataUrl);
92
- return dataUrl;
75
+ // If image has data property, use that
76
+ if (imageData.data) {
77
+ const dataUrl = imageData.data;
78
+ this.imageCache.set(imageId, dataUrl);
79
+ return dataUrl;
80
+ }
81
+ if (this.zipFile) {
82
+ // Try to get the image file from the ZIP
83
+ // Images are typically stored in an 'images' folder or root
84
+ const possiblePaths = [
85
+ imageData.path, // Explicit path if provided
86
+ `images/${imageData.filename || imageId}`, // Standard images folder
87
+ imageData.id, // Just the ID
88
+ ].filter(Boolean);
89
+ for (const imagePath of possiblePaths) {
90
+ try {
91
+ const buffer = await this.zipFile.readFile(imagePath);
92
+ if (buffer) {
93
+ const contentType = imageData.content_type ||
94
+ this.getMimeTypeFromFilename(imagePath);
95
+ const dataUrl = `data:${contentType};base64,${(0, io_1.encodeBase64)(buffer)}`;
96
+ this.imageCache.set(imageId, dataUrl);
97
+ return dataUrl;
98
+ }
99
+ }
100
+ catch (err) {
101
+ // Continue to next path
102
+ continue;
93
103
  }
94
- }
95
- catch (err) {
96
- // Continue to next path
97
- continue;
98
104
  }
99
105
  }
100
106
  // If image has a URL, use that as fallback
@@ -170,8 +176,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
170
176
  buttonParameters.image_id = btn.image_id;
171
177
  }
172
178
  return new treeStructure_1.AACButton({
173
- // Make button ID unique by combining page ID and button ID
174
- id: `${pageId}::${btn?.id || ''}`,
179
+ id: String(btn.id),
175
180
  label: String(btn?.label || ''),
176
181
  message: String(btn?.vocalization || btn?.label || ''),
177
182
  visibility: mapObfVisibility(btn.hidden),
@@ -220,7 +225,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
220
225
  return;
221
226
  if (rowIndex >= rows || colIndex >= cols)
222
227
  return;
223
- const aacBtn = buttonMap.get(`${pageId}::${cellId}`);
228
+ const aacBtn = buttonMap.get(String(cellId));
224
229
  if (aacBtn) {
225
230
  grid[rowIndex][colIndex] = aacBtn;
226
231
  }
@@ -233,7 +238,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
233
238
  const row = Math.floor(btn.box_id / cols);
234
239
  const col = btn.box_id % cols;
235
240
  if (row < rows && col < cols) {
236
- const aacBtn = buttonMap.get(`${pageId}::${btn.id}`);
241
+ const aacBtn = buttonMap.get(String(btn.id));
237
242
  if (aacBtn) {
238
243
  grid[row][col] = aacBtn;
239
244
  }
@@ -290,7 +295,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
290
295
  // Detailed logging for debugging input
291
296
  const bufferLength = typeof filePathOrBuffer === 'string'
292
297
  ? null
293
- : readBinaryFromInput(filePathOrBuffer).byteLength;
298
+ : (await readBinaryFromInput(filePathOrBuffer)).byteLength;
294
299
  console.log('[OBF] loadIntoTree called with:', {
295
300
  type: typeof filePathOrBuffer,
296
301
  isBuffer: typeof Buffer !== 'undefined' && Buffer.isBuffer(filePathOrBuffer),
@@ -300,9 +305,9 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
300
305
  });
301
306
  const tree = new treeStructure_1.AACTree();
302
307
  // Helper: try to parse JSON OBF
303
- function tryParseObfJson(data) {
308
+ async function tryParseObfJson(data) {
304
309
  try {
305
- const str = typeof data === 'string' ? data : readTextFromInput(data);
310
+ const str = typeof data === 'string' ? data : await readTextFromInput(data);
306
311
  // Check for empty or whitespace-only content
307
312
  if (!str.trim()) {
308
313
  return null;
@@ -324,8 +329,8 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
324
329
  // If input is a string path and ends with .obf, treat as JSON
325
330
  if (typeof filePathOrBuffer === 'string' && filePathOrBuffer.toLowerCase().endsWith('.obf')) {
326
331
  try {
327
- const content = readTextFromInput(filePathOrBuffer);
328
- const boardData = tryParseObfJson(content);
332
+ const content = await readTextFromInput(filePathOrBuffer);
333
+ const boardData = await tryParseObfJson(content);
329
334
  if (boardData) {
330
335
  console.log('[OBF] Detected .obf file, parsed as JSON');
331
336
  const page = await this.processBoard(boardData, filePathOrBuffer, false);
@@ -353,17 +358,17 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
353
358
  }
354
359
  }
355
360
  // Detect likely zip signature first
356
- function isLikelyZip(input) {
361
+ async function isLikelyZip(input) {
357
362
  if (typeof input === 'string') {
358
363
  const lowered = input.toLowerCase();
359
364
  return lowered.endsWith('.zip') || lowered.endsWith('.obz');
360
365
  }
361
- const bytes = readBinaryFromInput(input);
366
+ const bytes = await readBinaryFromInput(input);
362
367
  return bytes.length >= 2 && bytes[0] === 0x50 && bytes[1] === 0x4b;
363
368
  }
364
369
  // Check if input is a buffer or string that parses as OBF JSON; throw if neither JSON nor ZIP
365
- if (!isLikelyZip(filePathOrBuffer)) {
366
- const asJson = tryParseObfJson(filePathOrBuffer);
370
+ if (!(await isLikelyZip(filePathOrBuffer))) {
371
+ const asJson = await tryParseObfJson(filePathOrBuffer);
367
372
  if (!asJson)
368
373
  throw new Error('Invalid OBF content: not JSON and not ZIP');
369
374
  console.log('[OBF] Detected buffer/string as OBF JSON');
@@ -402,7 +407,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
402
407
  try {
403
408
  const content = await this.zipFile.readFile(manifestFile[0]);
404
409
  const data = (0, io_1.decodeText)(content);
405
- const str = typeof data === 'string' ? data : readTextFromInput(data);
410
+ const str = typeof data === 'string' ? data : await readTextFromInput(data);
406
411
  if (!str.trim())
407
412
  throw new Error('Manifest object missing');
408
413
  const manifestObject = JSON.parse(str);
@@ -426,7 +431,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
426
431
  for (const entryName of obfEntries) {
427
432
  try {
428
433
  const content = await this.zipFile.readFile(entryName);
429
- const boardData = tryParseObfJson((0, io_1.decodeText)(content));
434
+ const boardData = await tryParseObfJson((0, io_1.decodeText)(content));
430
435
  if (boardData) {
431
436
  const page = await this.processBoard(boardData, entryName, true);
432
437
  tree.addPage(page);
@@ -533,6 +538,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
533
538
  border_color: button.style?.borderColor,
534
539
  box_id: buttonPositions.get(String(button.id ?? '')),
535
540
  image_id: imageId,
541
+ hidden: button.visibility === 'Hidden' || false,
536
542
  };
537
543
  }),
538
544
  images: Array.isArray(page.images) ? page.images : [],
@@ -570,10 +576,10 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
570
576
  });
571
577
  // Save the translated tree and return its content
572
578
  await this.saveFromTree(tree, outputPath);
573
- return readBinaryFromInput(outputPath);
579
+ return await readBinaryFromInput(outputPath);
574
580
  }
575
581
  async saveFromTree(tree, outputPath) {
576
- const { writeTextToPath, writeBinaryToPath } = this.options.fileAdapter;
582
+ const { writeTextToPath, writeBinaryToPath, pathExists } = this.options.fileAdapter;
577
583
  if (outputPath.endsWith('.obf')) {
578
584
  // Save as single OBF JSON file
579
585
  const rootPage = tree.rootId ? tree.getPage(tree.rootId) : Object.values(tree.pages)[0];
@@ -581,7 +587,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
581
587
  throw new Error('No pages to save');
582
588
  }
583
589
  const obfBoard = this.createObfBoardFromPage(rootPage, 'Exported Board', tree.metadata);
584
- writeTextToPath(outputPath, JSON.stringify(obfBoard, null, 2));
590
+ await writeTextToPath(outputPath, JSON.stringify(obfBoard, null, 2));
585
591
  }
586
592
  else {
587
593
  const files = Object.values(tree.pages).map((page) => {
@@ -593,9 +599,10 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
593
599
  data: new TextEncoder().encode(obfContent),
594
600
  };
595
601
  });
596
- const zip = await (0, zip_1.getZipAdapter)(undefined, this.options.fileAdapter);
597
- const zipData = await zip.writeFiles(files);
598
- writeBinaryToPath(outputPath, zipData);
602
+ const fileExists = await pathExists(outputPath);
603
+ this.zipFile = await this.options.zipAdapter(fileExists ? outputPath : undefined, this.options.fileAdapter);
604
+ const zipData = await this.zipFile.writeFiles(files);
605
+ await writeBinaryToPath(outputPath, zipData);
599
606
  }
600
607
  }
601
608
  /**
@@ -628,7 +635,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
628
635
  * This method uses shared translation utilities that work across all AAC formats.
629
636
  *
630
637
  * @param filePathOrBuffer - Path to OBF/OBZ file or buffer
631
- * @returns Array of symbol information for LLM processing
638
+ * @returns Promise resolving to symbol information for LLM processing
632
639
  */
633
640
  async extractSymbolsForLLM(filePathOrBuffer) {
634
641
  const tree = await this.loadIntoTree(filePathOrBuffer);
@@ -658,7 +665,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
658
665
  * @param llmTranslations - Array of LLM translations with symbol info
659
666
  * @param outputPath - Where to save the translated OBF/OBZ file
660
667
  * @param options - Translation options (e.g., allowPartial for testing)
661
- * @returns Buffer of the translated OBF/OBZ file
668
+ * @returns Promise resolving to a buffer of the translated OBF/OBZ file
662
669
  */
663
670
  async processLLMTranslations(filePathOrBuffer, llmTranslations, outputPath, options) {
664
671
  const { readBinaryFromInput } = this.options.fileAdapter;
@@ -700,7 +707,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
700
707
  });
701
708
  // Save and return
702
709
  await this.saveFromTree(tree, outputPath);
703
- return readBinaryFromInput(outputPath);
710
+ return await readBinaryFromInput(outputPath);
704
711
  }
705
712
  getObfValidator() {
706
713
  try {
@@ -33,10 +33,9 @@ class ObfsetProcessor extends baseProcessor_1.BaseProcessor {
33
33
  */
34
34
  async loadIntoTree(filePathOrBuffer) {
35
35
  const { readTextFromInput } = this.options.fileAdapter;
36
- await Promise.resolve();
37
36
  const tree = new treeStructure_1.AACTree();
38
37
  tree.metadata.format = 'obfset';
39
- const content = readTextFromInput(filePathOrBuffer);
38
+ const content = await readTextFromInput(filePathOrBuffer);
40
39
  const boards = JSON.parse(content);
41
40
  // Track board ID mappings
42
41
  const boardMap = new Map();
@@ -53,8 +53,7 @@ class OpmlProcessor extends baseProcessor_1.BaseProcessor {
53
53
  }
54
54
  async extractTexts(filePathOrBuffer) {
55
55
  const { readTextFromInput } = this.options.fileAdapter;
56
- await Promise.resolve();
57
- const content = readTextFromInput(filePathOrBuffer);
56
+ const content = await readTextFromInput(filePathOrBuffer);
58
57
  const parser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false });
59
58
  const data = parser.parse(content);
60
59
  const texts = [];
@@ -86,10 +85,9 @@ class OpmlProcessor extends baseProcessor_1.BaseProcessor {
86
85
  }
87
86
  async loadIntoTree(filePathOrBuffer) {
88
87
  const { readBinaryFromInput, readTextFromInput } = this.options.fileAdapter;
89
- await Promise.resolve();
90
88
  const filename = typeof filePathOrBuffer === 'string' ? (0, io_1.getBasename)(filePathOrBuffer) : 'upload.opml';
91
- const buffer = readBinaryFromInput(filePathOrBuffer);
92
- const content = readTextFromInput(buffer);
89
+ const buffer = await readBinaryFromInput(filePathOrBuffer);
90
+ const content = await readTextFromInput(buffer);
93
91
  try {
94
92
  if (!content || !content.trim()) {
95
93
  const validationResult = (0, validationTypes_1.buildValidationResultFromMessage)({
@@ -173,8 +171,7 @@ class OpmlProcessor extends baseProcessor_1.BaseProcessor {
173
171
  }
174
172
  async processTexts(filePathOrBuffer, translations, outputPath) {
175
173
  const { writeBinaryToPath, readTextFromInput } = this.options.fileAdapter;
176
- await Promise.resolve();
177
- const content = readTextFromInput(filePathOrBuffer);
174
+ const content = await readTextFromInput(filePathOrBuffer);
178
175
  let translatedContent = content;
179
176
  // Apply translations to text attributes in OPML outline elements
180
177
  translations.forEach((translation, originalText) => {
@@ -185,12 +182,11 @@ class OpmlProcessor extends baseProcessor_1.BaseProcessor {
185
182
  }
186
183
  });
187
184
  const resultBuffer = (0, io_1.encodeText)(translatedContent);
188
- writeBinaryToPath(outputPath, resultBuffer);
185
+ await writeBinaryToPath(outputPath, resultBuffer);
189
186
  return resultBuffer;
190
187
  }
191
188
  async saveFromTree(tree, outputPath) {
192
189
  const { writeTextToPath } = this.options.fileAdapter;
193
- await Promise.resolve();
194
190
  // Helper to recursively build outline nodes with cycle detection
195
191
  function buildOutline(page, visited = new Set()) {
196
192
  // Prevent infinite recursion by tracking visited pages
@@ -260,7 +256,7 @@ class OpmlProcessor extends baseProcessor_1.BaseProcessor {
260
256
  attributeNamePrefix: '@_',
261
257
  });
262
258
  const xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + builder.build(opmlObj);
263
- writeTextToPath(outputPath, xml);
259
+ await writeTextToPath(outputPath, xml);
264
260
  }
265
261
  /**
266
262
  * Extract strings with metadata for aac-tools-platform compatibility