treste 2.5.1 → 2.5.2
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 +19 -7
- package/dist/compiler/web.d.ts +8 -0
- package/dist/compiler/web.d.ts.map +1 -1
- package/dist/compiler/web.js +135 -4
- package/dist/compiler/web.js.map +1 -1
- package/dist/interpreter.d.ts +4 -0
- package/dist/interpreter.d.ts.map +1 -1
- package/dist/interpreter.js +166 -0
- package/dist/interpreter.js.map +1 -1
- package/dist/lexer.d.ts.map +1 -1
- package/dist/lexer.js +2 -0
- package/dist/lexer.js.map +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +4 -0
- package/dist/parser.js.map +1 -1
- package/dist/std/dom.trest +96 -0
- package/dist/std/style.trest +78 -0
- package/dist/std/test.trest +61 -0
- package/dist/std-native.d.ts +208 -2
- package/dist/std-native.d.ts.map +1 -1
- package/dist/std-native.js +823 -50
- package/dist/std-native.js.map +1 -1
- package/package.json +7 -2
- package/src/std/dom.trest +96 -0
- package/src/std/style.trest +78 -0
- package/src/std/test.trest +61 -0
package/dist/std-native.js
CHANGED
|
@@ -37,12 +37,51 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
};
|
|
38
38
|
})();
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.StdModules = exports.StdIO = exports.StdProcess = exports.StdPath = exports.StdRegEx = exports.StdCrypto = exports.StdDate = exports.StdJSON = exports.StdFileSystem = exports.StdDatabase = exports.StdGUI = exports.StdAsync = exports.StdHTTP = void 0;
|
|
40
|
+
exports.StdModules = exports.StdTest = exports.StdStyle = exports.StdDOM = exports.StdIO = exports.StdProcess = exports.StdPath = exports.StdRegEx = exports.StdCrypto = exports.StdDate = exports.StdJSON = exports.StdFileSystem = exports.StdDatabase = exports.StdGUI = exports.StdAsync = exports.StdHTTP = void 0;
|
|
41
41
|
const http = __importStar(require("http"));
|
|
42
42
|
const https = __importStar(require("https"));
|
|
43
43
|
const fs = __importStar(require("fs"));
|
|
44
44
|
const path = __importStar(require("path"));
|
|
45
45
|
const url_1 = require("url");
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
const readline = __importStar(require("readline"));
|
|
48
|
+
// Database drivers - lazy loading
|
|
49
|
+
let Database;
|
|
50
|
+
let mysql;
|
|
51
|
+
let pg;
|
|
52
|
+
function loadSQLite() {
|
|
53
|
+
if (!Database) {
|
|
54
|
+
try {
|
|
55
|
+
Database = require('better-sqlite3');
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
// Silently fail - will throw error when used
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return Database;
|
|
62
|
+
}
|
|
63
|
+
function loadMySQL() {
|
|
64
|
+
if (!mysql) {
|
|
65
|
+
try {
|
|
66
|
+
mysql = require('mysql2/promise');
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
// Silently fail - will throw error when used
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return mysql;
|
|
73
|
+
}
|
|
74
|
+
function loadPostgreSQL() {
|
|
75
|
+
if (!pg) {
|
|
76
|
+
try {
|
|
77
|
+
pg = require('pg');
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
// Silently fail - will throw error when used
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return pg;
|
|
84
|
+
}
|
|
46
85
|
/**
|
|
47
86
|
* ========================================
|
|
48
87
|
* HTTP Module - Cliente e Servidor HTTP
|
|
@@ -1365,68 +1404,380 @@ StdGUI._ipcHandlersRegistered = false;
|
|
|
1365
1404
|
*/
|
|
1366
1405
|
class StdDatabase {
|
|
1367
1406
|
/**
|
|
1368
|
-
*
|
|
1407
|
+
* Sanitiza query SQL substituindo ? pelos valores de forma segura (Prevent SQL Injection)
|
|
1408
|
+
*/
|
|
1409
|
+
static sanitizeQuery(query, params) {
|
|
1410
|
+
if (!params || params.length === 0) {
|
|
1411
|
+
return query;
|
|
1412
|
+
}
|
|
1413
|
+
// Escapar valores para prevenir SQL Injection
|
|
1414
|
+
const escapeValue = (value) => {
|
|
1415
|
+
if (value === null || value === undefined) {
|
|
1416
|
+
return 'NULL';
|
|
1417
|
+
}
|
|
1418
|
+
if (typeof value === 'number') {
|
|
1419
|
+
return String(value);
|
|
1420
|
+
}
|
|
1421
|
+
if (typeof value === 'boolean') {
|
|
1422
|
+
return value ? '1' : '0';
|
|
1423
|
+
}
|
|
1424
|
+
// String: escapar aspas simples e barras
|
|
1425
|
+
const escaped = String(value)
|
|
1426
|
+
.replace(/\\/g, '\\\\')
|
|
1427
|
+
.replace(/'/g, "''")
|
|
1428
|
+
.replace(/"/g, '""');
|
|
1429
|
+
return `'${escaped}'`;
|
|
1430
|
+
};
|
|
1431
|
+
// Substituir cada ? pelo valor correspondente
|
|
1432
|
+
let safeQuery = query;
|
|
1433
|
+
let paramIndex = 0;
|
|
1434
|
+
// Substituir ? pelos valores escapados
|
|
1435
|
+
safeQuery = safeQuery.replace(/\?/g, () => {
|
|
1436
|
+
if (paramIndex < params.length) {
|
|
1437
|
+
const value = escapeValue(params[paramIndex]);
|
|
1438
|
+
paramIndex++;
|
|
1439
|
+
return value;
|
|
1440
|
+
}
|
|
1441
|
+
return '?'; // Se não houver parâmetro suficiente, manter ?
|
|
1442
|
+
});
|
|
1443
|
+
return safeQuery;
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* Detect database type from connection string or path
|
|
1447
|
+
*/
|
|
1448
|
+
static detectDBType(connection) {
|
|
1449
|
+
if (connection.startsWith('mysql://') || connection.startsWith('mysql2://')) {
|
|
1450
|
+
return 'mysql';
|
|
1451
|
+
}
|
|
1452
|
+
if (connection.startsWith('postgresql://') || connection.startsWith('postgres://')) {
|
|
1453
|
+
return 'postgresql';
|
|
1454
|
+
}
|
|
1455
|
+
if (connection.endsWith('.db') || connection.includes('/') || connection.includes('\\')) {
|
|
1456
|
+
return 'sqlite';
|
|
1457
|
+
}
|
|
1458
|
+
return 'unknown';
|
|
1459
|
+
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Parse MySQL connection string
|
|
1462
|
+
*/
|
|
1463
|
+
static parseMySQLConnection(connectionString) {
|
|
1464
|
+
try {
|
|
1465
|
+
const url = new url_1.URL(connectionString);
|
|
1466
|
+
return {
|
|
1467
|
+
host: url.hostname,
|
|
1468
|
+
port: parseInt(url.port) || 3306,
|
|
1469
|
+
user: url.username,
|
|
1470
|
+
password: url.password,
|
|
1471
|
+
database: url.pathname.substring(1),
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
catch (e) {
|
|
1475
|
+
throw new Error(`Invalid MySQL connection string: ${connectionString}`);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Parse PostgreSQL connection string
|
|
1369
1480
|
*/
|
|
1370
|
-
static
|
|
1481
|
+
static parsePostgreSQLConnection(connectionString) {
|
|
1482
|
+
try {
|
|
1483
|
+
const url = new url_1.URL(connectionString);
|
|
1484
|
+
return {
|
|
1485
|
+
host: url.hostname,
|
|
1486
|
+
port: parseInt(url.port) || 5432,
|
|
1487
|
+
user: url.username,
|
|
1488
|
+
password: url.password,
|
|
1489
|
+
database: url.pathname.substring(1),
|
|
1490
|
+
ssl: url.searchParams.get('ssl') === 'true',
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
catch (e) {
|
|
1494
|
+
throw new Error(`Invalid PostgreSQL connection string: ${connectionString}`);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Open Database - Supports SQLite, MySQL, PostgreSQL
|
|
1499
|
+
*/
|
|
1500
|
+
static openDB(connection) {
|
|
1501
|
+
// If it's an object, treat as config
|
|
1502
|
+
if (typeof connection === 'object' && connection !== null) {
|
|
1503
|
+
if (connection.type === 'mysql' || connection.host && !connection.path) {
|
|
1504
|
+
return this.openMySQL(connection);
|
|
1505
|
+
}
|
|
1506
|
+
if (connection.type === 'postgresql' || connection.type === 'postgres') {
|
|
1507
|
+
return this.openPostgreSQL(connection);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
// Detect type from connection string
|
|
1511
|
+
const dbType = this.detectDBType(String(connection));
|
|
1512
|
+
if (dbType === 'mysql') {
|
|
1513
|
+
const config = this.parseMySQLConnection(String(connection));
|
|
1514
|
+
return this.openMySQL(config);
|
|
1515
|
+
}
|
|
1516
|
+
if (dbType === 'postgresql') {
|
|
1517
|
+
const config = this.parsePostgreSQLConnection(String(connection));
|
|
1518
|
+
return this.openPostgreSQL(config);
|
|
1519
|
+
}
|
|
1520
|
+
// Default to SQLite
|
|
1521
|
+
return this.openSQLite(String(connection));
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Open SQLite Database (real implementation)
|
|
1525
|
+
*/
|
|
1526
|
+
static openSQLite(dbPath) {
|
|
1371
1527
|
if (this.dbConnections.has(dbPath)) {
|
|
1372
1528
|
return this.dbConnections.get(dbPath);
|
|
1373
1529
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1530
|
+
const Database = loadSQLite();
|
|
1531
|
+
if (!Database) {
|
|
1532
|
+
throw new Error('better-sqlite3 is not installed. Install it with: npm install better-sqlite3');
|
|
1533
|
+
}
|
|
1534
|
+
try {
|
|
1535
|
+
const db = new Database(dbPath);
|
|
1536
|
+
const dbWrapper = {
|
|
1537
|
+
path: dbPath,
|
|
1538
|
+
_db: db,
|
|
1539
|
+
execute: (query, params = []) => {
|
|
1540
|
+
try {
|
|
1541
|
+
const stmt = db.prepare(query);
|
|
1542
|
+
const result = stmt.run(...params);
|
|
1543
|
+
return {
|
|
1544
|
+
success: true,
|
|
1545
|
+
lastInsertRowid: result.lastInsertRowid,
|
|
1546
|
+
changes: result.changes
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
catch (error) {
|
|
1550
|
+
throw new Error(`SQLite execute error: ${error.message}`);
|
|
1551
|
+
}
|
|
1552
|
+
},
|
|
1553
|
+
query: (query, params = []) => {
|
|
1554
|
+
try {
|
|
1555
|
+
const stmt = db.prepare(query);
|
|
1556
|
+
return stmt.all(...params);
|
|
1557
|
+
}
|
|
1558
|
+
catch (error) {
|
|
1559
|
+
throw new Error(`SQLite query error: ${error.message}`);
|
|
1560
|
+
}
|
|
1561
|
+
},
|
|
1562
|
+
transaction: (fn) => {
|
|
1563
|
+
try {
|
|
1564
|
+
const transaction = db.transaction(fn);
|
|
1565
|
+
transaction();
|
|
1566
|
+
}
|
|
1567
|
+
catch (error) {
|
|
1568
|
+
throw new Error(`SQLite transaction error: ${error.message}`);
|
|
1569
|
+
}
|
|
1570
|
+
},
|
|
1571
|
+
close: () => {
|
|
1572
|
+
try {
|
|
1573
|
+
db.close();
|
|
1574
|
+
this.dbConnections.delete(dbPath);
|
|
1575
|
+
}
|
|
1576
|
+
catch (error) {
|
|
1577
|
+
throw new Error(`SQLite close error: ${error.message}`);
|
|
1578
|
+
}
|
|
1579
|
+
},
|
|
1580
|
+
};
|
|
1581
|
+
this.dbConnections.set(dbPath, dbWrapper);
|
|
1582
|
+
return dbWrapper;
|
|
1583
|
+
}
|
|
1584
|
+
catch (error) {
|
|
1585
|
+
throw new Error(`Failed to open SQLite database: ${error.message}`);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Open MySQL Database (real implementation)
|
|
1590
|
+
*/
|
|
1591
|
+
static openMySQL(config) {
|
|
1592
|
+
const connectionKey = `mysql://${config.host}:${config.port}/${config.database}`;
|
|
1593
|
+
if (this.dbConnections.has(connectionKey)) {
|
|
1594
|
+
return this.dbConnections.get(connectionKey);
|
|
1595
|
+
}
|
|
1596
|
+
const mysql = loadMySQL();
|
|
1597
|
+
if (!mysql) {
|
|
1598
|
+
throw new Error('mysql2 is not installed. Install it with: npm install mysql2');
|
|
1599
|
+
}
|
|
1600
|
+
try {
|
|
1601
|
+
const pool = mysql.createPool({
|
|
1602
|
+
host: config.host || 'localhost',
|
|
1603
|
+
port: config.port || 3306,
|
|
1604
|
+
user: config.user || 'root',
|
|
1605
|
+
password: config.password || '',
|
|
1606
|
+
database: config.database,
|
|
1607
|
+
waitForConnections: true,
|
|
1608
|
+
connectionLimit: 10,
|
|
1609
|
+
queueLimit: 0,
|
|
1610
|
+
});
|
|
1611
|
+
const dbWrapper = {
|
|
1612
|
+
_pool: pool,
|
|
1613
|
+
_config: config,
|
|
1614
|
+
execute: async (query, params = []) => {
|
|
1615
|
+
try {
|
|
1616
|
+
const [result] = await pool.execute(query, params);
|
|
1617
|
+
return {
|
|
1618
|
+
success: true,
|
|
1619
|
+
insertId: result.insertId,
|
|
1620
|
+
affectedRows: result.affectedRows
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
catch (error) {
|
|
1624
|
+
throw new Error(`MySQL execute error: ${error.message}`);
|
|
1625
|
+
}
|
|
1626
|
+
},
|
|
1627
|
+
query: async (query, params = []) => {
|
|
1628
|
+
try {
|
|
1629
|
+
const [rows] = await pool.execute(query, params);
|
|
1630
|
+
return rows;
|
|
1631
|
+
}
|
|
1632
|
+
catch (error) {
|
|
1633
|
+
throw new Error(`MySQL query error: ${error.message}`);
|
|
1634
|
+
}
|
|
1635
|
+
},
|
|
1636
|
+
transaction: async (fn) => {
|
|
1637
|
+
const connection = await pool.getConnection();
|
|
1638
|
+
try {
|
|
1639
|
+
await connection.beginTransaction();
|
|
1640
|
+
await fn(connection);
|
|
1641
|
+
await connection.commit();
|
|
1642
|
+
}
|
|
1643
|
+
catch (error) {
|
|
1644
|
+
await connection.rollback();
|
|
1645
|
+
throw new Error(`MySQL transaction error: ${error.message}`);
|
|
1646
|
+
}
|
|
1647
|
+
finally {
|
|
1648
|
+
connection.release();
|
|
1649
|
+
}
|
|
1650
|
+
},
|
|
1651
|
+
close: async () => {
|
|
1652
|
+
try {
|
|
1653
|
+
await pool.end();
|
|
1654
|
+
this.dbConnections.delete(connectionKey);
|
|
1655
|
+
}
|
|
1656
|
+
catch (error) {
|
|
1657
|
+
throw new Error(`MySQL close error: ${error.message}`);
|
|
1658
|
+
}
|
|
1659
|
+
},
|
|
1660
|
+
};
|
|
1661
|
+
this.dbConnections.set(connectionKey, dbWrapper);
|
|
1662
|
+
return dbWrapper;
|
|
1663
|
+
}
|
|
1664
|
+
catch (error) {
|
|
1665
|
+
throw new Error(`Failed to open MySQL database: ${error.message}`);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
/**
|
|
1669
|
+
* Open PostgreSQL Database (real implementation)
|
|
1670
|
+
*/
|
|
1671
|
+
static openPostgreSQL(config) {
|
|
1672
|
+
const connectionKey = `postgresql://${config.host}:${config.port}/${config.database}`;
|
|
1673
|
+
if (this.dbConnections.has(connectionKey)) {
|
|
1674
|
+
return this.dbConnections.get(connectionKey);
|
|
1675
|
+
}
|
|
1676
|
+
const pgLib = loadPostgreSQL();
|
|
1677
|
+
if (!pgLib) {
|
|
1678
|
+
throw new Error('pg is not installed. Install it with: npm install pg');
|
|
1679
|
+
}
|
|
1680
|
+
try {
|
|
1681
|
+
const pool = new pgLib.Pool({
|
|
1682
|
+
host: config.host || 'localhost',
|
|
1683
|
+
port: config.port || 5432,
|
|
1684
|
+
user: config.user || 'postgres',
|
|
1685
|
+
password: config.password || '',
|
|
1686
|
+
database: config.database,
|
|
1687
|
+
max: 20,
|
|
1688
|
+
idleTimeoutMillis: 30000,
|
|
1689
|
+
connectionTimeoutMillis: 2000,
|
|
1690
|
+
ssl: config.ssl || false,
|
|
1691
|
+
});
|
|
1692
|
+
const dbWrapper = {
|
|
1693
|
+
_pool: pool,
|
|
1694
|
+
_config: config,
|
|
1695
|
+
execute: async (query, params = []) => {
|
|
1696
|
+
try {
|
|
1697
|
+
const result = await pool.query(query, params);
|
|
1698
|
+
return {
|
|
1699
|
+
success: true,
|
|
1700
|
+
rowCount: result.rowCount,
|
|
1701
|
+
rows: result.rows
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
catch (error) {
|
|
1705
|
+
throw new Error(`PostgreSQL execute error: ${error.message}`);
|
|
1706
|
+
}
|
|
1707
|
+
},
|
|
1708
|
+
query: async (query, params = []) => {
|
|
1709
|
+
try {
|
|
1710
|
+
const result = await pool.query(query, params);
|
|
1711
|
+
return result.rows;
|
|
1712
|
+
}
|
|
1713
|
+
catch (error) {
|
|
1714
|
+
throw new Error(`PostgreSQL query error: ${error.message}`);
|
|
1715
|
+
}
|
|
1716
|
+
},
|
|
1717
|
+
transaction: async (fn) => {
|
|
1718
|
+
const client = await pool.connect();
|
|
1719
|
+
try {
|
|
1720
|
+
await client.query('BEGIN');
|
|
1721
|
+
await fn(client);
|
|
1722
|
+
await client.query('COMMIT');
|
|
1723
|
+
}
|
|
1724
|
+
catch (error) {
|
|
1725
|
+
await client.query('ROLLBACK');
|
|
1726
|
+
throw new Error(`PostgreSQL transaction error: ${error.message}`);
|
|
1727
|
+
}
|
|
1728
|
+
finally {
|
|
1729
|
+
client.release();
|
|
1730
|
+
}
|
|
1731
|
+
},
|
|
1732
|
+
close: async () => {
|
|
1733
|
+
try {
|
|
1734
|
+
await pool.end();
|
|
1735
|
+
this.dbConnections.delete(connectionKey);
|
|
1736
|
+
}
|
|
1737
|
+
catch (error) {
|
|
1738
|
+
throw new Error(`PostgreSQL close error: ${error.message}`);
|
|
1739
|
+
}
|
|
1740
|
+
},
|
|
1741
|
+
};
|
|
1742
|
+
this.dbConnections.set(connectionKey, dbWrapper);
|
|
1743
|
+
return dbWrapper;
|
|
1744
|
+
}
|
|
1745
|
+
catch (error) {
|
|
1746
|
+
throw new Error(`Failed to open PostgreSQL database: ${error.message}`);
|
|
1747
|
+
}
|
|
1397
1748
|
}
|
|
1398
1749
|
/**
|
|
1399
1750
|
* Query Builder
|
|
1400
1751
|
*/
|
|
1401
1752
|
static createQueryBuilder(table) {
|
|
1402
1753
|
const builder = {
|
|
1403
|
-
table,
|
|
1754
|
+
table: table,
|
|
1404
1755
|
selectFields: '*',
|
|
1405
1756
|
whereClause: '',
|
|
1406
1757
|
orderClause: '',
|
|
1407
1758
|
limitValue: '',
|
|
1408
1759
|
conditions: [],
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1760
|
+
};
|
|
1761
|
+
builder.select = function (fields) {
|
|
1762
|
+
builder.selectFields = fields;
|
|
1763
|
+
return builder;
|
|
1764
|
+
};
|
|
1765
|
+
builder.where = function (condition) {
|
|
1766
|
+
builder.whereClause = `WHERE ${condition}`;
|
|
1767
|
+
return builder;
|
|
1768
|
+
};
|
|
1769
|
+
builder.order = function (field) {
|
|
1770
|
+
builder.orderClause = `ORDER BY ${field}`;
|
|
1771
|
+
return builder;
|
|
1772
|
+
};
|
|
1773
|
+
builder.limit = function (n) {
|
|
1774
|
+
builder.limitValue = `LIMIT ${n}`;
|
|
1775
|
+
return builder;
|
|
1776
|
+
};
|
|
1777
|
+
builder.execute = function () {
|
|
1778
|
+
const sql = `SELECT ${builder.selectFields} FROM ${builder.table} ${builder.whereClause} ${builder.orderClause} ${builder.limitValue}`;
|
|
1779
|
+
console.log(`[Query Builder] ${sql}`);
|
|
1780
|
+
return [];
|
|
1430
1781
|
};
|
|
1431
1782
|
return builder;
|
|
1432
1783
|
}
|
|
@@ -1634,7 +1985,6 @@ exports.StdDate = StdDate;
|
|
|
1634
1985
|
* Crypto Module
|
|
1635
1986
|
* ========================================
|
|
1636
1987
|
*/
|
|
1637
|
-
const crypto = __importStar(require("crypto"));
|
|
1638
1988
|
class StdCrypto {
|
|
1639
1989
|
/**
|
|
1640
1990
|
* Hash MD5
|
|
@@ -1876,7 +2226,6 @@ exports.StdProcess = StdProcess;
|
|
|
1876
2226
|
* IO Module - Entrada e Saída
|
|
1877
2227
|
* ========================================
|
|
1878
2228
|
*/
|
|
1879
|
-
const readline = __importStar(require("readline"));
|
|
1880
2229
|
class StdIO {
|
|
1881
2230
|
/**
|
|
1882
2231
|
* Initialize readline interface if needed
|
|
@@ -1998,6 +2347,427 @@ class StdIO {
|
|
|
1998
2347
|
}
|
|
1999
2348
|
exports.StdIO = StdIO;
|
|
2000
2349
|
StdIO.rl = null;
|
|
2350
|
+
/**
|
|
2351
|
+
* ========================================
|
|
2352
|
+
* DOM Module - Manipulação de DOM (Front-End)
|
|
2353
|
+
* ========================================
|
|
2354
|
+
*/
|
|
2355
|
+
class StdDOM {
|
|
2356
|
+
/**
|
|
2357
|
+
* Verifica se está rodando no navegador
|
|
2358
|
+
*/
|
|
2359
|
+
static isBrowser() {
|
|
2360
|
+
return typeof globalThis.window !== 'undefined' && typeof globalThis.document !== 'undefined';
|
|
2361
|
+
}
|
|
2362
|
+
/**
|
|
2363
|
+
* Selecionar elemento (querySelector)
|
|
2364
|
+
*/
|
|
2365
|
+
static selecionar(seletor) {
|
|
2366
|
+
if (!this.isBrowser()) {
|
|
2367
|
+
throw new Error('DOM.selecionar só funciona no navegador. Use --mode web para compilar.');
|
|
2368
|
+
}
|
|
2369
|
+
return globalThis.document.querySelector(seletor);
|
|
2370
|
+
}
|
|
2371
|
+
static select(seletor) {
|
|
2372
|
+
return this.selecionar(seletor);
|
|
2373
|
+
}
|
|
2374
|
+
/**
|
|
2375
|
+
* Adicionar evento (addEventListener)
|
|
2376
|
+
*/
|
|
2377
|
+
static evento(elemento, tipo, callback) {
|
|
2378
|
+
if (!this.isBrowser()) {
|
|
2379
|
+
throw new Error('DOM.evento só funciona no navegador. Use --mode web para compilar.');
|
|
2380
|
+
}
|
|
2381
|
+
if (elemento && elemento.addEventListener) {
|
|
2382
|
+
elemento.addEventListener(tipo, callback);
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
static addEvent(elemento, tipo, callback) {
|
|
2386
|
+
this.evento(elemento, tipo, callback);
|
|
2387
|
+
}
|
|
2388
|
+
/**
|
|
2389
|
+
* Manipular texto (innerText)
|
|
2390
|
+
*/
|
|
2391
|
+
static texto(elemento, valor) {
|
|
2392
|
+
if (!this.isBrowser()) {
|
|
2393
|
+
throw new Error('DOM.texto só funciona no navegador. Use --mode web para compilar.');
|
|
2394
|
+
}
|
|
2395
|
+
if (!elemento)
|
|
2396
|
+
return '';
|
|
2397
|
+
if (valor !== undefined) {
|
|
2398
|
+
elemento.innerText = valor;
|
|
2399
|
+
}
|
|
2400
|
+
else {
|
|
2401
|
+
return elemento.innerText || '';
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
static setText(elemento, valor) {
|
|
2405
|
+
return this.texto(elemento, valor);
|
|
2406
|
+
}
|
|
2407
|
+
/**
|
|
2408
|
+
* Manipular HTML (innerHTML)
|
|
2409
|
+
*/
|
|
2410
|
+
static html(elemento, valor) {
|
|
2411
|
+
if (!this.isBrowser()) {
|
|
2412
|
+
throw new Error('DOM.html só funciona no navegador. Use --mode web para compilar.');
|
|
2413
|
+
}
|
|
2414
|
+
if (!elemento)
|
|
2415
|
+
return '';
|
|
2416
|
+
if (valor !== undefined) {
|
|
2417
|
+
elemento.innerHTML = valor;
|
|
2418
|
+
}
|
|
2419
|
+
else {
|
|
2420
|
+
return elemento.innerHTML || '';
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
static setHTML(elemento, valor) {
|
|
2424
|
+
return this.html(elemento, valor);
|
|
2425
|
+
}
|
|
2426
|
+
/**
|
|
2427
|
+
* Obter/definir valor de input (value)
|
|
2428
|
+
*/
|
|
2429
|
+
static valor(elemento, valor) {
|
|
2430
|
+
if (!this.isBrowser()) {
|
|
2431
|
+
throw new Error('DOM.valor só funciona no navegador. Use --mode web para compilar.');
|
|
2432
|
+
}
|
|
2433
|
+
if (!elemento)
|
|
2434
|
+
return null;
|
|
2435
|
+
if (valor !== undefined) {
|
|
2436
|
+
elemento.value = valor;
|
|
2437
|
+
}
|
|
2438
|
+
else {
|
|
2439
|
+
return elemento.value !== undefined ? elemento.value : null;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
static val(elemento, valor) {
|
|
2443
|
+
return this.valor(elemento, valor);
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Criar elemento (createElement)
|
|
2447
|
+
*/
|
|
2448
|
+
static criar(tag) {
|
|
2449
|
+
if (!this.isBrowser()) {
|
|
2450
|
+
throw new Error('DOM.criar só funciona no navegador. Use --mode web para compilar.');
|
|
2451
|
+
}
|
|
2452
|
+
return globalThis.document.createElement(tag);
|
|
2453
|
+
}
|
|
2454
|
+
static create(tag) {
|
|
2455
|
+
return this.criar(tag);
|
|
2456
|
+
}
|
|
2457
|
+
/**
|
|
2458
|
+
* Adicionar elemento ao DOM (appendChild)
|
|
2459
|
+
*/
|
|
2460
|
+
static adicionar(parent, child) {
|
|
2461
|
+
if (!this.isBrowser()) {
|
|
2462
|
+
throw new Error('DOM.adicionar só funciona no navegador. Use --mode web para compilar.');
|
|
2463
|
+
}
|
|
2464
|
+
if (parent && parent.appendChild && child) {
|
|
2465
|
+
parent.appendChild(child);
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
static append(parent, child) {
|
|
2469
|
+
this.adicionar(parent, child);
|
|
2470
|
+
}
|
|
2471
|
+
/**
|
|
2472
|
+
* Remover elemento (removeChild)
|
|
2473
|
+
*/
|
|
2474
|
+
static remover(elemento) {
|
|
2475
|
+
if (!this.isBrowser()) {
|
|
2476
|
+
throw new Error('DOM.remover só funciona no navegador. Use --mode web para compilar.');
|
|
2477
|
+
}
|
|
2478
|
+
if (elemento && elemento.parentNode) {
|
|
2479
|
+
elemento.parentNode.removeChild(elemento);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
static remove(elemento) {
|
|
2483
|
+
this.remover(elemento);
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* Obter atributo (getAttribute)
|
|
2487
|
+
*/
|
|
2488
|
+
static atributo(elemento, nome) {
|
|
2489
|
+
if (!this.isBrowser()) {
|
|
2490
|
+
throw new Error('DOM.atributo só funciona no navegador. Use --mode web para compilar.');
|
|
2491
|
+
}
|
|
2492
|
+
if (!elemento || !elemento.getAttribute)
|
|
2493
|
+
return null;
|
|
2494
|
+
return elemento.getAttribute(nome);
|
|
2495
|
+
}
|
|
2496
|
+
static getAttr(elemento, nome) {
|
|
2497
|
+
return this.atributo(elemento, nome);
|
|
2498
|
+
}
|
|
2499
|
+
/**
|
|
2500
|
+
* Definir atributo (setAttribute)
|
|
2501
|
+
*/
|
|
2502
|
+
static definirАтрибут(elemento, nome, valor) {
|
|
2503
|
+
if (!this.isBrowser()) {
|
|
2504
|
+
throw new Error('DOM.definirАтрибут só funciona no navegador. Use --mode web para compilar.');
|
|
2505
|
+
}
|
|
2506
|
+
if (elemento && elemento.setAttribute) {
|
|
2507
|
+
elemento.setAttribute(nome, valor);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
static setAttr(elemento, nome, valor) {
|
|
2511
|
+
this.definirАтрибут(elemento, nome, valor);
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
exports.StdDOM = StdDOM;
|
|
2515
|
+
/**
|
|
2516
|
+
* ========================================
|
|
2517
|
+
* Style Module - Gerenciamento de CSS
|
|
2518
|
+
* ========================================
|
|
2519
|
+
*/
|
|
2520
|
+
class StdStyle {
|
|
2521
|
+
/**
|
|
2522
|
+
* Verifica se está rodando no navegador
|
|
2523
|
+
*/
|
|
2524
|
+
static isBrowser() {
|
|
2525
|
+
return typeof globalThis.window !== 'undefined' && typeof globalThis.document !== 'undefined';
|
|
2526
|
+
}
|
|
2527
|
+
/**
|
|
2528
|
+
* Carregar CSS de CDN (Bootstrap, Tailwind, etc)
|
|
2529
|
+
*/
|
|
2530
|
+
static carregarCDN(url) {
|
|
2531
|
+
if (!this.isBrowser()) {
|
|
2532
|
+
throw new Error('Style.carregarCDN só funciona no navegador. Use --mode web para compilar.');
|
|
2533
|
+
}
|
|
2534
|
+
const doc = globalThis.document;
|
|
2535
|
+
const link = doc.createElement('link');
|
|
2536
|
+
link.rel = 'stylesheet';
|
|
2537
|
+
link.href = url;
|
|
2538
|
+
doc.head.appendChild(link);
|
|
2539
|
+
}
|
|
2540
|
+
static loadCDN(url) {
|
|
2541
|
+
this.carregarCDN(url);
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2544
|
+
* Carregar CSS de arquivo local
|
|
2545
|
+
* No modo web, o compilador deve injetar o conteúdo do arquivo
|
|
2546
|
+
*/
|
|
2547
|
+
static carregarАрхив(caminho) {
|
|
2548
|
+
if (!this.isBrowser()) {
|
|
2549
|
+
// No Node.js, apenas log (o compilador web deve injetar)
|
|
2550
|
+
console.log(`[Style] Carregando CSS: ${caminho} (será injetado no bundle)`);
|
|
2551
|
+
return;
|
|
2552
|
+
}
|
|
2553
|
+
// No navegador, criar link para o arquivo
|
|
2554
|
+
const doc = globalThis.document;
|
|
2555
|
+
const link = doc.createElement('link');
|
|
2556
|
+
link.rel = 'stylesheet';
|
|
2557
|
+
link.href = caminho;
|
|
2558
|
+
doc.head.appendChild(link);
|
|
2559
|
+
}
|
|
2560
|
+
static loadFile(caminho) {
|
|
2561
|
+
this.carregarАрхив(caminho);
|
|
2562
|
+
}
|
|
2563
|
+
/**
|
|
2564
|
+
* Aplicar estilos inline a um elemento
|
|
2565
|
+
*/
|
|
2566
|
+
static aplicar(elemento, estilos) {
|
|
2567
|
+
if (!this.isBrowser()) {
|
|
2568
|
+
throw new Error('Style.aplicar só funciona no navegador. Use --mode web para compilar.');
|
|
2569
|
+
}
|
|
2570
|
+
if (!elemento || !elemento.style)
|
|
2571
|
+
return;
|
|
2572
|
+
// Mapear propriedades em cirílico para CSS
|
|
2573
|
+
const mapeamento = {
|
|
2574
|
+
cor: 'color',
|
|
2575
|
+
фон: 'backgroundColor',
|
|
2576
|
+
фонЦвет: 'backgroundColor',
|
|
2577
|
+
ширина: 'width',
|
|
2578
|
+
высота: 'height',
|
|
2579
|
+
отступ: 'padding',
|
|
2580
|
+
маржа: 'margin',
|
|
2581
|
+
граница: 'border',
|
|
2582
|
+
размерШрифта: 'fontSize',
|
|
2583
|
+
весШрифта: 'fontWeight',
|
|
2584
|
+
выравнивание: 'textAlign',
|
|
2585
|
+
отображение: 'display',
|
|
2586
|
+
};
|
|
2587
|
+
for (const key in estilos) {
|
|
2588
|
+
const cssProp = mapeamento[key] || key;
|
|
2589
|
+
elemento.style[cssProp] = estilos[key];
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
static apply(elemento, estilos) {
|
|
2593
|
+
this.aplicar(elemento, estilos);
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Obter estilo computado
|
|
2597
|
+
*/
|
|
2598
|
+
static obter(elemento, propriedade) {
|
|
2599
|
+
if (!this.isBrowser()) {
|
|
2600
|
+
throw new Error('Style.obter só funciona no navegador. Use --mode web para compilar.');
|
|
2601
|
+
}
|
|
2602
|
+
if (!elemento)
|
|
2603
|
+
return null;
|
|
2604
|
+
const win = globalThis.window;
|
|
2605
|
+
const computed = win.getComputedStyle ? win.getComputedStyle(elemento) : null;
|
|
2606
|
+
return computed ? computed[propriedade] : null;
|
|
2607
|
+
}
|
|
2608
|
+
static get(elemento, propriedade) {
|
|
2609
|
+
return this.obter(elemento, propriedade);
|
|
2610
|
+
}
|
|
2611
|
+
/**
|
|
2612
|
+
* Definir estilo individual
|
|
2613
|
+
*/
|
|
2614
|
+
static definir(elemento, propriedade, valor) {
|
|
2615
|
+
if (!this.isBrowser()) {
|
|
2616
|
+
throw new Error('Style.definir só funciona no navegador. Use --mode web para compilar.');
|
|
2617
|
+
}
|
|
2618
|
+
if (elemento && elemento.style) {
|
|
2619
|
+
elemento.style[propriedade] = valor;
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
static set(elemento, propriedade, valor) {
|
|
2623
|
+
this.definir(elemento, propriedade, valor);
|
|
2624
|
+
}
|
|
2625
|
+
/**
|
|
2626
|
+
* Adicionar classe CSS
|
|
2627
|
+
*/
|
|
2628
|
+
static добавитьКласс(elemento, classe) {
|
|
2629
|
+
if (!this.isBrowser()) {
|
|
2630
|
+
throw new Error('Style.добавитьКласс só funciona no navegador. Use --mode web para compilar.');
|
|
2631
|
+
}
|
|
2632
|
+
if (elemento && elemento.classList) {
|
|
2633
|
+
elemento.classList.add(classe);
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
static addClass(elemento, classe) {
|
|
2637
|
+
this.добавитьКласс(elemento, classe);
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Remover classe CSS
|
|
2641
|
+
*/
|
|
2642
|
+
static удалитьКласс(elemento, classe) {
|
|
2643
|
+
if (!this.isBrowser()) {
|
|
2644
|
+
throw new Error('Style.удалитьКласс só funciona no navegador. Use --mode web para compilar.');
|
|
2645
|
+
}
|
|
2646
|
+
if (elemento && elemento.classList) {
|
|
2647
|
+
elemento.classList.remove(classe);
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
static removeClass(elemento, classe) {
|
|
2651
|
+
this.удалитьКласс(elemento, classe);
|
|
2652
|
+
}
|
|
2653
|
+
/**
|
|
2654
|
+
* Alternar classe CSS
|
|
2655
|
+
*/
|
|
2656
|
+
static переключитьКласс(elemento, classe) {
|
|
2657
|
+
if (!this.isBrowser()) {
|
|
2658
|
+
throw new Error('Style.переключитьКласс só funciona no navegador. Use --mode web para compilar.');
|
|
2659
|
+
}
|
|
2660
|
+
if (elemento && elemento.classList) {
|
|
2661
|
+
elemento.classList.toggle(classe);
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
static toggleClass(elemento, classe) {
|
|
2665
|
+
this.переключитьКласс(elemento, classe);
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
exports.StdStyle = StdStyle;
|
|
2669
|
+
/**
|
|
2670
|
+
* ========================================
|
|
2671
|
+
* Test Module - Framework de Testes
|
|
2672
|
+
* ========================================
|
|
2673
|
+
*/
|
|
2674
|
+
class StdTest {
|
|
2675
|
+
/**
|
|
2676
|
+
* Descrever um teste
|
|
2677
|
+
*/
|
|
2678
|
+
static descrever(nome, callback) {
|
|
2679
|
+
this.tests.push({ name: nome, fn: callback });
|
|
2680
|
+
}
|
|
2681
|
+
static describe(nome, callback) {
|
|
2682
|
+
this.descrever(nome, callback);
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* Afirmar condição
|
|
2686
|
+
*/
|
|
2687
|
+
static afirmar(condicao, mensagem = 'Assertion failed') {
|
|
2688
|
+
if (!condicao) {
|
|
2689
|
+
throw new Error(mensagem);
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
static assert(condicao, mensagem = 'Assertion failed') {
|
|
2693
|
+
this.afirmar(condicao, mensagem);
|
|
2694
|
+
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Afirmar igualdade
|
|
2697
|
+
*/
|
|
2698
|
+
static igual(esperado, atual, mensagem) {
|
|
2699
|
+
if (esperado !== atual) {
|
|
2700
|
+
const msg = mensagem || `Expected ${esperado}, but got ${atual}`;
|
|
2701
|
+
throw new Error(msg);
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
static equal(esperado, atual, mensagem) {
|
|
2705
|
+
this.igual(esperado, atual, mensagem);
|
|
2706
|
+
}
|
|
2707
|
+
/**
|
|
2708
|
+
* Afirmar que é verdadeiro
|
|
2709
|
+
*/
|
|
2710
|
+
static verdadeiro(valor, mensagem) {
|
|
2711
|
+
if (valor !== true) {
|
|
2712
|
+
const msg = mensagem || `Expected true, but got ${valor}`;
|
|
2713
|
+
throw new Error(msg);
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
static isTrue(valor, mensagem) {
|
|
2717
|
+
this.verdadeiro(valor, mensagem);
|
|
2718
|
+
}
|
|
2719
|
+
/**
|
|
2720
|
+
* Afirmar que é falso
|
|
2721
|
+
*/
|
|
2722
|
+
static ложь(valor, mensagem) {
|
|
2723
|
+
if (valor !== false) {
|
|
2724
|
+
const msg = mensagem || `Expected false, but got ${valor}`;
|
|
2725
|
+
throw new Error(msg);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
static isFalse(valor, mensagem) {
|
|
2729
|
+
this.ложь(valor, mensagem);
|
|
2730
|
+
}
|
|
2731
|
+
/**
|
|
2732
|
+
* Executar todos os testes
|
|
2733
|
+
*/
|
|
2734
|
+
static выполнить() {
|
|
2735
|
+
this.results = [];
|
|
2736
|
+
let passed = 0;
|
|
2737
|
+
let failed = 0;
|
|
2738
|
+
for (const test of this.tests) {
|
|
2739
|
+
try {
|
|
2740
|
+
test.fn();
|
|
2741
|
+
this.results.push({ name: test.name, passed: true });
|
|
2742
|
+
passed++;
|
|
2743
|
+
console.log(`✅ ${test.name}`);
|
|
2744
|
+
}
|
|
2745
|
+
catch (error) {
|
|
2746
|
+
this.results.push({ name: test.name, passed: false, error: error.message });
|
|
2747
|
+
failed++;
|
|
2748
|
+
console.error(`❌ ${test.name}: ${error.message}`);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
console.log(`\n📊 Testes: ${passed} passaram, ${failed} falharam`);
|
|
2752
|
+
return { passed, failed, results: this.results };
|
|
2753
|
+
}
|
|
2754
|
+
static run() {
|
|
2755
|
+
return this.выполнить();
|
|
2756
|
+
}
|
|
2757
|
+
/**
|
|
2758
|
+
* Limpar testes registrados
|
|
2759
|
+
*/
|
|
2760
|
+
static limpar() {
|
|
2761
|
+
this.tests = [];
|
|
2762
|
+
this.results = [];
|
|
2763
|
+
}
|
|
2764
|
+
static clear() {
|
|
2765
|
+
this.limpar();
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
exports.StdTest = StdTest;
|
|
2769
|
+
StdTest.tests = [];
|
|
2770
|
+
StdTest.results = [];
|
|
2001
2771
|
/**
|
|
2002
2772
|
* Export all modules
|
|
2003
2773
|
*/
|
|
@@ -2014,5 +2784,8 @@ exports.StdModules = {
|
|
|
2014
2784
|
Path: StdPath,
|
|
2015
2785
|
Process: StdProcess,
|
|
2016
2786
|
IO: StdIO,
|
|
2787
|
+
DOM: StdDOM,
|
|
2788
|
+
Style: StdStyle,
|
|
2789
|
+
Test: StdTest,
|
|
2017
2790
|
};
|
|
2018
2791
|
//# sourceMappingURL=std-native.js.map
|