@willwade/aac-processors 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/browser/index.browser.js +15 -1
- package/dist/browser/processors/gridset/password.js +11 -0
- package/dist/browser/processors/gridsetProcessor.js +42 -46
- package/dist/browser/processors/obfProcessor.js +47 -63
- package/dist/browser/processors/snapProcessor.js +1031 -0
- package/dist/browser/processors/touchchatProcessor.js +1004 -0
- package/dist/browser/utils/io.js +36 -2
- package/dist/browser/utils/sqlite.js +109 -0
- package/dist/browser/utils/zip.js +54 -0
- package/dist/browser/validation/gridsetValidator.js +7 -27
- package/dist/browser/validation/obfValidator.js +9 -4
- package/dist/browser/validation/snapValidator.js +197 -0
- package/dist/browser/validation/touchChatValidator.js +201 -0
- package/dist/index.browser.d.ts +7 -0
- package/dist/index.browser.js +19 -2
- package/dist/processors/gridset/helpers.js +3 -4
- package/dist/processors/gridset/index.d.ts +1 -1
- package/dist/processors/gridset/index.js +3 -2
- package/dist/processors/gridset/password.d.ts +3 -2
- package/dist/processors/gridset/password.js +12 -0
- package/dist/processors/gridset/wordlistHelpers.js +107 -51
- package/dist/processors/gridsetProcessor.js +40 -44
- package/dist/processors/obfProcessor.js +46 -62
- package/dist/processors/snapProcessor.js +60 -54
- package/dist/processors/touchchatProcessor.js +38 -36
- package/dist/utils/io.d.ts +4 -0
- package/dist/utils/io.js +40 -2
- package/dist/utils/sqlite.d.ts +21 -0
- package/dist/utils/sqlite.js +137 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.js +80 -0
- package/dist/validation/applePanelsValidator.js +11 -28
- package/dist/validation/astericsValidator.js +11 -30
- package/dist/validation/dotValidator.js +11 -30
- package/dist/validation/excelValidator.js +5 -6
- package/dist/validation/gridsetValidator.js +29 -26
- package/dist/validation/index.d.ts +2 -1
- package/dist/validation/index.js +9 -32
- package/dist/validation/obfValidator.js +8 -3
- package/dist/validation/obfsetValidator.js +11 -30
- package/dist/validation/opmlValidator.js +11 -30
- package/dist/validation/snapValidator.js +6 -9
- package/dist/validation/touchChatValidator.js +6 -7
- package/docs/BROWSER_USAGE.md +2 -10
- package/examples/README.md +3 -75
- package/examples/vitedemo/README.md +13 -7
- package/examples/vitedemo/index.html +51 -2
- package/examples/vitedemo/package-lock.json +9 -0
- package/examples/vitedemo/package.json +1 -0
- package/examples/vitedemo/src/main.ts +132 -2
- package/examples/vitedemo/src/vite-env.d.ts +1 -0
- package/examples/vitedemo/vite.config.ts +26 -7
- package/package.json +3 -1
- package/examples/browser-test-server.js +0 -81
|
@@ -1,21 +1,15 @@
|
|
|
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.TouchChatProcessor = void 0;
|
|
7
4
|
const baseProcessor_1 = require("../core/baseProcessor");
|
|
8
5
|
const treeStructure_1 = require("../core/treeStructure");
|
|
9
6
|
const idGenerator_1 = require("../utilities/analytics/utils/idGenerator");
|
|
10
7
|
const stringCasing_1 = require("../core/stringCasing");
|
|
11
|
-
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
12
|
-
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
const fs_1 = __importDefault(require("fs"));
|
|
15
|
-
const os_1 = __importDefault(require("os"));
|
|
16
8
|
const touchChatValidator_1 = require("../validation/touchChatValidator");
|
|
17
9
|
const io_1 = require("../utils/io");
|
|
18
10
|
const translationProcessor_1 = require("../utilities/translation/translationProcessor");
|
|
11
|
+
const sqlite_1 = require("../utils/sqlite");
|
|
12
|
+
const zip_1 = require("../utils/zip");
|
|
19
13
|
const toNumberOrUndefined = (value) => typeof value === 'number' ? value : undefined;
|
|
20
14
|
const toStringOrUndefined = (value) => typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
21
15
|
const toBooleanOrUndefined = (value) => typeof value === 'number' ? value !== 0 : undefined;
|
|
@@ -66,25 +60,22 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
66
60
|
async loadIntoTree(filePathOrBuffer) {
|
|
67
61
|
await Promise.resolve();
|
|
68
62
|
// Unzip .ce file, extract the .c4v SQLite DB, and parse pages/buttons
|
|
69
|
-
let tmpDir = null;
|
|
70
63
|
let db = null;
|
|
64
|
+
let cleanup;
|
|
71
65
|
try {
|
|
72
66
|
// Store source file path or buffer
|
|
73
67
|
this.sourceFile = filePathOrBuffer;
|
|
74
68
|
// Step 1: Unzip
|
|
75
|
-
tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'touchchat-'));
|
|
76
69
|
const zipInput = (0, io_1.readBinaryFromInput)(filePathOrBuffer);
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
// Step 2: Find and open SQLite DB
|
|
81
|
-
const files = fs_1.default.readdirSync(tmpDir);
|
|
82
|
-
const vocabFile = files.find((f) => f.endsWith('.c4v'));
|
|
83
|
-
if (!vocabFile) {
|
|
70
|
+
const { zip } = await (0, zip_1.openZipFromInput)(zipInput);
|
|
71
|
+
const vocabEntry = zip.listFiles().find((name) => name.endsWith('.c4v'));
|
|
72
|
+
if (!vocabEntry) {
|
|
84
73
|
throw new Error('No .c4v vocab DB found in TouchChat export');
|
|
85
74
|
}
|
|
86
|
-
const
|
|
87
|
-
|
|
75
|
+
const dbBuffer = await zip.readFile(vocabEntry);
|
|
76
|
+
const dbResult = await (0, sqlite_1.openSqliteDatabase)(dbBuffer, { readonly: true });
|
|
77
|
+
db = dbResult.db;
|
|
78
|
+
cleanup = dbResult.cleanup;
|
|
88
79
|
// Step 3: Create tree and load pages
|
|
89
80
|
const tree = new treeStructure_1.AACTree();
|
|
90
81
|
// Set root ID to the first page ID (will be updated if we find a better root)
|
|
@@ -476,20 +467,18 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
476
467
|
}
|
|
477
468
|
finally {
|
|
478
469
|
// Clean up
|
|
479
|
-
if (
|
|
480
|
-
|
|
470
|
+
if (cleanup) {
|
|
471
|
+
cleanup();
|
|
481
472
|
}
|
|
482
|
-
if (
|
|
483
|
-
|
|
484
|
-
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
485
|
-
}
|
|
486
|
-
catch (e) {
|
|
487
|
-
console.warn('Failed to clean up temp directory:', e);
|
|
488
|
-
}
|
|
473
|
+
else if (db) {
|
|
474
|
+
db.close();
|
|
489
475
|
}
|
|
490
476
|
}
|
|
491
477
|
}
|
|
492
478
|
async processTexts(filePathOrBuffer, translations, outputPath) {
|
|
479
|
+
if (!(0, io_1.isNodeRuntime)()) {
|
|
480
|
+
throw new Error('processTexts is only supported in Node.js environments for TouchChat files.');
|
|
481
|
+
}
|
|
493
482
|
// Load the tree, apply translations, and save to new file
|
|
494
483
|
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
495
484
|
// Apply translations to all text content
|
|
@@ -519,15 +508,23 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
519
508
|
});
|
|
520
509
|
// Save the translated tree and return its content
|
|
521
510
|
await this.saveFromTree(tree, outputPath);
|
|
522
|
-
|
|
511
|
+
const fs = (0, io_1.getFs)();
|
|
512
|
+
return fs.readFileSync(outputPath);
|
|
523
513
|
}
|
|
524
514
|
async saveFromTree(tree, outputPath) {
|
|
525
515
|
await Promise.resolve();
|
|
516
|
+
if (!(0, io_1.isNodeRuntime)()) {
|
|
517
|
+
throw new Error('saveFromTree is only supported in Node.js environments for TouchChat files.');
|
|
518
|
+
}
|
|
519
|
+
const fs = (0, io_1.getFs)();
|
|
520
|
+
const path = (0, io_1.getPath)();
|
|
521
|
+
const os = (0, io_1.getOs)();
|
|
526
522
|
// Create a TouchChat database that matches the expected schema for loading
|
|
527
|
-
const tmpDir =
|
|
528
|
-
const dbPath =
|
|
523
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'touchchat-export-'));
|
|
524
|
+
const dbPath = path.join(tmpDir, 'vocab.c4v');
|
|
529
525
|
try {
|
|
530
|
-
const
|
|
526
|
+
const Database = (0, sqlite_1.requireBetterSqlite3)();
|
|
527
|
+
const db = new Database(dbPath);
|
|
531
528
|
// Create schema that matches what loadIntoTree expects
|
|
532
529
|
db.exec(`
|
|
533
530
|
CREATE TABLE IF NOT EXISTS resources (
|
|
@@ -817,14 +814,15 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
817
814
|
}
|
|
818
815
|
db.close();
|
|
819
816
|
// Create zip file with the database
|
|
820
|
-
const
|
|
817
|
+
const AdmZip = (0, io_1.getNodeRequire)()('adm-zip');
|
|
818
|
+
const zip = new AdmZip();
|
|
821
819
|
zip.addLocalFile(dbPath, '', 'vocab.c4v');
|
|
822
820
|
zip.writeZip(outputPath);
|
|
823
821
|
}
|
|
824
822
|
finally {
|
|
825
823
|
// Clean up
|
|
826
|
-
if (
|
|
827
|
-
|
|
824
|
+
if (fs.existsSync(tmpDir)) {
|
|
825
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
828
826
|
}
|
|
829
827
|
}
|
|
830
828
|
}
|
|
@@ -961,6 +959,9 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
961
959
|
* @returns Buffer of the translated TouchChat file
|
|
962
960
|
*/
|
|
963
961
|
async processLLMTranslations(filePathOrBuffer, llmTranslations, outputPath, options) {
|
|
962
|
+
if (!(0, io_1.isNodeRuntime)()) {
|
|
963
|
+
throw new Error('processLLMTranslations is only supported in Node.js environments for TouchChat files.');
|
|
964
|
+
}
|
|
964
965
|
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
965
966
|
// Validate translations using shared utility
|
|
966
967
|
const buttonIds = Object.values(tree.pages).flatMap((page) => page.buttons.map((b) => b.id));
|
|
@@ -999,7 +1000,8 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
999
1000
|
});
|
|
1000
1001
|
// Save and return
|
|
1001
1002
|
await this.saveFromTree(tree, outputPath);
|
|
1002
|
-
|
|
1003
|
+
const fs = (0, io_1.getFs)();
|
|
1004
|
+
return fs.readFileSync(outputPath);
|
|
1003
1005
|
}
|
|
1004
1006
|
}
|
|
1005
1007
|
exports.TouchChatProcessor = TouchChatProcessor;
|
package/dist/utils/io.d.ts
CHANGED
|
@@ -4,7 +4,11 @@ type NodeRequire = (id: string) => any;
|
|
|
4
4
|
export declare function getNodeRequire(): NodeRequire;
|
|
5
5
|
export declare function getFs(): typeof import('fs');
|
|
6
6
|
export declare function getPath(): typeof import('path');
|
|
7
|
+
export declare function getOs(): typeof import('os');
|
|
8
|
+
export declare function isNodeRuntime(): boolean;
|
|
7
9
|
export declare function getBasename(filePath: string): string;
|
|
10
|
+
export declare function toUint8Array(input: Uint8Array | ArrayBuffer | Buffer): Uint8Array;
|
|
11
|
+
export declare function toArrayBuffer(input: Uint8Array | ArrayBuffer | Buffer): ArrayBuffer;
|
|
8
12
|
export declare function decodeText(input: Uint8Array): string;
|
|
9
13
|
export declare function encodeBase64(input: Uint8Array): string;
|
|
10
14
|
export declare function encodeText(text: string): BinaryOutput;
|
package/dist/utils/io.js
CHANGED
|
@@ -3,7 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getNodeRequire = getNodeRequire;
|
|
4
4
|
exports.getFs = getFs;
|
|
5
5
|
exports.getPath = getPath;
|
|
6
|
+
exports.getOs = getOs;
|
|
7
|
+
exports.isNodeRuntime = isNodeRuntime;
|
|
6
8
|
exports.getBasename = getBasename;
|
|
9
|
+
exports.toUint8Array = toUint8Array;
|
|
10
|
+
exports.toArrayBuffer = toArrayBuffer;
|
|
7
11
|
exports.decodeText = decodeText;
|
|
8
12
|
exports.encodeBase64 = encodeBase64;
|
|
9
13
|
exports.encodeText = encodeText;
|
|
@@ -13,6 +17,7 @@ exports.writeBinaryToPath = writeBinaryToPath;
|
|
|
13
17
|
exports.writeTextToPath = writeTextToPath;
|
|
14
18
|
let cachedFs = null;
|
|
15
19
|
let cachedPath = null;
|
|
20
|
+
let cachedOs = null;
|
|
16
21
|
let cachedRequire = undefined;
|
|
17
22
|
function getNodeRequire() {
|
|
18
23
|
if (cachedRequire === undefined) {
|
|
@@ -64,9 +69,42 @@ function getPath() {
|
|
|
64
69
|
}
|
|
65
70
|
return cachedPath;
|
|
66
71
|
}
|
|
72
|
+
function getOs() {
|
|
73
|
+
if (!cachedOs) {
|
|
74
|
+
try {
|
|
75
|
+
const nodeRequire = getNodeRequire();
|
|
76
|
+
const osModule = 'os';
|
|
77
|
+
cachedOs = nodeRequire(osModule);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
throw new Error('OS utilities are not available in this environment.');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!cachedOs) {
|
|
84
|
+
throw new Error('OS utilities are not available in this environment.');
|
|
85
|
+
}
|
|
86
|
+
return cachedOs;
|
|
87
|
+
}
|
|
88
|
+
function isNodeRuntime() {
|
|
89
|
+
return typeof process !== 'undefined' && !!process.versions?.node;
|
|
90
|
+
}
|
|
67
91
|
function getBasename(filePath) {
|
|
68
|
-
const
|
|
69
|
-
|
|
92
|
+
const trimmed = filePath.replace(/[/\\]+$/, '') || filePath;
|
|
93
|
+
const parts = trimmed.split(/[/\\]/);
|
|
94
|
+
return parts[parts.length - 1] || trimmed;
|
|
95
|
+
}
|
|
96
|
+
function toUint8Array(input) {
|
|
97
|
+
if (input instanceof Uint8Array) {
|
|
98
|
+
return input;
|
|
99
|
+
}
|
|
100
|
+
return new Uint8Array(input);
|
|
101
|
+
}
|
|
102
|
+
function toArrayBuffer(input) {
|
|
103
|
+
if (input instanceof ArrayBuffer) {
|
|
104
|
+
return input;
|
|
105
|
+
}
|
|
106
|
+
const view = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
107
|
+
return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
|
|
70
108
|
}
|
|
71
109
|
function decodeText(input) {
|
|
72
110
|
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(input)) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SqlJsConfig } from 'sql.js';
|
|
2
|
+
export interface SqliteStatementAdapter {
|
|
3
|
+
all(...params: unknown[]): any[];
|
|
4
|
+
get(...params: unknown[]): any;
|
|
5
|
+
run(...params: unknown[]): any;
|
|
6
|
+
}
|
|
7
|
+
export interface SqliteDatabaseAdapter {
|
|
8
|
+
prepare(sql: string): SqliteStatementAdapter;
|
|
9
|
+
exec(sql: string): void;
|
|
10
|
+
close(): void;
|
|
11
|
+
}
|
|
12
|
+
export interface SqliteOpenOptions {
|
|
13
|
+
readonly?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface SqliteOpenResult {
|
|
16
|
+
db: SqliteDatabaseAdapter;
|
|
17
|
+
cleanup?: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function configureSqlJs(config: SqlJsConfig): void;
|
|
20
|
+
export declare function requireBetterSqlite3(): typeof import('better-sqlite3');
|
|
21
|
+
export declare function openSqliteDatabase(input: string | Uint8Array | ArrayBuffer | Buffer, options?: SqliteOpenOptions): Promise<SqliteOpenResult>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.configureSqlJs = configureSqlJs;
|
|
27
|
+
exports.requireBetterSqlite3 = requireBetterSqlite3;
|
|
28
|
+
exports.openSqliteDatabase = openSqliteDatabase;
|
|
29
|
+
const io_1 = require("./io");
|
|
30
|
+
let sqlJsConfig = null;
|
|
31
|
+
let sqlJsPromise = null;
|
|
32
|
+
function configureSqlJs(config) {
|
|
33
|
+
sqlJsConfig = { ...(sqlJsConfig ?? {}), ...config };
|
|
34
|
+
}
|
|
35
|
+
async function getSqlJs() {
|
|
36
|
+
if (!sqlJsPromise) {
|
|
37
|
+
sqlJsPromise = Promise.resolve().then(() => __importStar(require('sql.js'))).then((module) => {
|
|
38
|
+
const initSqlJs = module.default || module;
|
|
39
|
+
return initSqlJs(sqlJsConfig ?? {});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return sqlJsPromise;
|
|
43
|
+
}
|
|
44
|
+
function createSqlJsAdapter(db) {
|
|
45
|
+
return {
|
|
46
|
+
prepare(sql) {
|
|
47
|
+
return {
|
|
48
|
+
all(...params) {
|
|
49
|
+
const stmt = db.prepare(sql);
|
|
50
|
+
if (params.length > 0) {
|
|
51
|
+
stmt.bind(params);
|
|
52
|
+
}
|
|
53
|
+
const rows = [];
|
|
54
|
+
while (stmt.step()) {
|
|
55
|
+
rows.push(stmt.getAsObject());
|
|
56
|
+
}
|
|
57
|
+
stmt.free();
|
|
58
|
+
return rows;
|
|
59
|
+
},
|
|
60
|
+
get(...params) {
|
|
61
|
+
const stmt = db.prepare(sql);
|
|
62
|
+
if (params.length > 0) {
|
|
63
|
+
stmt.bind(params);
|
|
64
|
+
}
|
|
65
|
+
const row = stmt.step() ? stmt.getAsObject() : undefined;
|
|
66
|
+
stmt.free();
|
|
67
|
+
return row;
|
|
68
|
+
},
|
|
69
|
+
run(...params) {
|
|
70
|
+
const stmt = db.prepare(sql);
|
|
71
|
+
if (params.length > 0) {
|
|
72
|
+
stmt.bind(params);
|
|
73
|
+
}
|
|
74
|
+
stmt.step();
|
|
75
|
+
stmt.free();
|
|
76
|
+
return undefined;
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
exec(sql) {
|
|
81
|
+
db.exec(sql);
|
|
82
|
+
},
|
|
83
|
+
close() {
|
|
84
|
+
db.close();
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function getBetterSqlite3() {
|
|
89
|
+
try {
|
|
90
|
+
const nodeRequire = (0, io_1.getNodeRequire)();
|
|
91
|
+
return nodeRequire('better-sqlite3');
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
throw new Error('better-sqlite3 is not available in this environment.');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function requireBetterSqlite3() {
|
|
98
|
+
return getBetterSqlite3();
|
|
99
|
+
}
|
|
100
|
+
async function openSqliteDatabase(input, options = {}) {
|
|
101
|
+
if (typeof input === 'string') {
|
|
102
|
+
if (!(0, io_1.isNodeRuntime)()) {
|
|
103
|
+
throw new Error('SQLite file paths are not supported in browser environments.');
|
|
104
|
+
}
|
|
105
|
+
const Database = getBetterSqlite3();
|
|
106
|
+
const db = new Database(input, { readonly: options.readonly ?? true });
|
|
107
|
+
return { db };
|
|
108
|
+
}
|
|
109
|
+
const data = (0, io_1.readBinaryFromInput)(input);
|
|
110
|
+
if (!(0, io_1.isNodeRuntime)()) {
|
|
111
|
+
const SQL = await getSqlJs();
|
|
112
|
+
const db = new SQL.Database(data);
|
|
113
|
+
return { db: createSqlJsAdapter(db) };
|
|
114
|
+
}
|
|
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);
|
|
121
|
+
const Database = getBetterSqlite3();
|
|
122
|
+
const db = new Database(dbPath, { readonly: options.readonly ?? true });
|
|
123
|
+
const cleanup = () => {
|
|
124
|
+
try {
|
|
125
|
+
db.close();
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
try {
|
|
129
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.warn('Failed to clean up temporary SQLite files:', error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
return { db, cleanup };
|
|
137
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.openZipFromInput = openZipFromInput;
|
|
27
|
+
const io_1 = require("./io");
|
|
28
|
+
async function openZipFromInput(input) {
|
|
29
|
+
if (typeof input === 'string') {
|
|
30
|
+
if (!(0, io_1.isNodeRuntime)()) {
|
|
31
|
+
throw new Error('Zip file paths are not supported in browser environments.');
|
|
32
|
+
}
|
|
33
|
+
const AdmZip = (0, io_1.getNodeRequire)()('adm-zip');
|
|
34
|
+
const admZip = new AdmZip(input);
|
|
35
|
+
return {
|
|
36
|
+
zip: {
|
|
37
|
+
listFiles: () => admZip.getEntries().map((entry) => entry.entryName),
|
|
38
|
+
readFile: (name) => {
|
|
39
|
+
const entry = admZip.getEntry(name);
|
|
40
|
+
if (!entry) {
|
|
41
|
+
throw new Error(`Zip entry not found: ${name}`);
|
|
42
|
+
}
|
|
43
|
+
return Promise.resolve(entry.getData());
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const data = (0, io_1.readBinaryFromInput)(input);
|
|
49
|
+
if ((0, io_1.isNodeRuntime)()) {
|
|
50
|
+
const AdmZip = (0, io_1.getNodeRequire)()('adm-zip');
|
|
51
|
+
const admZip = new AdmZip(Buffer.from(data));
|
|
52
|
+
return {
|
|
53
|
+
zip: {
|
|
54
|
+
listFiles: () => admZip.getEntries().map((entry) => entry.entryName),
|
|
55
|
+
readFile: (name) => {
|
|
56
|
+
const entry = admZip.getEntry(name);
|
|
57
|
+
if (!entry) {
|
|
58
|
+
throw new Error(`Zip entry not found: ${name}`);
|
|
59
|
+
}
|
|
60
|
+
return Promise.resolve(entry.getData());
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const module = await Promise.resolve().then(() => __importStar(require('jszip')));
|
|
66
|
+
const init = module.default || module;
|
|
67
|
+
const zip = await init.loadAsync(data);
|
|
68
|
+
return {
|
|
69
|
+
zip: {
|
|
70
|
+
listFiles: () => Object.keys(zip.files),
|
|
71
|
+
readFile: async (name) => {
|
|
72
|
+
const file = zip.file(name);
|
|
73
|
+
if (!file) {
|
|
74
|
+
throw new Error(`Zip entry not found: ${name}`);
|
|
75
|
+
}
|
|
76
|
+
return file.async('uint8array');
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -1,45 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
4
|
};
|
|
28
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
6
|
exports.ApplePanelsValidator = void 0;
|
|
30
7
|
/* eslint-disable @typescript-eslint/require-await */
|
|
31
|
-
const fs = __importStar(require("fs"));
|
|
32
|
-
const path = __importStar(require("path"));
|
|
33
8
|
const plist_1 = __importDefault(require("plist"));
|
|
34
9
|
const baseValidator_1 = require("./baseValidator");
|
|
10
|
+
const io_1 = require("../utils/io");
|
|
35
11
|
/**
|
|
36
12
|
* Validator for Apple Panels (.plist or .ascconfig directory)
|
|
37
13
|
*/
|
|
38
14
|
class ApplePanelsValidator extends baseValidator_1.BaseValidator {
|
|
39
15
|
static async validateFile(filePath) {
|
|
40
16
|
const validator = new ApplePanelsValidator();
|
|
17
|
+
const fs = (0, io_1.getFs)();
|
|
18
|
+
const path = (0, io_1.getPath)();
|
|
41
19
|
let content;
|
|
42
|
-
const filename =
|
|
20
|
+
const filename = (0, io_1.getBasename)(filePath);
|
|
43
21
|
let size = 0;
|
|
44
22
|
const stats = fs.existsSync(filePath) ? fs.statSync(filePath) : null;
|
|
45
23
|
if (stats?.isDirectory() && filename.toLowerCase().endsWith('.ascconfig')) {
|
|
@@ -62,7 +40,12 @@ class ApplePanelsValidator extends baseValidator_1.BaseValidator {
|
|
|
62
40
|
return true;
|
|
63
41
|
}
|
|
64
42
|
try {
|
|
65
|
-
|
|
43
|
+
if (typeof content !== 'string' &&
|
|
44
|
+
!(content instanceof ArrayBuffer) &&
|
|
45
|
+
!(content instanceof Uint8Array)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const str = typeof content === 'string' ? content : (0, io_1.decodeText)((0, io_1.toUint8Array)(content));
|
|
66
49
|
const parsed = plist_1.default.parse(str);
|
|
67
50
|
return Boolean(parsed.panels || parsed.Panels);
|
|
68
51
|
}
|
|
@@ -80,7 +63,7 @@ class ApplePanelsValidator extends baseValidator_1.BaseValidator {
|
|
|
80
63
|
let parsed = null;
|
|
81
64
|
await this.add_check('plist_parse', 'valid plist/XML', async () => {
|
|
82
65
|
try {
|
|
83
|
-
const str =
|
|
66
|
+
const str = (0, io_1.decodeText)(content);
|
|
84
67
|
parsed = plist_1.default.parse(str);
|
|
85
68
|
}
|
|
86
69
|
catch (e) {
|
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
3
|
exports.AstericsGridValidator = void 0;
|
|
27
4
|
/* eslint-disable @typescript-eslint/require-await */
|
|
28
|
-
const fs = __importStar(require("fs"));
|
|
29
|
-
const path = __importStar(require("path"));
|
|
30
5
|
const baseValidator_1 = require("./baseValidator");
|
|
6
|
+
const io_1 = require("../utils/io");
|
|
31
7
|
/**
|
|
32
8
|
* Validator for Asterics Grid (.grd) JSON files
|
|
33
9
|
*/
|
|
@@ -37,9 +13,9 @@ class AstericsGridValidator extends baseValidator_1.BaseValidator {
|
|
|
37
13
|
*/
|
|
38
14
|
static async validateFile(filePath) {
|
|
39
15
|
const validator = new AstericsGridValidator();
|
|
40
|
-
const content =
|
|
41
|
-
const stats =
|
|
42
|
-
return validator.validate(content,
|
|
16
|
+
const content = (0, io_1.readBinaryFromInput)(filePath);
|
|
17
|
+
const stats = (0, io_1.getFs)().statSync(filePath);
|
|
18
|
+
return validator.validate(content, (0, io_1.getBasename)(filePath), stats.size);
|
|
43
19
|
}
|
|
44
20
|
/**
|
|
45
21
|
* Identify whether the content appears to be an Asterics .grd file
|
|
@@ -50,7 +26,12 @@ class AstericsGridValidator extends baseValidator_1.BaseValidator {
|
|
|
50
26
|
return true;
|
|
51
27
|
}
|
|
52
28
|
try {
|
|
53
|
-
|
|
29
|
+
if (typeof content !== 'string' &&
|
|
30
|
+
!(content instanceof ArrayBuffer) &&
|
|
31
|
+
!(content instanceof Uint8Array)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const str = typeof content === 'string' ? content : (0, io_1.decodeText)((0, io_1.toUint8Array)(content));
|
|
54
35
|
const json = JSON.parse(str);
|
|
55
36
|
return Array.isArray(json?.grids);
|
|
56
37
|
}
|
|
@@ -68,7 +49,7 @@ class AstericsGridValidator extends baseValidator_1.BaseValidator {
|
|
|
68
49
|
let json = null;
|
|
69
50
|
await this.add_check('json_parse', 'valid JSON', async () => {
|
|
70
51
|
try {
|
|
71
|
-
let str =
|
|
52
|
+
let str = (0, io_1.decodeText)(content);
|
|
72
53
|
if (str.charCodeAt(0) === 0xfeff) {
|
|
73
54
|
str = str.slice(1);
|
|
74
55
|
}
|