@willwade/aac-processors 0.1.20 → 0.2.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 (113) hide show
  1. package/dist/browser/core/baseProcessor.js +4 -0
  2. package/dist/browser/processors/applePanelsProcessor.js +33 -40
  3. package/dist/browser/processors/astericsGridProcessor.js +31 -26
  4. package/dist/browser/processors/dotProcessor.js +11 -12
  5. package/dist/browser/processors/gridset/colorUtils.js +354 -0
  6. package/dist/browser/processors/gridset/helpers.js +60 -53
  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 +39 -72
  12. package/dist/browser/processors/gridsetProcessor.js +39 -48
  13. package/dist/browser/processors/obfProcessor.js +39 -53
  14. package/dist/browser/processors/opmlProcessor.js +11 -12
  15. package/dist/browser/processors/snap/helpers.js +57 -49
  16. package/dist/browser/processors/snapProcessor.js +48 -51
  17. package/dist/browser/processors/touchchatProcessor.js +60 -52
  18. package/dist/browser/utilities/analytics/history.js +24 -18
  19. package/dist/browser/utilities/analytics/metrics/comparison.js +16 -16
  20. package/dist/browser/utilities/analytics/metrics/vocabulary.js +2 -2
  21. package/dist/browser/utilities/analytics/reference/browser.js +16 -16
  22. package/dist/browser/utilities/analytics/reference/index.js +44 -35
  23. package/dist/browser/utils/io.js +78 -21
  24. package/dist/browser/utils/sqlite.js +8 -10
  25. package/dist/browser/utils/zip.js +43 -43
  26. package/dist/browser/validation/baseValidator.js +5 -0
  27. package/dist/browser/validation/gridsetValidator.js +12 -20
  28. package/dist/browser/validation/obfValidator.js +6 -5
  29. package/dist/browser/validation/snapValidator.js +11 -7
  30. package/dist/browser/validation/touchChatValidator.js +23 -13
  31. package/dist/cli/index.js +22 -24
  32. package/dist/core/baseProcessor.d.ts +7 -7
  33. package/dist/core/baseProcessor.js +4 -0
  34. package/dist/processors/applePanelsProcessor.js +32 -39
  35. package/dist/processors/astericsGridProcessor.d.ts +4 -4
  36. package/dist/processors/astericsGridProcessor.js +30 -25
  37. package/dist/processors/dotProcessor.js +10 -11
  38. package/dist/processors/excelProcessor.d.ts +3 -3
  39. package/dist/processors/excelProcessor.js +14 -20
  40. package/dist/processors/gridset/helpers.d.ts +12 -14
  41. package/dist/processors/gridset/helpers.js +60 -79
  42. package/dist/processors/gridset/imageDebug.d.ts +3 -5
  43. package/dist/processors/gridset/imageDebug.js +4 -4
  44. package/dist/processors/gridset/password.d.ts +1 -1
  45. package/dist/processors/gridset/symbolExtractor.d.ts +5 -3
  46. package/dist/processors/gridset/symbolExtractor.js +15 -38
  47. package/dist/processors/gridset/symbolSearch.d.ts +11 -10
  48. package/dist/processors/gridset/symbolSearch.js +29 -51
  49. package/dist/processors/gridset/symbols.d.ts +8 -6
  50. package/dist/processors/gridset/symbols.js +38 -71
  51. package/dist/processors/gridset/wordlistHelpers.d.ts +4 -6
  52. package/dist/processors/gridset/wordlistHelpers.js +15 -74
  53. package/dist/processors/gridsetProcessor.d.ts +2 -2
  54. package/dist/processors/gridsetProcessor.js +38 -70
  55. package/dist/processors/obfProcessor.d.ts +2 -2
  56. package/dist/processors/obfProcessor.js +38 -75
  57. package/dist/processors/obfsetProcessor.js +2 -3
  58. package/dist/processors/opmlProcessor.js +10 -11
  59. package/dist/processors/snap/helpers.d.ts +9 -9
  60. package/dist/processors/snap/helpers.js +58 -76
  61. package/dist/processors/snapProcessor.d.ts +2 -2
  62. package/dist/processors/snapProcessor.js +47 -50
  63. package/dist/processors/touchchatProcessor.d.ts +2 -2
  64. package/dist/processors/touchchatProcessor.js +59 -51
  65. package/dist/types/aac.d.ts +2 -2
  66. package/dist/utilities/analytics/history.d.ts +8 -8
  67. package/dist/utilities/analytics/history.js +24 -18
  68. package/dist/utilities/analytics/index.d.ts +3 -2
  69. package/dist/utilities/analytics/index.js +9 -10
  70. package/dist/utilities/analytics/metrics/comparison.d.ts +1 -1
  71. package/dist/utilities/analytics/metrics/comparison.js +16 -16
  72. package/dist/utilities/analytics/metrics/vocabulary.d.ts +1 -1
  73. package/dist/utilities/analytics/metrics/vocabulary.js +2 -2
  74. package/dist/utilities/analytics/reference/browser.d.ts +9 -9
  75. package/dist/utilities/analytics/reference/browser.js +16 -16
  76. package/dist/utilities/analytics/reference/index.d.ts +25 -23
  77. package/dist/utilities/analytics/reference/index.js +43 -34
  78. package/dist/utilities/symbolTools.d.ts +8 -6
  79. package/dist/utilities/symbolTools.js +21 -18
  80. package/dist/utils/io.d.ts +24 -6
  81. package/dist/utils/io.js +79 -25
  82. package/dist/utils/sqlite.d.ts +3 -1
  83. package/dist/utils/sqlite.js +7 -9
  84. package/dist/utils/zip.d.ts +7 -3
  85. package/dist/utils/zip.js +43 -43
  86. package/dist/validation/applePanelsValidator.d.ts +2 -1
  87. package/dist/validation/applePanelsValidator.js +10 -11
  88. package/dist/validation/astericsValidator.d.ts +2 -1
  89. package/dist/validation/astericsValidator.js +5 -4
  90. package/dist/validation/baseValidator.d.ts +2 -2
  91. package/dist/validation/baseValidator.js +5 -0
  92. package/dist/validation/dotValidator.d.ts +2 -1
  93. package/dist/validation/dotValidator.js +5 -4
  94. package/dist/validation/excelValidator.d.ts +2 -1
  95. package/dist/validation/excelValidator.js +5 -4
  96. package/dist/validation/gridsetValidator.d.ts +2 -1
  97. package/dist/validation/gridsetValidator.js +11 -22
  98. package/dist/validation/index.d.ts +2 -2
  99. package/dist/validation/index.js +5 -4
  100. package/dist/validation/obfValidator.d.ts +2 -1
  101. package/dist/validation/obfValidator.js +5 -4
  102. package/dist/validation/obfsetValidator.d.ts +2 -1
  103. package/dist/validation/obfsetValidator.js +5 -4
  104. package/dist/validation/opmlValidator.d.ts +2 -1
  105. package/dist/validation/opmlValidator.js +5 -4
  106. package/dist/validation/snapValidator.d.ts +2 -1
  107. package/dist/validation/snapValidator.js +10 -6
  108. package/dist/validation/touchChatValidator.d.ts +4 -6
  109. package/dist/validation/touchChatValidator.js +22 -12
  110. package/dist/validation/validationTypes.d.ts +8 -1
  111. package/package.json +1 -1
  112. package/dist/core/fileProcessor.d.ts +0 -7
  113. package/dist/core/fileProcessor.js +0 -57
