@willwade/aac-processors 0.1.20 → 0.1.21

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 (94) hide show
  1. package/dist/browser/core/baseProcessor.js +4 -0
  2. package/dist/browser/processors/applePanelsProcessor.js +24 -31
  3. package/dist/browser/processors/astericsGridProcessor.js +10 -3
  4. package/dist/browser/processors/dotProcessor.js +5 -2
  5. package/dist/browser/processors/gridset/colorUtils.js +354 -0
  6. package/dist/browser/processors/gridset/helpers.js +49 -45
  7. package/dist/browser/processors/gridset/index.js +61 -0
  8. package/dist/browser/processors/gridset/styleHelpers.js +205 -0
  9. package/dist/browser/processors/gridset/symbolExtractor.js +331 -0
  10. package/dist/browser/processors/gridset/symbolSearch.js +248 -0
  11. package/dist/browser/processors/gridset/symbols.js +35 -68
  12. package/dist/browser/processors/gridsetProcessor.js +32 -41
  13. package/dist/browser/processors/obfProcessor.js +20 -33
  14. package/dist/browser/processors/opmlProcessor.js +5 -2
  15. package/dist/browser/processors/snap/helpers.js +49 -45
  16. package/dist/browser/processors/snapProcessor.js +39 -42
  17. package/dist/browser/processors/touchchatProcessor.js +54 -45
  18. package/dist/browser/utilities/analytics/reference/index.js +27 -19
  19. package/dist/browser/utils/io.js +67 -14
  20. package/dist/browser/utils/sqlite.js +6 -8
  21. package/dist/browser/utils/zip.js +45 -43
  22. package/dist/browser/validation/baseValidator.js +5 -0
  23. package/dist/browser/validation/gridsetValidator.js +12 -20
  24. package/dist/browser/validation/obfValidator.js +5 -4
  25. package/dist/browser/validation/snapValidator.js +9 -5
  26. package/dist/browser/validation/touchChatValidator.js +21 -11
  27. package/dist/cli/index.js +10 -15
  28. package/dist/core/baseProcessor.d.ts +7 -7
  29. package/dist/core/baseProcessor.js +4 -0
  30. package/dist/processors/applePanelsProcessor.js +29 -36
  31. package/dist/processors/astericsGridProcessor.js +20 -13
  32. package/dist/processors/dotProcessor.js +10 -7
  33. package/dist/processors/excelProcessor.js +9 -12
  34. package/dist/processors/gridset/helpers.d.ts +9 -11
  35. package/dist/processors/gridset/helpers.js +49 -71
  36. package/dist/processors/gridset/imageDebug.d.ts +3 -5
  37. package/dist/processors/gridset/imageDebug.js +4 -4
  38. package/dist/processors/gridset/password.d.ts +1 -1
  39. package/dist/processors/gridset/symbolExtractor.d.ts +5 -3
  40. package/dist/processors/gridset/symbolExtractor.js +15 -38
  41. package/dist/processors/gridset/symbolSearch.d.ts +3 -2
  42. package/dist/processors/gridset/symbolSearch.js +12 -34
  43. package/dist/processors/gridset/symbols.d.ts +8 -6
  44. package/dist/processors/gridset/symbols.js +34 -67
  45. package/dist/processors/gridset/wordlistHelpers.d.ts +4 -6
  46. package/dist/processors/gridset/wordlistHelpers.js +15 -74
  47. package/dist/processors/gridsetProcessor.js +36 -68
  48. package/dist/processors/obfProcessor.js +26 -62
  49. package/dist/processors/obfsetProcessor.js +2 -2
  50. package/dist/processors/opmlProcessor.js +10 -7
  51. package/dist/processors/snap/helpers.d.ts +8 -8
  52. package/dist/processors/snap/helpers.js +50 -72
  53. package/dist/processors/snapProcessor.js +38 -41
  54. package/dist/processors/touchchatProcessor.js +54 -45
  55. package/dist/utilities/analytics/index.d.ts +3 -2
  56. package/dist/utilities/analytics/index.js +8 -10
  57. package/dist/utilities/analytics/reference/index.d.ts +5 -3
  58. package/dist/utilities/analytics/reference/index.js +26 -18
  59. package/dist/utilities/symbolTools.d.ts +4 -2
  60. package/dist/utilities/symbolTools.js +16 -15
  61. package/dist/utils/io.d.ts +24 -6
  62. package/dist/utils/io.js +64 -14
  63. package/dist/utils/sqlite.d.ts +2 -0
  64. package/dist/utils/sqlite.js +6 -8
  65. package/dist/utils/zip.d.ts +7 -3
  66. package/dist/utils/zip.js +45 -43
  67. package/dist/validation/applePanelsValidator.d.ts +2 -1
  68. package/dist/validation/applePanelsValidator.js +9 -11
  69. package/dist/validation/astericsValidator.d.ts +2 -1
  70. package/dist/validation/astericsValidator.js +5 -4
  71. package/dist/validation/baseValidator.d.ts +2 -2
  72. package/dist/validation/baseValidator.js +5 -0
  73. package/dist/validation/dotValidator.d.ts +2 -1
  74. package/dist/validation/dotValidator.js +5 -4
  75. package/dist/validation/excelValidator.d.ts +2 -1
  76. package/dist/validation/excelValidator.js +5 -4
  77. package/dist/validation/gridsetValidator.d.ts +2 -1
  78. package/dist/validation/gridsetValidator.js +11 -22
  79. package/dist/validation/index.d.ts +2 -2
  80. package/dist/validation/index.js +5 -4
  81. package/dist/validation/obfValidator.d.ts +2 -1
  82. package/dist/validation/obfValidator.js +5 -4
  83. package/dist/validation/obfsetValidator.d.ts +2 -1
  84. package/dist/validation/obfsetValidator.js +5 -4
  85. package/dist/validation/opmlValidator.d.ts +2 -1
  86. package/dist/validation/opmlValidator.js +5 -4
  87. package/dist/validation/snapValidator.d.ts +2 -1
  88. package/dist/validation/snapValidator.js +9 -5
  89. package/dist/validation/touchChatValidator.d.ts +4 -6
  90. package/dist/validation/touchChatValidator.js +21 -11
  91. package/dist/validation/validationTypes.d.ts +8 -1
  92. package/package.json +1 -1
  93. package/dist/core/fileProcessor.d.ts +0 -7
  94. package/dist/core/fileProcessor.js +0 -57