@@ -5,17 +5,18 @@
5
5
  * for AAC metrics analysis.
6
6
  */
7
7
  import { CoreList, CommonWordsData, SynonymsData } from '../metrics/types';
8
+ import { FileAdapter } from '../../../utils/io';
8
9
  export interface ReferenceDataProvider {
9
- loadCoreLists(): CoreList[];
10
- loadCommonWords(): CommonWordsData;
11
- loadSynonyms(): SynonymsData;
12
- loadSentences(): string[][];
13
- loadFringe(): string[];
14
- loadBaseWords(): {
10
+ loadCoreLists(): Promise<CoreList[]>;
11
+ loadCommonWords(): Promise<CommonWordsData>;
12
+ loadSynonyms(): Promise<SynonymsData>;
13
+ loadSentences(): Promise<string[][]>;
14
+ loadFringe(): Promise<string[]>;
15
+ loadBaseWords(): Promise<{
15
16
  [word: string]: boolean;
16
- };
17
- loadCommonFringe(): string[];
18
- loadAll(): {
17
+ }>;
18
+ loadCommonFringe(): Promise<string[]>;
19
+ loadAll(): Promise<{
19
20
  coreLists: CoreList[];
20
21
  commonWords: CommonWordsData;
21
22
  synonyms: SynonymsData;
@@ -24,48 +25,49 @@ export interface ReferenceDataProvider {
24
25
  baseWords: {
25
26
  [word: string]: boolean;
26
27
  };
27
- };
28
+ }>;
28
29
  }
29
30
  export declare class ReferenceLoader {
30
31
  private dataDir;
31
32
  private locale;
32
- constructor(dataDir?: string, locale?: string);
33
+ private fileAdapter;
34
+ constructor(dataDir?: string, locale?: string, fileAdapter?: FileAdapter);
33
35
  /**
34
36
  * Load core vocabulary lists
35
37
  */
36
- loadCoreLists(): CoreList[];
38
+ loadCoreLists(): Promise<CoreList[]>;
37
39
  /**
38
40
  * Load common words with baseline effort scores
39
41
  */
40
- loadCommonWords(): CommonWordsData;
42
+ loadCommonWords(): Promise<CommonWordsData>;
41
43
  /**
42
44
  * Load synonym mappings
43
45
  */
44
- loadSynonyms(): SynonymsData;
46
+ loadSynonyms(): Promise<SynonymsData>;
45
47
  /**
46
48
  * Load test sentences
47
49
  */
48
- loadSentences(): string[][];
50
+ loadSentences(): Promise<string[][]>;
49
51
  /**
50
52
  * Load fringe vocabulary
51
53
  */
52
- loadFringe(): string[];
54
+ loadFringe(): Promise<string[]>;
53
55
  /**
54
56
  * Load base words hash map
55
57
  */
56
- loadBaseWords(): {
58
+ loadBaseWords(): Promise<{
57
59
  [word: string]: boolean;
58
- };
60
+ }>;
59
61
  /**
60
62
  * Load common fringe vocabulary
61
63
  * Common words that are NOT in core vocabulary lists
62
64
  * (matching Ruby loader.rb:413-420)
63
65
  */
64
- loadCommonFringe(): string[];
66
+ loadCommonFringe(): Promise<string[]>;
65
67
  /**
66
68
  * Get all reference data at once
67
69
  */
68
- loadAll(): {
70
+ loadAll(): Promise<{
69
71
  coreLists: CoreList[];
70
72
  commonWords: CommonWordsData;
71
73
  synonyms: SynonymsData;
@@ -74,13 +76,13 @@ export declare class ReferenceLoader {
74
76
  baseWords: {
75
77
  [word: string]: boolean;
76
78
  };
77
- };
79
+ }>;
78
80
  }
79
81
  /**
80
82
  * Get the default reference data path
81
83
  */
82
- export declare function getReferenceDataPath(): string;
84
+ export declare function getReferenceDataPath(fileAdapter?: FileAdapter): string;
83
85
  /**
84
86
  * Check if reference data files exist
85
87
  */
86
- export declare function hasReferenceData(): boolean;
88
+ export declare function hasReferenceData(fileAdapter?: FileAdapter): Promise<boolean>;
@@ -11,55 +11,61 @@ exports.getReferenceDataPath = getReferenceDataPath;
11
11
  exports.hasReferenceData = hasReferenceData;
12
12
  const io_1 = require("../../../utils/io");
13
13
  class ReferenceLoader {
14
- constructor(dataDir, locale = 'en') {
14
+ constructor(dataDir, locale = 'en', fileAdapter = io_1.defaultFileAdapter) {
15
15
  this.locale = locale;
16
+ this.fileAdapter = fileAdapter;
16
17
  if (dataDir) {
17
18
  this.dataDir = dataDir;
18
19
  }
19
20
  else {
20
21
  // Resolve the data directory relative to this file's location
21
22
  // Use __dirname which works correctly after compilation
22
- this.dataDir = (0, io_1.getPath)().join(__dirname, 'data');
23
+ this.dataDir = this.fileAdapter.join(__dirname, 'data');
23
24
  }
24
25
  }
25
26
  /**
26
27
  * Load core vocabulary lists
27
28
  */
28
- loadCoreLists() {
29
- const filePath = (0, io_1.getPath)().join(this.dataDir, `core_lists.${this.locale}.json`);
30
- const content = (0, io_1.getFs)().readFileSync(filePath, 'utf-8');
29
+ async loadCoreLists() {
30
+ const { readTextFromInput } = this.fileAdapter;
31
+ const filePath = this.fileAdapter.join(this.dataDir, `core_lists.${this.locale}.json`);
32
+ const content = await readTextFromInput(filePath);
31
33
  return JSON.parse(String(content));
32
34
  }
33
35
  /**
34
36
  * Load common words with baseline effort scores
35
37
  */
36
- loadCommonWords() {
37
- const filePath = (0, io_1.getPath)().join(this.dataDir, `common_words.${this.locale}.json`);
38
- const content = (0, io_1.getFs)().readFileSync(filePath, 'utf-8');
38
+ async loadCommonWords() {
39
+ const { readTextFromInput, join } = this.fileAdapter;
40
+ const filePath = join(this.dataDir, `common_words.${this.locale}.json`);
41
+ const content = await readTextFromInput(filePath);
39
42
  return JSON.parse(String(content));
40
43
  }
41
44
  /**
42
45
  * Load synonym mappings
43
46
  */
44
- loadSynonyms() {
45
- const filePath = (0, io_1.getPath)().join(this.dataDir, `synonyms.${this.locale}.json`);
46
- const content = (0, io_1.getFs)().readFileSync(filePath, 'utf-8');
47
+ async loadSynonyms() {
48
+ const { readTextFromInput, join } = this.fileAdapter;
49
+ const filePath = join(this.dataDir, `synonyms.${this.locale}.json`);
50
+ const content = await readTextFromInput(filePath);
47
51
  return JSON.parse(String(content));
48
52
  }
49
53
  /**
50
54
  * Load test sentences
51
55
  */
52
- loadSentences() {
53
- const filePath = (0, io_1.getPath)().join(this.dataDir, `sentences.${this.locale}.json`);
54
- const content = (0, io_1.getFs)().readFileSync(filePath, 'utf-8');
56
+ async loadSentences() {
57
+ const { readTextFromInput, join } = this.fileAdapter;
58
+ const filePath = join(this.dataDir, `sentences.${this.locale}.json`);
59
+ const content = await readTextFromInput(filePath);
55
60
  return JSON.parse(String(content));
56
61
  }
57
62
  /**
58
63
  * Load fringe vocabulary
59
64
  */
60
- loadFringe() {
61
- const filePath = (0, io_1.getPath)().join(this.dataDir, `fringe.${this.locale}.json`);
62
- const content = (0, io_1.getFs)().readFileSync(filePath, 'utf-8');
65
+ async loadFringe() {
66
+ const { readTextFromInput, join } = this.fileAdapter;
67
+ const filePath = join(this.dataDir, `fringe.${this.locale}.json`);
68
+ const content = await readTextFromInput(filePath);
63
69
  const data = JSON.parse(String(content));
64
70
  // Flatten nested category words if needed
65
71
  if (Array.isArray(data) && data.length > 0 && data[0].categories) {
@@ -76,9 +82,10 @@ class ReferenceLoader {
76
82
  /**
77
83
  * Load base words hash map
78
84
  */
79
- loadBaseWords() {
80
- const filePath = (0, io_1.getPath)().join(this.dataDir, `base_words.${this.locale}.json`);
81
- const content = (0, io_1.getFs)().readFileSync(filePath, 'utf-8');
85
+ async loadBaseWords() {
86
+ const { readTextFromInput, join } = this.fileAdapter;
87
+ const filePath = join(this.dataDir, `base_words.${this.locale}.json`);
88
+ const content = await readTextFromInput(filePath);
82
89
  return JSON.parse(String(content));
83
90
  }
84
91
  /**
@@ -86,10 +93,10 @@ class ReferenceLoader {
86
93
  * Common words that are NOT in core vocabulary lists
87
94
  * (matching Ruby loader.rb:413-420)
88
95
  */
89
- loadCommonFringe() {
90
- const commonWordsData = this.loadCommonWords();
96
+ async loadCommonFringe() {
97
+ const commonWordsData = await this.loadCommonWords();
91
98
  const commonWords = new Set(commonWordsData.words.map((w) => w.toLowerCase()));
92
- const coreLists = this.loadCoreLists();
99
+ const coreLists = await this.loadCoreLists();
93
100
  const coreWords = new Set();
94
101
  coreLists.forEach((list) => {
95
102
  list.words.forEach((word) => coreWords.add(word.toLowerCase()));
@@ -101,14 +108,14 @@ class ReferenceLoader {
101
108
  /**
102
109
  * Get all reference data at once
103
110
  */
104
- loadAll() {
111
+ async loadAll() {
105
112
  return {
106
- coreLists: this.loadCoreLists(),
107
- commonWords: this.loadCommonWords(),
108
- synonyms: this.loadSynonyms(),
109
- sentences: this.loadSentences(),
110
- fringe: this.loadFringe(),
111
- baseWords: this.loadBaseWords(),
113
+ coreLists: await this.loadCoreLists(),
114
+ commonWords: await this.loadCommonWords(),
115
+ synonyms: await this.loadSynonyms(),
116
+ sentences: await this.loadSentences(),
117
+ fringe: await this.loadFringe(),
118
+ baseWords: await this.loadBaseWords(),
112
119
  };
113
120
  }
114
121
  }
@@ -116,13 +123,14 @@ exports.ReferenceLoader = ReferenceLoader;
116
123
  /**
117
124
  * Get the default reference data path
118
125
  */
119
- function getReferenceDataPath() {
120
- return String((0, io_1.getPath)().join(__dirname, 'data'));
126
+ function getReferenceDataPath(fileAdapter = io_1.defaultFileAdapter) {
127
+ return String(fileAdapter.join(__dirname, 'data'));
121
128
  }
122
129
  /**
123
130
  * Check if reference data files exist
124
131
  */
125
- function hasReferenceData() {
132
+ async function hasReferenceData(fileAdapter = io_1.defaultFileAdapter) {
133
+ const { pathExists, join } = fileAdapter;
126
134
  const dataPath = getReferenceDataPath();
127
135
  const requiredFiles = [
128
136
  'core_lists.en.json',
@@ -131,5 +139,6 @@ function hasReferenceData() {
131
139
  'synonyms.en.json',
132
140
  'fringe.en.json',
133
141
  ];
134
- return requiredFiles.every((file) => (0, io_1.getFs)().existsSync((0, io_1.getPath)().join(dataPath, file)));
142
+ const existingPaths = await Promise.all(requiredFiles.map(async (file) => await pathExists(join(dataPath, file))));
143
+ return existingPaths.every((exists) => exists);
135
144
  }
@@ -1,28 +1,30 @@
1
+ import { FileAdapter } from '../utils/io';
1
2
  export declare abstract class SymbolExtractor {
2
3
  abstract getSymbolReferences(filePath: string): string[];
3
4
  }
4
5
  export declare abstract class SymbolResolver {
5
6
  protected symbolPath: string;
6
7
  protected dbPath: string;
7
- constructor(symbolPath: string, dbPath: string);
8
- abstract resolveSymbol(symbolRef: string): string | null;
8
+ protected fileAdapter: FileAdapter;
9
+ constructor(symbolPath: string, dbPath: string, fileAdapter?: FileAdapter);
10
+ abstract resolveSymbol(symbolRef: string): Promise<string | null>;
9
11
  }
10
12
  export declare class SnapSymbolExtractor extends SymbolExtractor {
11
13
  getSymbolReferences(filePath: string): string[];
12
14
  }
13
15
  export declare class SnapSymbolResolver extends SymbolResolver {
14
- resolveSymbol(symbolRef: string): string | null;
16
+ resolveSymbol(symbolRef: string): Promise<string | null>;
15
17
  }
16
18
  export declare class Grid3SymbolExtractor extends SymbolExtractor {
17
19
  getSymbolReferences(filePath: string): string[];
18
20
  }
19
21
  export declare class Grid3SymbolResolver extends SymbolResolver {
20
- resolveSymbol(symbolRef: string): string | null;
22
+ resolveSymbol(symbolRef: string): Promise<string | null>;
21
23
  }
22
24
  export declare class TouchChatSymbolExtractor extends SymbolExtractor {
23
25
  getSymbolReferences(_filePath: string): string[];
24
26
  }
25
27
  export declare class TouchChatSymbolResolver extends SymbolResolver {
26
- resolveSymbol(symbolRef: string): string | null;
28
+ resolveSymbol(symbolRef: string): Promise<string | null>;
27
29
  }
28
- export declare function resolveSymbol(label: string, symbolDir: string): string | null;
30
+ export declare function resolveSymbol(label: string, symbolDir: string, fileAdapter?: FileAdapter): Promise<string | null>;
@@ -1,21 +1,18 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.TouchChatSymbolResolver = exports.TouchChatSymbolExtractor = exports.Grid3SymbolResolver = exports.Grid3SymbolExtractor = exports.SnapSymbolResolver = exports.SnapSymbolExtractor = exports.SymbolResolver = exports.SymbolExtractor = void 0;
7
4
  exports.resolveSymbol = resolveSymbol;
8
- const path_1 = __importDefault(require("path"));
9
- const fs_1 = __importDefault(require("fs"));
10
5
  const symbols_1 = require("../processors/gridset/symbols");
6
+ const io_1 = require("../utils/io");
11
7
  // --- Base Classes ---
12
8
  class SymbolExtractor {
13
9
  }
14
10
  exports.SymbolExtractor = SymbolExtractor;
15
11
  class SymbolResolver {
16
- constructor(symbolPath, dbPath) {
12
+ constructor(symbolPath, dbPath, fileAdapter = io_1.defaultFileAdapter) {
17
13
  this.symbolPath = symbolPath;
18
14
  this.dbPath = dbPath;
15
+ this.fileAdapter = fileAdapter;
19
16
  }
20
17
  }
21
18
  exports.SymbolResolver = SymbolResolver;
@@ -42,7 +39,8 @@ class SnapSymbolExtractor extends SymbolExtractor {
42
39
  }
43
40
  exports.SnapSymbolExtractor = SnapSymbolExtractor;
44
41
  class SnapSymbolResolver extends SymbolResolver {
45
- resolveSymbol(symbolRef) {
42
+ async resolveSymbol(symbolRef) {
43
+ const { join, writeBinaryToPath } = this.fileAdapter;
46
44
  if (!Database)
47
45
  throw new Error('better-sqlite3 not installed');
48
46
  const db = new Database(this.dbPath, { readonly: true });
@@ -51,8 +49,8 @@ class SnapSymbolResolver extends SymbolResolver {
51
49
  db.close();
52
50
  if (!row)
53
51
  return null;
54
- const outPath = path_1.default.join(this.symbolPath, `${symbolRef}.png`);
55
- fs_1.default.writeFileSync(outPath, row.ImageData);
52
+ const outPath = join(this.symbolPath, `${symbolRef}.png`);
53
+ await writeBinaryToPath(outPath, row.ImageData);
56
54
  return outPath;
57
55
  }
58
56
  }
@@ -88,10 +86,12 @@ class Grid3SymbolExtractor extends SymbolExtractor {
88
86
  }
89
87
  exports.Grid3SymbolExtractor = Grid3SymbolExtractor;
90
88
  class Grid3SymbolResolver extends SymbolResolver {
91
- resolveSymbol(symbolRef) {
89
+ async resolveSymbol(symbolRef) {
90
+ const { join, pathExists } = this.fileAdapter;
92
91
  // Implementation depends on Grid 3 symbol storage format
93
- const symbolPath = path_1.default.join(this.symbolPath, symbolRef);
94
- return fs_1.default.existsSync(symbolPath) ? symbolPath : null;
92
+ const symbolPath = join(this.symbolPath, symbolRef);
93
+ const exists = await pathExists(symbolPath);
94
+ return exists ? symbolPath : null;
95
95
  }
96
96
  }
97
97
  exports.Grid3SymbolResolver = Grid3SymbolResolver;
@@ -104,20 +104,23 @@ class TouchChatSymbolExtractor extends SymbolExtractor {
104
104
  }
105
105
  exports.TouchChatSymbolExtractor = TouchChatSymbolExtractor;
106
106
  class TouchChatSymbolResolver extends SymbolResolver {
107
- resolveSymbol(symbolRef) {
107
+ async resolveSymbol(symbolRef) {
108
+ const { join, pathExists } = this.fileAdapter;
108
109
  // Implementation depends on TouchChat symbol storage format
109
- const symbolPath = path_1.default.join(this.symbolPath, symbolRef);
110
- return fs_1.default.existsSync(symbolPath) ? symbolPath : null;
110
+ const symbolPath = join(this.symbolPath, symbolRef);
111
+ const exists = await pathExists(symbolPath);
112
+ return exists ? symbolPath : null;
111
113
  }
112
114
  }
113
115
  exports.TouchChatSymbolResolver = TouchChatSymbolResolver;
114
116
  // --- Simple fallback function for PCS-style lookup ---
115
- function resolveSymbol(label, symbolDir) {
117
+ async function resolveSymbol(label, symbolDir, fileAdapter = io_1.defaultFileAdapter) {
118
+ const { join, pathExists } = fileAdapter;
116
119
  const cleanLabel = label.toLowerCase().replace(/[^a-z0-9]/g, '');
117
120
  const exts = ['.png', '.jpg', '.svg'];
118
121
  for (const ext of exts) {
119
- const symbolPath = path_1.default.join(symbolDir, cleanLabel + ext);
120
- if (fs_1.default.existsSync(symbolPath)) {
122
+ const symbolPath = join(symbolDir, cleanLabel + ext);
123
+ if (await pathExists(symbolPath)) {
121
124
  return symbolPath;
122
125
  }
123
126
  }
@@ -1,9 +1,28 @@
1
1
  export type ProcessorInput = string | Buffer | ArrayBuffer | Uint8Array;
2
2
  export type BinaryOutput = Buffer | Uint8Array;
3
+ export interface FileAdapter {
4
+ readBinaryFromInput: (input: ProcessorInput) => Promise<Uint8Array>;
5
+ readTextFromInput: (input: ProcessorInput, encoding?: BufferEncoding) => Promise<string>;
6
+ writeBinaryToPath: (outputPath: string, data: BinaryOutput) => Promise<void>;
7
+ writeTextToPath: (outputPath: string, text: string) => Promise<void>;
8
+ pathExists: (path: string) => Promise<boolean>;
9
+ isDirectory: (path: string) => Promise<boolean>;
10
+ getFileSize: (path: string) => Promise<number>;
11
+ mkDir: (path: string, options?: {
12
+ recursive?: boolean;
13
+ }) => Promise<void>;
14
+ listDir: (path: string) => Promise<string[]>;
15
+ removePath: (path: string, options?: {
16
+ recursive?: boolean;
17
+ force?: boolean;
18
+ }) => Promise<void>;
19
+ mkTempDir: (prefix: string) => Promise<string>;
20
+ join: (...pathParts: string[]) => string;
21
+ dirname: (path: string) => string;
22
+ basename: (path: string, suffix?: string) => string;
23
+ }
3
24
  type NodeRequire = (id: string) => any;
4
25
  export declare function getNodeRequire(): NodeRequire;
5
- export declare function getFs(): typeof import('fs');
6
- export declare function getPath(): typeof import('path');
7
26
  export declare function getOs(): typeof import('os');
8
27
  export declare function isNodeRuntime(): boolean;
9
28
  export declare function getBasename(filePath: string): string;
@@ -12,8 +31,7 @@ export declare function toArrayBuffer(input: Uint8Array | ArrayBuffer | Buffer):
12
31
  export declare function decodeText(input: Uint8Array): string;
13
32
  export declare function encodeBase64(input: Uint8Array): string;
14
33
  export declare function encodeText(text: string): BinaryOutput;
15
- export declare function readBinaryFromInput(input: ProcessorInput): Uint8Array;
16
- export declare function readTextFromInput(input: ProcessorInput, encoding?: BufferEncoding): string;
17
- export declare function writeBinaryToPath(outputPath: string, data: BinaryOutput): void;
18
- export declare function writeTextToPath(outputPath: string, text: string): void;
34
+ export declare function extname(path: string): string;
35
+ export declare function joinWin32(...pathParts: string[]): string;
36
+ export declare const defaultFileAdapter: FileAdapter;
19
37
  export {};
package/dist/utils/io.js CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultFileAdapter = void 0;
3
4
  exports.getNodeRequire = getNodeRequire;
4
- exports.getFs = getFs;
5
- exports.getPath = getPath;
6
5
  exports.getOs = getOs;
7
6
  exports.isNodeRuntime = isNodeRuntime;
8
7
  exports.getBasename = getBasename;
@@ -11,10 +10,8 @@ exports.toArrayBuffer = toArrayBuffer;
11
10
  exports.decodeText = decodeText;
12
11
  exports.encodeBase64 = encodeBase64;
13
12
  exports.encodeText = encodeText;
14
- exports.readBinaryFromInput = readBinaryFromInput;
15
- exports.readTextFromInput = readTextFromInput;
16
- exports.writeBinaryToPath = writeBinaryToPath;
17
- exports.writeTextToPath = writeTextToPath;
13
+ exports.extname = extname;
14
+ exports.joinWin32 = joinWin32;
18
15
  let cachedFs = null;
19
16
  let cachedPath = null;
20
17
  let cachedOs = null;
@@ -41,7 +38,7 @@ function getFs() {
41
38
  if (!cachedFs) {
42
39
  try {
43
40
  const nodeRequire = getNodeRequire();
44
- const fsModule = 'fs';
41
+ const fsModule = 'node:fs';
45
42
  cachedFs = nodeRequire(fsModule);
46
43
  }
47
44
  catch {
@@ -131,37 +128,94 @@ function encodeText(text) {
131
128
  }
132
129
  return new TextEncoder().encode(text);
133
130
  }
134
- function readBinaryFromInput(input) {
131
+ // extname algorithm from node:path
132
+ const splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; //eslint-disable-line
133
+ const splitTailRe = /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; //eslint-disable-line
134
+ function extname(path) {
135
+ const tail = splitDeviceRe.exec(path)?.at(3) ?? '';
136
+ return splitTailRe.exec(tail)?.at(3) ?? '';
137
+ }
138
+ async function readBinaryFromInput(input) {
135
139
  if (typeof input === 'string') {
136
- const fs = getFs();
137
- return fs.readFileSync(input);
140
+ return Promise.resolve(getFs().readFileSync(input));
138
141
  }
139
142
  if (typeof Buffer !== 'undefined' && Buffer.isBuffer(input)) {
140
- return input;
143
+ return Promise.resolve(input);
141
144
  }
142
145
  if (input instanceof ArrayBuffer) {
143
- return new Uint8Array(input);
146
+ return Promise.resolve(new Uint8Array(input));
144
147
  }
145
- return input;
148
+ return Promise.resolve(input);
146
149
  }
147
- function readTextFromInput(input, encoding = 'utf8') {
150
+ async function readTextFromInput(input, encoding = 'utf8') {
148
151
  if (typeof input === 'string') {
149
- const fs = getFs();
150
- return fs.readFileSync(input, encoding);
152
+ return Promise.resolve(getFs().readFileSync(input, encoding));
151
153
  }
152
154
  if (typeof Buffer !== 'undefined' && Buffer.isBuffer(input)) {
153
- return input.toString(encoding);
155
+ return Promise.resolve(input.toString(encoding));
154
156
  }
155
157
  if (input instanceof ArrayBuffer) {
156
- return decodeText(new Uint8Array(input));
158
+ return Promise.resolve(decodeText(new Uint8Array(input)));
157
159
  }
158
- return decodeText(input);
160
+ return Promise.resolve(decodeText(input));
161
+ }
162
+ async function writeBinaryToPath(outputPath, data) {
163
+ getFs().writeFileSync(outputPath, data);
164
+ await Promise.resolve();
165
+ }
166
+ async function writeTextToPath(outputPath, text) {
167
+ getFs().writeFileSync(outputPath, text, 'utf8');
168
+ await Promise.resolve();
169
+ }
170
+ async function pathExists(path) {
171
+ return Promise.resolve(getFs().existsSync(path));
172
+ }
173
+ async function isDirectory(path) {
174
+ return Promise.resolve(getFs().statSync(path).isDirectory());
175
+ }
176
+ async function getFileSize(path) {
177
+ return Promise.resolve(getFs().statSync(path).size);
178
+ }
179
+ async function mkDir(path, options) {
180
+ getFs().mkdirSync(path, options);
181
+ await Promise.resolve();
182
+ }
183
+ async function listDir(path) {
184
+ return Promise.resolve(getFs().readdirSync(path));
185
+ }
186
+ async function removePath(path, options) {
187
+ getFs().rmSync(path, options);
188
+ await Promise.resolve();
189
+ }
190
+ async function mkTempDir(prefix) {
191
+ const path = join(getOs().tmpdir(), prefix);
192
+ return Promise.resolve(getFs().mkdtempSync(path));
193
+ }
194
+ function join(...pathParts) {
195
+ return getPath().join(...pathParts);
196
+ }
197
+ function joinWin32(...pathParts) {
198
+ return getPath().win32.join(...pathParts);
159
199
  }
160
- function writeBinaryToPath(outputPath, data) {
161
- const fs = getFs();
162
- fs.writeFileSync(outputPath, data);
200
+ function dirname(path) {
201
+ return getPath().dirname(path);
163
202
  }
164
- function writeTextToPath(outputPath, text) {
165
- const fs = getFs();
166
- fs.writeFileSync(outputPath, text, 'utf8');
203
+ function basename(path, suffix) {
204
+ return getPath().basename(path, suffix);
167
205
  }
206
+ exports.defaultFileAdapter = {
207
+ readBinaryFromInput,
208
+ readTextFromInput,
209
+ writeBinaryToPath,
210
+ writeTextToPath,
211
+ pathExists,
212
+ isDirectory,
213
+ getFileSize,
214
+ mkDir,
215
+ listDir,
216
+ removePath,
217
+ mkTempDir,
218
+ join,
219
+ dirname,
220
+ basename,
221
+ };
@@ -1,4 +1,5 @@
1
1
  import type { SqlJsConfig } from 'sql.js';
2
+ import { FileAdapter } from './io';
2
3
  export interface SqliteStatementAdapter {
3
4
  all(...params: unknown[]): any[];
4
5
  get(...params: unknown[]): any;
@@ -11,10 +12,11 @@ export interface SqliteDatabaseAdapter {
11
12
  }
12
13
  export interface SqliteOpenOptions {
13
14
  readonly?: boolean;
15
+ fileAdapter?: FileAdapter;
14
16
  }
15
17
  export interface SqliteOpenResult {
16
18
  db: SqliteDatabaseAdapter;
17
- cleanup?: () => void;
19
+ cleanup?: () => Promise<void>;
18
20
  }
19
21
  export declare function configureSqlJs(config: SqlJsConfig): void;
20
22
  export declare function requireBetterSqlite3(): typeof import('better-sqlite3');
@@ -98,6 +98,7 @@ function requireBetterSqlite3() {
98
98
  return getBetterSqlite3();
99
99
  }
100
100
  async function openSqliteDatabase(input, options = {}) {
101
+ const { readBinaryFromInput, mkTempDir, writeBinaryToPath, removePath, join } = options.fileAdapter ?? io_1.defaultFileAdapter;
101
102
  if (typeof input === 'string') {
102
103
  if (!(0, io_1.isNodeRuntime)()) {
103
104
  throw new Error('SQLite file paths are not supported in browser environments.');
@@ -106,27 +107,24 @@ async function openSqliteDatabase(input, options = {}) {
106
107
  const db = new Database(input, { readonly: options.readonly ?? true });
107
108
  return { db };
108
109
  }
109
- const data = (0, io_1.readBinaryFromInput)(input);
110
+ const data = await readBinaryFromInput(input);
110
111
  if (!(0, io_1.isNodeRuntime)()) {
111
112
  const SQL = await getSqlJs();
112
113
  const db = new SQL.Database(data);
113
114
  return { db: createSqlJsAdapter(db) };
114
115
  }
115
- const fs = (0, io_1.getFs)();
116
- const path = (0, io_1.getPath)();
117
- const os = (0, io_1.getOs)();
118
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'aac-sqlite-'));
119
- const dbPath = path.join(tempDir, 'input.sqlite');
120
- fs.writeFileSync(dbPath, data);
116
+ const tempDir = await mkTempDir('aac-sqlite-');
117
+ const dbPath = join(tempDir, 'input.sqlite');
118
+ await writeBinaryToPath(dbPath, data);
121
119
  const Database = getBetterSqlite3();
122
120
  const db = new Database(dbPath, { readonly: options.readonly ?? true });
123
- const cleanup = () => {
121
+ const cleanup = async () => {
124
122
  try {
125
123
  db.close();
126
124
  }
127
125
  finally {
128
126
  try {
129
- fs.rmSync(tempDir, { recursive: true, force: true });
127
+ await removePath(tempDir, { recursive: true, force: true });
130
128
  }
131
129
  catch (error) {
132
130
  console.warn('Failed to clean up temporary SQLite files:', error);
@@ -1,7 +1,11 @@
1
+ import { ProcessorInput, FileAdapter } from './io';
1
2
  export interface ZipAdapter {
2
3
  listFiles(): string[];
3
4
  readFile(name: string): Promise<Uint8Array>;
5
+ writeFiles(files: ZipFile[]): Promise<Uint8Array>;
4
6
  }
5
- export declare function openZipFromInput(input: string | Uint8Array | ArrayBuffer | Buffer): Promise<{
6
- zip: ZipAdapter;
7
- }>;
7
+ export interface ZipFile {
8
+ name: string;
9
+ data: string | Uint8Array;
10
+ }
11
+ export declare function getZipAdapter(input?: ProcessorInput, fileAdapter?: FileAdapter): Promise<ZipAdapter>;