@@ -22,15 +22,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
26
  exports.GridsetValidator = void 0;
30
27
  /* eslint-disable @typescript-eslint/require-await */
31
28
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
32
29
  /* eslint-disable @typescript-eslint/no-unsafe-return */
33
- const jszip_1 = __importDefault(require("jszip"));
34
30
  const xml2js = __importStar(require("xml2js"));
35
31
  const baseValidator_1 = require("./baseValidator");
36
32
  const io_1 = require("../utils/io");
@@ -44,12 +40,12 @@ class GridsetValidator extends baseValidator_1.BaseValidator {
44
40
  /**
45
41
  * Validate a Gridset file from disk
46
42
  */
47
- static async validateFile(filePath) {
43
+ static async validateFile(filePath, fileAdapter) {
44
+ const { readBinaryFromInput, getFileSize } = fileAdapter ?? io_1.defaultFileAdapter;
48
45
  const validator = new GridsetValidator();
49
- const fs = (0, io_1.getFs)();
50
- const content = fs.readFileSync(filePath);
51
- const stats = fs.statSync(filePath);
52
- return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
46
+ const content = readBinaryFromInput(filePath);
47
+ const size = getFileSize(filePath);
48
+ return validator.validate(content, (0, io_1.getBasename)(filePath), size);
53
49
  }
54
50
  /**
55
51
  * Check if content is Gridset format
@@ -138,24 +134,17 @@ class GridsetValidator extends baseValidator_1.BaseValidator {
138
134
  * Validate a ZIP archive (.gridset)
139
135
  */
140
136
  async validateZipArchive(content, filename, _filesize) {
141
- let zip;
142
- try {
143
- zip = await jszip_1.default.loadAsync((0, io_1.toUint8Array)(content));
144
- }
145
- catch (e) {
146
- this.err(`Failed to open ZIP archive: ${e.message}`, true);
147
- return;
148
- }
149
- const entries = Object.values(zip.files).filter((entry) => !entry.dir);
137
+ const zip = await this._options.zipAdapter(content);
138
+ const entries = zip.listFiles();
150
139
  // Check for gridset.xml (required)
151
140
  await this.add_check('gridset_xml_presence', 'gridset.xml presence', async () => {
152
- const gridsetEntry = entries.find((e) => e.name.toLowerCase() === 'gridset.xml');
141
+ const gridsetEntry = entries.find((e) => e.toLowerCase() === 'gridset.xml');
153
142
  if (!gridsetEntry) {
154
143
  this.err('Missing gridset.xml in archive', true);
155
144
  }
156
145
  else {
157
146
  try {
158
- const gridsetXml = await gridsetEntry.async('string');
147
+ const gridsetXml = await zip.readFile(gridsetEntry);
159
148
  const parser = new xml2js.Parser();
160
149
  const xmlObj = await parser.parseStringPromise(gridsetXml);
161
150
  const gridset = xmlObj.gridset || xmlObj.Gridset;
@@ -173,13 +162,13 @@ class GridsetValidator extends baseValidator_1.BaseValidator {
173
162
  });
174
163
  // Check for settings.xml (highly recommended/required for metadata)
175
164
  await this.add_check('settings_xml_presence', 'settings.xml presence', async () => {
176
- const settingsEntry = entries.find((e) => e.name.toLowerCase() === 'settings.xml');
165
+ const settingsEntry = entries.find((e) => e.toLowerCase() === 'settings.xml');
177
166
  if (!settingsEntry) {
178
167
  this.warn('Missing settings.xml in archive (required for full metadata)');
179
168
  }
180
169
  else {
181
170
  try {
182
- const settingsXml = await settingsEntry.async('string');
171
+ const settingsXml = await zip.readFile(settingsEntry);
183
172
  const parser = new xml2js.Parser();
184
173
  const xmlObj = await parser.parseStringPromise(settingsXml);
185
174
  const settings = xmlObj.GridSetSettings || xmlObj.gridSetSettings || xmlObj.GridsetSettings;
@@ -16,7 +16,7 @@ export { ApplePanelsValidator } from './applePanelsValidator';
16
16
  export { ObfsetValidator } from './obfsetValidator';
17
17
  import { BaseValidator } from './baseValidator';
18
18
  import { ValidationResult } from './validationTypes';
19
- import { type ProcessorInput } from '../utils/io';
19
+ import { FileAdapter, type ProcessorInput } from '../utils/io';
20
20
  export declare function getValidatorForFormat(format: string): BaseValidator | null;
21
21
  export declare function getValidatorForFile(filename: string): BaseValidator | null;
22
22
  /**
@@ -24,4 +24,4 @@ export declare function getValidatorForFile(filename: string): BaseValidator | n
24
24
  * When a file path is provided, any validator-specific validateFile() helper
25
25
  * will be used if available to access nested resources.
26
26
  */
27
- export declare function validateFileOrBuffer(filePathOrBuffer: ProcessorInput, filenameHint?: string): Promise<ValidationResult>;
27
+ export declare function validateFileOrBuffer(filePathOrBuffer: ProcessorInput, fileAdapter?: FileAdapter, filenameHint?: string): Promise<ValidationResult>;
@@ -125,10 +125,11 @@ function getValidatorForFile(filename) {
125
125
  * When a file path is provided, any validator-specific validateFile() helper
126
126
  * will be used if available to access nested resources.
127
127
  */
128
- async function validateFileOrBuffer(filePathOrBuffer, filenameHint) {
128
+ async function validateFileOrBuffer(filePathOrBuffer, fileAdapter, filenameHint) {
129
129
  const isPath = typeof filePathOrBuffer === 'string';
130
130
  const name = filenameHint || (isPath ? (0, io_1.getBasename)(filePathOrBuffer) : 'upload');
131
131
  const validator = getValidatorForFile(name) || getValidatorForFormat(name);
132
+ const adapter = fileAdapter ?? io_1.defaultFileAdapter;
132
133
  if (!validator) {
133
134
  throw new Error(`No validator registered for ${name}`);
134
135
  }
@@ -140,9 +141,9 @@ async function validateFileOrBuffer(filePathOrBuffer, filenameHint) {
140
141
  if (typeof ctor.validateFile === 'function') {
141
142
  return ctor.validateFile(filePathOrBuffer);
142
143
  }
143
- const buf = (0, io_1.readBinaryFromInput)(filePathOrBuffer);
144
- const stats = (0, io_1.getFs)().statSync(filePathOrBuffer);
145
- return validator.validate(buf, (0, io_1.getBasename)(filePathOrBuffer), stats.size);
144
+ const buf = adapter.readBinaryFromInput(filePathOrBuffer);
145
+ const size = adapter.getFileSize(filePathOrBuffer);
146
+ return validator.validate(buf, (0, io_1.getBasename)(filePathOrBuffer), size);
146
147
  }
147
148
  const buffer = (0, io_1.toUint8Array)(filePathOrBuffer);
148
149
  return validator.validate(buffer, name, buffer.byteLength);
@@ -1,5 +1,6 @@
1
1
  import { BaseValidator } from './baseValidator';
2
2
  import { ValidationResult } from './validationTypes';
3
+ import { FileAdapter } from '../utils/io';
3
4
  /**
4
5
  * Validator for Open Board Format (OBF/OBZ) files
5
6
  */
@@ -8,7 +9,7 @@ export declare class ObfValidator extends BaseValidator {
8
9
  /**
9
10
  * Validate an OBF file from disk
10
11
  */
11
- static validateFile(filePath: string): Promise<ValidationResult>;
12
+ static validateFile(filePath: string, fileAdapter?: FileAdapter): Promise<ValidationResult>;
12
13
  /**
13
14
  * Check if content is OBF format
14
15
  */
@@ -24,11 +24,12 @@ class ObfValidator extends baseValidator_1.BaseValidator {
24
24
  /**
25
25
  * Validate an OBF file from disk
26
26
  */
27
- static async validateFile(filePath) {
27
+ static async validateFile(filePath, fileAdapter) {
28
+ const { readBinaryFromInput, getFileSize } = fileAdapter ?? io_1.defaultFileAdapter;
28
29
  const validator = new ObfValidator();
29
- const content = (0, io_1.readBinaryFromInput)(filePath);
30
- const stats = (0, io_1.getFs)().statSync(filePath);
31
- return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
30
+ const content = readBinaryFromInput(filePath);
31
+ const size = getFileSize(filePath);
32
+ return validator.validate(content, (0, io_1.getBasename)(filePath), size);
32
33
  }
33
34
  /**
34
35
  * Check if content is OBF format
@@ -1,10 +1,11 @@
1
1
  import { BaseValidator } from './baseValidator';
2
2
  import { ValidationResult } from './validationTypes';
3
+ import { FileAdapter } from '../utils/io';
3
4
  /**
4
5
  * Validator for OBF set bundles (.obfset) - JSON arrays of boards
5
6
  */
6
7
  export declare class ObfsetValidator extends BaseValidator {
7
- static validateFile(filePath: string): Promise<ValidationResult>;
8
+ static validateFile(filePath: string, fileAdapter?: FileAdapter): Promise<ValidationResult>;
8
9
  static identifyFormat(content: any, filename: string): Promise<boolean>;
9
10
  validate(content: Buffer | Uint8Array, filename: string, filesize: number): Promise<ValidationResult>;
10
11
  }
@@ -8,11 +8,12 @@ const io_1 = require("../utils/io");
8
8
  * Validator for OBF set bundles (.obfset) - JSON arrays of boards
9
9
  */
10
10
  class ObfsetValidator extends baseValidator_1.BaseValidator {
11
- static async validateFile(filePath) {
11
+ static async validateFile(filePath, fileAdapter) {
12
+ const { readBinaryFromInput, getFileSize } = fileAdapter ?? io_1.defaultFileAdapter;
12
13
  const validator = new ObfsetValidator();
13
- const content = (0, io_1.readBinaryFromInput)(filePath);
14
- const stats = (0, io_1.getFs)().statSync(filePath);
15
- return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
14
+ const content = readBinaryFromInput(filePath);
15
+ const size = getFileSize(filePath);
16
+ return validator.validate(content, (0, io_1.getBasename)(filePath), size);
16
17
  }
17
18
  static async identifyFormat(content, filename) {
18
19
  const name = filename.toLowerCase();
@@ -1,10 +1,11 @@
1
1
  import { BaseValidator } from './baseValidator';
2
2
  import { ValidationResult } from './validationTypes';
3
+ import { FileAdapter } from '../utils/io';
3
4
  /**
4
5
  * Validator for OPML files
5
6
  */
6
7
  export declare class OpmlValidator extends BaseValidator {
7
- static validateFile(filePath: string): Promise<ValidationResult>;
8
+ static validateFile(filePath: string, fileAdapter?: FileAdapter): Promise<ValidationResult>;
8
9
  static identifyFormat(content: any, filename: string): Promise<boolean>;
9
10
  validate(content: Buffer | Uint8Array, filename: string, filesize: number): Promise<ValidationResult>;
10
11
  }
@@ -9,11 +9,12 @@ const io_1 = require("../utils/io");
9
9
  * Validator for OPML files
10
10
  */
11
11
  class OpmlValidator extends baseValidator_1.BaseValidator {
12
- static async validateFile(filePath) {
12
+ static async validateFile(filePath, fileAdapter) {
13
+ const { readBinaryFromInput, getFileSize } = fileAdapter ?? io_1.defaultFileAdapter;
13
14
  const validator = new OpmlValidator();
14
- const content = (0, io_1.readBinaryFromInput)(filePath);
15
- const stats = (0, io_1.getFs)().statSync(filePath);
16
- return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
15
+ const content = readBinaryFromInput(filePath);
16
+ const size = getFileSize(filePath);
17
+ return validator.validate(content, (0, io_1.getBasename)(filePath), size);
17
18
  }
18
19
  static async identifyFormat(content, filename) {
19
20
  const name = filename.toLowerCase();
@@ -1,5 +1,6 @@
1
1
  import { BaseValidator } from './baseValidator';
2
2
  import { ValidationResult } from './validationTypes';
3
+ import { FileAdapter } from '../utils/io';
3
4
  /**
4
5
  * Validator for Snap files (.spb, .sps)
5
6
  * Snap files are zipped packages containing XML configuration
@@ -9,7 +10,7 @@ export declare class SnapValidator extends BaseValidator {
9
10
  /**
10
11
  * Validate a Snap file from disk
11
12
  */
12
- static validateFile(filePath: string): Promise<ValidationResult>;
13
+ static validateFile(filePath: string, fileAdapter?: FileAdapter): Promise<ValidationResult>;
13
14
  /**
14
15
  * Check if content is Snap format
15
16
  */
@@ -45,11 +45,12 @@ class SnapValidator extends baseValidator_1.BaseValidator {
45
45
  /**
46
46
  * Validate a Snap file from disk
47
47
  */
48
- static async validateFile(filePath) {
48
+ static async validateFile(filePath, fileAdapter) {
49
+ const { readBinaryFromInput, getFileSize } = fileAdapter ?? io_1.defaultFileAdapter;
49
50
  const validator = new SnapValidator();
50
- const content = (0, io_1.readBinaryFromInput)(filePath);
51
- const stats = (0, io_1.getFs)().statSync(filePath);
52
- return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
51
+ const content = readBinaryFromInput(filePath);
52
+ const size = getFileSize(filePath);
53
+ return validator.validate(content, (0, io_1.getBasename)(filePath), size);
53
54
  }
54
55
  /**
55
56
  * Check if content is Snap format
@@ -187,7 +188,10 @@ class SnapValidator extends baseValidator_1.BaseValidator {
187
188
  await this.add_check('sqlite', 'valid SQLite database', async () => {
188
189
  let cleanup;
189
190
  try {
190
- const result = await (0, sqlite_1.openSqliteDatabase)(content, { readonly: true });
191
+ const result = await (0, sqlite_1.openSqliteDatabase)(content, {
192
+ readonly: true,
193
+ fileAdapter: this._options.fileAdapter,
194
+ });
191
195
  const db = result.db;
192
196
  cleanup = result.cleanup;
193
197
  const tableRows = db
@@ -1,7 +1,7 @@
1
1
  import { BaseValidator } from './baseValidator';
2
2
  import { ValidationResult } from './validationTypes';
3
- import { type ProcessorInput } from '../utils/io';
4
- import { type ZipAdapter } from '../utils/zip';
3
+ import { FileAdapter, type ProcessorInput } from '../utils/io';
4
+ import { ZipAdapter } from '../utils/zip';
5
5
  /**
6
6
  * Validator for TouchChat files (.ce)
7
7
  * TouchChat files are ZIP archives that contain a .c4v SQLite database.
@@ -12,13 +12,11 @@ export declare class TouchChatValidator extends BaseValidator {
12
12
  /**
13
13
  * Validate a TouchChat file from disk
14
14
  */
15
- static validateFile(filePath: string): Promise<ValidationResult>;
15
+ static validateFile(filePath: string, fileAdapter?: FileAdapter): Promise<ValidationResult>;
16
16
  /**
17
17
  * Check if content is TouchChat format
18
18
  */
19
- static identifyFormat(content: any, filename: string, zipAdapter?: (input: ProcessorInput) => Promise<{
20
- zip: ZipAdapter;
21
- }>): Promise<boolean>;
19
+ static identifyFormat(content: any, filename: string, fileAdapter?: FileAdapter, zipAdapter?: (input: ProcessorInput) => Promise<ZipAdapter>): Promise<boolean>;
22
20
  /**
23
21
  * Main validation method
24
22
  */
@@ -30,8 +30,8 @@ exports.TouchChatValidator = void 0;
30
30
  const xml2js = __importStar(require("xml2js"));
31
31
  const baseValidator_1 = require("./baseValidator");
32
32
  const io_1 = require("../utils/io");
33
- const zip_1 = require("../utils/zip");
34
33
  const sqlite_1 = require("../utils/sqlite");
34
+ const zip_1 = require("../utils/zip");
35
35
  /**
36
36
  * Validator for TouchChat files (.ce)
37
37
  * TouchChat files are ZIP archives that contain a .c4v SQLite database.
@@ -44,23 +44,26 @@ class TouchChatValidator extends baseValidator_1.BaseValidator {
44
44
  /**
45
45
  * Validate a TouchChat file from disk
46
46
  */
47
- static async validateFile(filePath) {
47
+ static async validateFile(filePath, fileAdapter) {
48
+ const { readBinaryFromInput, getFileSize } = fileAdapter ?? io_1.defaultFileAdapter;
48
49
  const validator = new TouchChatValidator();
49
- const content = (0, io_1.readBinaryFromInput)(filePath);
50
- const stats = (0, io_1.getFs)().statSync(filePath);
51
- return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
50
+ const content = readBinaryFromInput(filePath);
51
+ const size = getFileSize(filePath);
52
+ return validator.validate(content, (0, io_1.getBasename)(filePath), size);
52
53
  }
53
54
  /**
54
55
  * Check if content is TouchChat format
55
56
  */
56
- static async identifyFormat(content, filename, zipAdapter) {
57
+ static async identifyFormat(content, filename, fileAdapter = io_1.defaultFileAdapter, zipAdapter) {
57
58
  const name = filename.toLowerCase();
58
59
  if (name.endsWith('.ce')) {
59
60
  return true;
60
61
  }
61
62
  // Try to parse as ZIP and check for .c4v database
62
63
  try {
63
- const { zip } = zipAdapter ? await zipAdapter(content) : await (0, zip_1.openZipFromInput)(content);
64
+ const zip = zipAdapter
65
+ ? await zipAdapter(content)
66
+ : await (0, zip_1.getZipAdapter)(content, fileAdapter);
64
67
  const entries = zip.listFiles();
65
68
  if (entries.some((entry) => entry.toLowerCase().endsWith('.c4v'))) {
66
69
  return true;
@@ -92,7 +95,9 @@ class TouchChatValidator extends baseValidator_1.BaseValidator {
92
95
  }
93
96
  });
94
97
  const looksLikeXml = this.isXmlBuffer(content);
95
- const zipped = looksLikeXml ? false : await this.tryValidateZipSqlite(content);
98
+ const zipped = looksLikeXml
99
+ ? false
100
+ : await this.tryValidateZipSqlite(content, this._options.fileAdapter, this._options.zipAdapter);
96
101
  if (!zipped) {
97
102
  let xmlObj = null;
98
103
  await this.add_check('xml_parse', 'valid XML', async () => {
@@ -272,11 +277,13 @@ class TouchChatValidator extends baseValidator_1.BaseValidator {
272
277
  }
273
278
  return bytes[start] === 0x3c; // '<'
274
279
  }
275
- async tryValidateZipSqlite(content) {
280
+ async tryValidateZipSqlite(content, fileAdapter = io_1.defaultFileAdapter, zipAdapter) {
276
281
  let usedZip = false;
277
282
  await this.add_check('zip', 'TouchChat ZIP package', async () => {
278
283
  try {
279
- const { zip } = await (0, zip_1.openZipFromInput)(content);
284
+ const zip = zipAdapter
285
+ ? await zipAdapter(content)
286
+ : await (0, zip_1.getZipAdapter)(content, fileAdapter);
280
287
  const entries = zip.listFiles();
281
288
  const vocabEntry = entries.find((name) => name.toLowerCase().endsWith('.c4v'));
282
289
  if (!vocabEntry) {
@@ -301,7 +308,10 @@ class TouchChatValidator extends baseValidator_1.BaseValidator {
301
308
  await this.add_check('sqlite', 'valid TouchChat SQLite database', async () => {
302
309
  let cleanup;
303
310
  try {
304
- const result = await (0, sqlite_1.openSqliteDatabase)(content, { readonly: true });
311
+ const result = await (0, sqlite_1.openSqliteDatabase)(content, {
312
+ readonly: true,
313
+ fileAdapter: this._options.fileAdapter,
314
+ });
305
315
  const db = result.db;
306
316
  cleanup = result.cleanup;
307
317
  const tableRows = db
@@ -1,3 +1,5 @@
1
+ import { FileAdapter, ProcessorInput } from '../utils/io';
2
+ import { ZipAdapter } from '../utils/zip';
1
3
  /**
2
4
  * Custom error class for validation errors
3
5
  * Can be marked as a blocker to stop validation immediately
@@ -45,14 +47,19 @@ export interface ValidationResult {
45
47
  /**
46
48
  * Options for validation behavior
47
49
  */
48
- export interface ValidationOptions {
50
+ export interface ValidationConfig {
49
51
  /** Whether to include warnings in validation (default: true) */
50
52
  includeWarnings?: boolean;
51
53
  /** Whether to stop on first blocker error (default: true) */
52
54
  stopOnBlocker?: boolean;
53
55
  /** Custom validation rules to apply */
54
56
  customRules?: ValidationRule[];
57
+ /** Adapter for handling file IO (optional) */
58
+ fileAdapter: FileAdapter;
59
+ /** Adapter for handling ZIP files (optional) */
60
+ zipAdapter: (input: ProcessorInput) => Promise<ZipAdapter>;
55
61
  }
62
+ export type ValidationOptions = Partial<ValidationConfig>;
56
63
  /**
57
64
  * Custom validation rule that can be added
58
65
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willwade/aac-processors",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "A comprehensive TypeScript library for processing AAC (Augmentative and Alternative Communication) file formats with translation support",
5
5
  "main": "dist/index.js",
6
6
  "browser": "dist/browser/index.browser.js",
@@ -1,7 +0,0 @@
1
- type FileFormat = 'gridset' | 'coughdrop' | 'touchchat' | 'snap' | 'dot' | 'opml' | 'excel' | 'unknown';
2
- declare class FileProcessor {
3
- static readFile(filePath: string): Buffer;
4
- static writeFile(filePath: string, data: Buffer | string): void;
5
- static detectFormat(filePathOrBuffer: string | Buffer): FileFormat;
6
- }
7
- export default FileProcessor;
@@ -1,57 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
- class FileProcessor {
9
- // Read a file and return its contents as a Buffer
10
- static readFile(filePath) {
11
- return fs_1.default.readFileSync(filePath);
12
- }
13
- // Write data (Buffer or string) to a file
14
- static writeFile(filePath, data) {
15
- fs_1.default.writeFileSync(filePath, data);
16
- }
17
- // Detect file format based on extension or magic bytes
18
- static detectFormat(filePathOrBuffer) {
19
- if (typeof filePathOrBuffer === 'string') {
20
- const ext = path_1.default.extname(filePathOrBuffer).toLowerCase();
21
- const fileName = path_1.default.basename(filePathOrBuffer).toLowerCase();
22
- // Handle double extensions like .sub.zip
23
- if (fileName.endsWith('.sub.zip') || ext === '.sub') {
24
- return 'snap';
25
- }
26
- switch (ext) {
27
- case '.gridset':
28
- case '.gridsetx':
29
- return 'gridset';
30
- case '.obf':
31
- case '.obz':
32
- return 'coughdrop';
33
- case '.ce':
34
- case '.wfl':
35
- case '.touchchat':
36
- return 'touchchat';
37
- case '.sps':
38
- case '.spb':
39
- return 'snap';
40
- case '.dot':
41
- return 'dot';
42
- case '.opml':
43
- return 'opml';
44
- case '.xlsx':
45
- return 'excel';
46
- default:
47
- return 'unknown';
48
- }
49
- }
50
- else if (Buffer.isBuffer(filePathOrBuffer)) {
51
- // Optionally: inspect magic bytes here
52
- return 'unknown';
53
- }
54
- return 'unknown';
55
- }
56
- }
57
- exports.default = FileProcessor;