api: revamp tests
Pedro Lucas Porcellis porcellis@eletrotupi.com · 6 months ago
bdc1f3aa45bfff5472ae567a15ca20cc76ec3370 Browse filesParents
86b8072Changed files
13
Additions
+1812
Deletions
-1997
api/package-lock.json
1 1
{
2 2
"name": "orbit-api",
3 3
"version": "0.0.0",
4 4
"lockfileVersion": 3,
5 5
"requires": true,
28 28
"@types/better-sqlite3": "^7.6.13",
29 29
"@types/express": "^5.0.6",
30 30
"@types/morgan": "^1.9.10",
31 31
"@types/node": "^25.5.2",
32 32
"ava": "^6.4.1",
33 +
"cross-var": "^1.1.0",
34 +
"dotenv-cli": "^11.0.0",
33 35
"prisma": "^7.5.0",
34 36
"supertest": "^7.1.4",
35 37
"ts-node": "^10.9.2",
36 38
"tsc-alias": "^1.8.16",
37 39
"tsconfig-paths": "^4.2.0",
1544 1546
"license": "MIT",
1545 1547
"engines": {
1546 1548
"node": ">= 6.0.0"
1547 1549
}
1548 1550
},
1551 +
"node_modules/babel-code-frame": {
1552 +
"version": "6.26.0",
1553 +
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
1554 +
"integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==",
1555 +
"dev": true,
1556 +
"license": "MIT",
1557 +
"dependencies": {
1558 +
"chalk": "^1.1.3",
1559 +
"esutils": "^2.0.2",
1560 +
"js-tokens": "^3.0.2"
1561 +
}
1562 +
},
1563 +
"node_modules/babel-code-frame/node_modules/ansi-regex": {
1564 +
"version": "2.1.1",
1565 +
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
1566 +
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
1567 +
"dev": true,
1568 +
"license": "MIT",
1569 +
"engines": {
1570 +
"node": ">=0.10.0"
1571 +
}
1572 +
},
1573 +
"node_modules/babel-code-frame/node_modules/ansi-styles": {
1574 +
"version": "2.2.1",
1575 +
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
1576 +
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
1577 +
"dev": true,
1578 +
"license": "MIT",
1579 +
"engines": {
1580 +
"node": ">=0.10.0"
1581 +
}
1582 +
},
1583 +
"node_modules/babel-code-frame/node_modules/chalk": {
1584 +
"version": "1.1.3",
1585 +
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
1586 +
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
1587 +
"dev": true,
1588 +
"license": "MIT",
1589 +
"dependencies": {
1590 +
"ansi-styles": "^2.2.1",
1591 +
"escape-string-regexp": "^1.0.2",
1592 +
"has-ansi": "^2.0.0",
1593 +
"strip-ansi": "^3.0.0",
1594 +
"supports-color": "^2.0.0"
1595 +
},
1596 +
"engines": {
1597 +
"node": ">=0.10.0"
1598 +
}
1599 +
},
1600 +
"node_modules/babel-code-frame/node_modules/escape-string-regexp": {
1601 +
"version": "1.0.5",
1602 +
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
1603 +
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
1604 +
"dev": true,
1605 +
"license": "MIT",
1606 +
"engines": {
1607 +
"node": ">=0.8.0"
1608 +
}
1609 +
},
1610 +
"node_modules/babel-code-frame/node_modules/strip-ansi": {
1611 +
"version": "3.0.1",
1612 +
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
1613 +
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
1614 +
"dev": true,
1615 +
"license": "MIT",
1616 +
"dependencies": {
1617 +
"ansi-regex": "^2.0.0"
1618 +
},
1619 +
"engines": {
1620 +
"node": ">=0.10.0"
1621 +
}
1622 +
},
1623 +
"node_modules/babel-core": {
1624 +
"version": "6.26.3",
1625 +
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
1626 +
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
1627 +
"dev": true,
1628 +
"license": "MIT",
1629 +
"dependencies": {
1630 +
"babel-code-frame": "^6.26.0",
1631 +
"babel-generator": "^6.26.0",
1632 +
"babel-helpers": "^6.24.1",
1633 +
"babel-messages": "^6.23.0",
1634 +
"babel-register": "^6.26.0",
1635 +
"babel-runtime": "^6.26.0",
1636 +
"babel-template": "^6.26.0",
1637 +
"babel-traverse": "^6.26.0",
1638 +
"babel-types": "^6.26.0",
1639 +
"babylon": "^6.18.0",
1640 +
"convert-source-map": "^1.5.1",
1641 +
"debug": "^2.6.9",
1642 +
"json5": "^0.5.1",
1643 +
"lodash": "^4.17.4",
1644 +
"minimatch": "^3.0.4",
1645 +
"path-is-absolute": "^1.0.1",
1646 +
"private": "^0.1.8",
1647 +
"slash": "^1.0.0",
1648 +
"source-map": "^0.5.7"
1649 +
}
1650 +
},
1651 +
"node_modules/babel-core/node_modules/brace-expansion": {
1652 +
"version": "1.1.13",
1653 +
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
1654 +
"integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
1655 +
"dev": true,
1656 +
"license": "MIT",
1657 +
"dependencies": {
1658 +
"balanced-match": "^1.0.0",
1659 +
"concat-map": "0.0.1"
1660 +
}
1661 +
},
1662 +
"node_modules/babel-core/node_modules/debug": {
1663 +
"version": "2.6.9",
1664 +
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1665 +
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1666 +
"dev": true,
1667 +
"license": "MIT",
1668 +
"dependencies": {
1669 +
"ms": "2.0.0"
1670 +
}
1671 +
},
1672 +
"node_modules/babel-core/node_modules/json5": {
1673 +
"version": "0.5.1",
1674 +
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
1675 +
"integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==",
1676 +
"dev": true,
1677 +
"license": "MIT",
1678 +
"bin": {
1679 +
"json5": "lib/cli.js"
1680 +
}
1681 +
},
1682 +
"node_modules/babel-core/node_modules/minimatch": {
1683 +
"version": "3.1.5",
1684 +
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
1685 +
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
1686 +
"dev": true,
1687 +
"license": "ISC",
1688 +
"dependencies": {
1689 +
"brace-expansion": "^1.1.7"
1690 +
},
1691 +
"engines": {
1692 +
"node": "*"
1693 +
}
1694 +
},
1695 +
"node_modules/babel-core/node_modules/ms": {
1696 +
"version": "2.0.0",
1697 +
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1698 +
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1699 +
"dev": true,
1700 +
"license": "MIT"
1701 +
},
1702 +
"node_modules/babel-core/node_modules/slash": {
1703 +
"version": "1.0.0",
1704 +
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
1705 +
"integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
1706 +
"dev": true,
1707 +
"license": "MIT",
1708 +
"engines": {
1709 +
"node": ">=0.10.0"
1710 +
}
1711 +
},
1712 +
"node_modules/babel-generator": {
1713 +
"version": "6.26.1",
1714 +
"resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
1715 +
"integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
1716 +
"dev": true,
1717 +
"license": "MIT",
1718 +
"dependencies": {
1719 +
"babel-messages": "^6.23.0",
1720 +
"babel-runtime": "^6.26.0",
1721 +
"babel-types": "^6.26.0",
1722 +
"detect-indent": "^4.0.0",
1723 +
"jsesc": "^1.3.0",
1724 +
"lodash": "^4.17.4",
1725 +
"source-map": "^0.5.7",
1726 +
"trim-right": "^1.0.1"
1727 +
}
1728 +
},
1729 +
"node_modules/babel-helper-bindify-decorators": {
1730 +
"version": "6.24.1",
1731 +
"resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz",
1732 +
"integrity": "sha512-TYX2QQATKA6Wssp6j7jqlw4QLmABDN1olRdEHndYvBXdaXM5dcx6j5rN0+nd+aVL+Th40fAEYvvw/Xxd/LETuQ==",
1733 +
"dev": true,
1734 +
"license": "MIT",
1735 +
"dependencies": {
1736 +
"babel-runtime": "^6.22.0",
1737 +
"babel-traverse": "^6.24.1",
1738 +
"babel-types": "^6.24.1"
1739 +
}
1740 +
},
1741 +
"node_modules/babel-helper-builder-binary-assignment-operator-visitor": {
1742 +
"version": "6.24.1",
1743 +
"resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
1744 +
"integrity": "sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==",
1745 +
"dev": true,
1746 +
"license": "MIT",
1747 +
"dependencies": {
1748 +
"babel-helper-explode-assignable-expression": "^6.24.1",
1749 +
"babel-runtime": "^6.22.0",
1750 +
"babel-types": "^6.24.1"
1751 +
}
1752 +
},
1753 +
"node_modules/babel-helper-call-delegate": {
1754 +
"version": "6.24.1",
1755 +
"resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
1756 +
"integrity": "sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==",
1757 +
"dev": true,
1758 +
"license": "MIT",
1759 +
"dependencies": {
1760 +
"babel-helper-hoist-variables": "^6.24.1",
1761 +
"babel-runtime": "^6.22.0",
1762 +
"babel-traverse": "^6.24.1",
1763 +
"babel-types": "^6.24.1"
1764 +
}
1765 +
},
1766 +
"node_modules/babel-helper-define-map": {
1767 +
"version": "6.26.0",
1768 +
"resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
1769 +
"integrity": "sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==",
1770 +
"dev": true,
1771 +
"license": "MIT",
1772 +
"dependencies": {
1773 +
"babel-helper-function-name": "^6.24.1",
1774 +
"babel-runtime": "^6.26.0",
1775 +
"babel-types": "^6.26.0",
1776 +
"lodash": "^4.17.4"
1777 +
}
1778 +
},
1779 +
"node_modules/babel-helper-explode-assignable-expression": {
1780 +
"version": "6.24.1",
1781 +
"resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
1782 +
"integrity": "sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==",
1783 +
"dev": true,
1784 +
"license": "MIT",
1785 +
"dependencies": {
1786 +
"babel-runtime": "^6.22.0",
1787 +
"babel-traverse": "^6.24.1",
1788 +
"babel-types": "^6.24.1"
1789 +
}
1790 +
},
1791 +
"node_modules/babel-helper-explode-class": {
1792 +
"version": "6.24.1",
1793 +
"resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz",
1794 +
"integrity": "sha512-SFbWewr0/0U4AiRzsHqwsbOQeLXVa9T1ELdqEa2efcQB5KopTnunAqoj07TuHlN2lfTQNPGO/rJR4FMln5fVcA==",
1795 +
"dev": true,
1796 +
"license": "MIT",
1797 +
"dependencies": {
1798 +
"babel-helper-bindify-decorators": "^6.24.1",
1799 +
"babel-runtime": "^6.22.0",
1800 +
"babel-traverse": "^6.24.1",
1801 +
"babel-types": "^6.24.1"
1802 +
}
1803 +
},
1804 +
"node_modules/babel-helper-function-name": {
1805 +
"version": "6.24.1",
1806 +
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
1807 +
"integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==",
1808 +
"dev": true,
1809 +
"license": "MIT",
1810 +
"dependencies": {
1811 +
"babel-helper-get-function-arity": "^6.24.1",
1812 +
"babel-runtime": "^6.22.0",
1813 +
"babel-template": "^6.24.1",
1814 +
"babel-traverse": "^6.24.1",
1815 +
"babel-types": "^6.24.1"
1816 +
}
1817 +
},
1818 +
"node_modules/babel-helper-get-function-arity": {
1819 +
"version": "6.24.1",
1820 +
"resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
1821 +
"integrity": "sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==",
1822 +
"dev": true,
1823 +
"license": "MIT",
1824 +
"dependencies": {
1825 +
"babel-runtime": "^6.22.0",
1826 +
"babel-types": "^6.24.1"
1827 +
}
1828 +
},
1829 +
"node_modules/babel-helper-hoist-variables": {
1830 +
"version": "6.24.1",
1831 +
"resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
1832 +
"integrity": "sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==",
1833 +
"dev": true,
1834 +
"license": "MIT",
1835 +
"dependencies": {
1836 +
"babel-runtime": "^6.22.0",
1837 +
"babel-types": "^6.24.1"
1838 +
}
1839 +
},
1840 +
"node_modules/babel-helper-optimise-call-expression": {
1841 +
"version": "6.24.1",
1842 +
"resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
1843 +
"integrity": "sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==",
1844 +
"dev": true,
1845 +
"license": "MIT",
1846 +
"dependencies": {
1847 +
"babel-runtime": "^6.22.0",
1848 +
"babel-types": "^6.24.1"
1849 +
}
1850 +
},
1851 +
"node_modules/babel-helper-regex": {
1852 +
"version": "6.26.0",
1853 +
"resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
1854 +
"integrity": "sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==",
1855 +
"dev": true,
1856 +
"license": "MIT",
1857 +
"dependencies": {
1858 +
"babel-runtime": "^6.26.0",
1859 +
"babel-types": "^6.26.0",
1860 +
"lodash": "^4.17.4"
1861 +
}
1862 +
},
1863 +
"node_modules/babel-helper-remap-async-to-generator": {
1864 +
"version": "6.24.1",
1865 +
"resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
1866 +
"integrity": "sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==",
1867 +
"dev": true,
1868 +
"license": "MIT",
1869 +
"dependencies": {
1870 +
"babel-helper-function-name": "^6.24.1",
1871 +
"babel-runtime": "^6.22.0",
1872 +
"babel-template": "^6.24.1",
1873 +
"babel-traverse": "^6.24.1",
1874 +
"babel-types": "^6.24.1"
1875 +
}
1876 +
},
1877 +
"node_modules/babel-helper-replace-supers": {
1878 +
"version": "6.24.1",
1879 +
"resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
1880 +
"integrity": "sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==",
1881 +
"dev": true,
1882 +
"license": "MIT",
1883 +
"dependencies": {
1884 +
"babel-helper-optimise-call-expression": "^6.24.1",
1885 +
"babel-messages": "^6.23.0",
1886 +
"babel-runtime": "^6.22.0",
1887 +
"babel-template": "^6.24.1",
1888 +
"babel-traverse": "^6.24.1",
1889 +
"babel-types": "^6.24.1"
1890 +
}
1891 +
},
1892 +
"node_modules/babel-helpers": {
1893 +
"version": "6.24.1",
1894 +
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
1895 +
"integrity": "sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==",
1896 +
"dev": true,
1897 +
"license": "MIT",
1898 +
"dependencies": {
1899 +
"babel-runtime": "^6.22.0",
1900 +
"babel-template": "^6.24.1"
1901 +
}
1902 +
},
1903 +
"node_modules/babel-messages": {
1904 +
"version": "6.23.0",
1905 +
"resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
1906 +
"integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==",
1907 +
"dev": true,
1908 +
"license": "MIT",
1909 +
"dependencies": {
1910 +
"babel-runtime": "^6.22.0"
1911 +
}
1912 +
},
1913 +
"node_modules/babel-plugin-check-es2015-constants": {
1914 +
"version": "6.22.0",
1915 +
"resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
1916 +
"integrity": "sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==",
1917 +
"dev": true,
1918 +
"license": "MIT",
1919 +
"dependencies": {
1920 +
"babel-runtime": "^6.22.0"
1921 +
}
1922 +
},
1923 +
"node_modules/babel-plugin-syntax-async-functions": {
1924 +
"version": "6.13.0",
1925 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
1926 +
"integrity": "sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==",
1927 +
"dev": true,
1928 +
"license": "MIT"
1929 +
},
1930 +
"node_modules/babel-plugin-syntax-async-generators": {
1931 +
"version": "6.13.0",
1932 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
1933 +
"integrity": "sha512-EbciFN5Jb9iqU9bqaLmmFLx2G8pAUsvpWJ6OzOWBNrSY9qTohXj+7YfZx6Ug1Qqh7tCb1EA7Jvn9bMC1HBiucg==",
1934 +
"dev": true,
1935 +
"license": "MIT"
1936 +
},
1937 +
"node_modules/babel-plugin-syntax-class-constructor-call": {
1938 +
"version": "6.18.0",
1939 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
1940 +
"integrity": "sha512-EEuBcXz/wZ81Jaac0LnMHtD4Mfz9XWn2oH2Xj+CHwz2SZWUqqdtR2BgWPSdTGMmxN/5KLSh4PImt9+9ZedDarA==",
1941 +
"dev": true,
1942 +
"license": "MIT"
1943 +
},
1944 +
"node_modules/babel-plugin-syntax-class-properties": {
1945 +
"version": "6.13.0",
1946 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
1947 +
"integrity": "sha512-chI3Rt9T1AbrQD1s+vxw3KcwC9yHtF621/MacuItITfZX344uhQoANjpoSJZleAmW2tjlolqB/f+h7jIqXa7pA==",
1948 +
"dev": true,
1949 +
"license": "MIT"
1950 +
},
1951 +
"node_modules/babel-plugin-syntax-decorators": {
1952 +
"version": "6.13.0",
1953 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
1954 +
"integrity": "sha512-AWj19x2aDm8qFQ5O2JcD6pwJDW1YdcnO+1b81t7gxrGjz5VHiUqeYWAR4h7zueWMalRelrQDXprv2FrY1dbpbw==",
1955 +
"dev": true,
1956 +
"license": "MIT"
1957 +
},
1958 +
"node_modules/babel-plugin-syntax-do-expressions": {
1959 +
"version": "6.13.0",
1960 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
1961 +
"integrity": "sha512-HD/5qJB9oSXzl0caxM+aRD7ENICXqcc3Up/8toDQk7zNIDE7TzsqtxC5f4t9Rwhu2Ya8l9l4j6b3vOsy+a6qxg==",
1962 +
"dev": true,
1963 +
"license": "MIT"
1964 +
},
1965 +
"node_modules/babel-plugin-syntax-dynamic-import": {
1966 +
"version": "6.18.0",
1967 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
1968 +
"integrity": "sha512-MioUE+LfjCEz65Wf7Z/Rm4XCP5k2c+TbMd2Z2JKc7U9uwjBhAfNPE48KC4GTGKhppMeYVepwDBNO/nGY6NYHBA==",
1969 +
"dev": true,
1970 +
"license": "MIT"
1971 +
},
1972 +
"node_modules/babel-plugin-syntax-exponentiation-operator": {
1973 +
"version": "6.13.0",
1974 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
1975 +
"integrity": "sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==",
1976 +
"dev": true,
1977 +
"license": "MIT"
1978 +
},
1979 +
"node_modules/babel-plugin-syntax-export-extensions": {
1980 +
"version": "6.13.0",
1981 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
1982 +
"integrity": "sha512-Eo0rcRaIDMld/W6mVhePiudIuLW+Cr/8eveW3mBREfZORScZgx4rh6BAPyvzdEc/JZvQ+LkC80t0VGFs6FX+lg==",
1983 +
"dev": true,
1984 +
"license": "MIT"
1985 +
},
1986 +
"node_modules/babel-plugin-syntax-function-bind": {
1987 +
"version": "6.13.0",
1988 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
1989 +
"integrity": "sha512-m8yMoh9LIiNyeLdQs5I9G+3YXo4nqVsKQkk7YplrG4qAFbNi9hkZlow8HDHxhH9QOVFPHmy8+03NzRCdyChIKw==",
1990 +
"dev": true,
1991 +
"license": "MIT"
1992 +
},
1993 +
"node_modules/babel-plugin-syntax-object-rest-spread": {
1994 +
"version": "6.13.0",
1995 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
1996 +
"integrity": "sha512-C4Aq+GaAj83pRQ0EFgTvw5YO6T3Qz2KGrNRwIj9mSoNHVvdZY4KO2uA6HNtNXCw993iSZnckY1aLW8nOi8i4+w==",
1997 +
"dev": true,
1998 +
"license": "MIT"
1999 +
},
2000 +
"node_modules/babel-plugin-syntax-trailing-function-commas": {
2001 +
"version": "6.22.0",
2002 +
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
2003 +
"integrity": "sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==",
2004 +
"dev": true,
2005 +
"license": "MIT"
2006 +
},
2007 +
"node_modules/babel-plugin-transform-async-generator-functions": {
2008 +
"version": "6.24.1",
2009 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz",
2010 +
"integrity": "sha512-uT7eovUxtXe8Q2ufcjRuJIOL0hg6VAUJhiWJBLxH/evYAw+aqoJLcYTR8hqx13iOx/FfbCMHgBmXWZjukbkyPg==",
2011 +
"dev": true,
2012 +
"license": "MIT",
2013 +
"dependencies": {
2014 +
"babel-helper-remap-async-to-generator": "^6.24.1",
2015 +
"babel-plugin-syntax-async-generators": "^6.5.0",
2016 +
"babel-runtime": "^6.22.0"
2017 +
}
2018 +
},
2019 +
"node_modules/babel-plugin-transform-async-to-generator": {
2020 +
"version": "6.24.1",
2021 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
2022 +
"integrity": "sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==",
2023 +
"dev": true,
2024 +
"license": "MIT",
2025 +
"dependencies": {
2026 +
"babel-helper-remap-async-to-generator": "^6.24.1",
2027 +
"babel-plugin-syntax-async-functions": "^6.8.0",
2028 +
"babel-runtime": "^6.22.0"
2029 +
}
2030 +
},
2031 +
"node_modules/babel-plugin-transform-class-constructor-call": {
2032 +
"version": "6.24.1",
2033 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz",
2034 +
"integrity": "sha512-RvYukT1Nh7njz8P8326ztpQUGCKwmjgu6aRIx1lkvylWITYcskg29vy1Kp8WXIq7FvhXsz0Crf2kS94bjB690A==",
2035 +
"dev": true,
2036 +
"license": "MIT",
2037 +
"dependencies": {
2038 +
"babel-plugin-syntax-class-constructor-call": "^6.18.0",
2039 +
"babel-runtime": "^6.22.0",
2040 +
"babel-template": "^6.24.1"
2041 +
}
2042 +
},
2043 +
"node_modules/babel-plugin-transform-class-properties": {
2044 +
"version": "6.24.1",
2045 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
2046 +
"integrity": "sha512-n4jtBA3OYBdvG5PRMKsMXJXHfLYw/ZOmtxCLOOwz6Ro5XlrColkStLnz1AS1L2yfPA9BKJ1ZNlmVCLjAL9DSIg==",
2047 +
"dev": true,
2048 +
"license": "MIT",
2049 +
"dependencies": {
2050 +
"babel-helper-function-name": "^6.24.1",
2051 +
"babel-plugin-syntax-class-properties": "^6.8.0",
2052 +
"babel-runtime": "^6.22.0",
2053 +
"babel-template": "^6.24.1"
2054 +
}
2055 +
},
2056 +
"node_modules/babel-plugin-transform-decorators": {
2057 +
"version": "6.24.1",
2058 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz",
2059 +
"integrity": "sha512-skQ2CImwDkCHu0mkWvCOlBCpBIHW4/49IZWVwV4A/EnWjL9bB6UBvLyMNe3Td5XDStSZNhe69j4bfEW8dvUbew==",
2060 +
"dev": true,
2061 +
"license": "MIT",
2062 +
"dependencies": {
2063 +
"babel-helper-explode-class": "^6.24.1",
2064 +
"babel-plugin-syntax-decorators": "^6.13.0",
2065 +
"babel-runtime": "^6.22.0",
2066 +
"babel-template": "^6.24.1",
2067 +
"babel-types": "^6.24.1"
2068 +
}
2069 +
},
2070 +
"node_modules/babel-plugin-transform-do-expressions": {
2071 +
"version": "6.22.0",
2072 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz",
2073 +
"integrity": "sha512-yQwYqYg+Tnj1InA8W1rsItsZVhkv1Euc4KVua9ledtPz5PDWYz7LVyy6rDBpVYUWFZj5k6GUm3YZpCbIm8Tqew==",
2074 +
"dev": true,
2075 +
"license": "MIT",
2076 +
"dependencies": {
2077 +
"babel-plugin-syntax-do-expressions": "^6.8.0",
2078 +
"babel-runtime": "^6.22.0"
2079 +
}
2080 +
},
2081 +
"node_modules/babel-plugin-transform-es2015-arrow-functions": {
2082 +
"version": "6.22.0",
2083 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
2084 +
"integrity": "sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==",
2085 +
"dev": true,
2086 +
"license": "MIT",
2087 +
"dependencies": {
2088 +
"babel-runtime": "^6.22.0"
2089 +
}
2090 +
},
2091 +
"node_modules/babel-plugin-transform-es2015-block-scoped-functions": {
2092 +
"version": "6.22.0",
2093 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
2094 +
"integrity": "sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==",
2095 +
"dev": true,
2096 +
"license": "MIT",
2097 +
"dependencies": {
2098 +
"babel-runtime": "^6.22.0"
2099 +
}
2100 +
},
2101 +
"node_modules/babel-plugin-transform-es2015-block-scoping": {
2102 +
"version": "6.26.0",
2103 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
2104 +
"integrity": "sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==",
2105 +
"dev": true,
2106 +
"license": "MIT",
2107 +
"dependencies": {
2108 +
"babel-runtime": "^6.26.0",
2109 +
"babel-template": "^6.26.0",
2110 +
"babel-traverse": "^6.26.0",
2111 +
"babel-types": "^6.26.0",
2112 +
"lodash": "^4.17.4"
2113 +
}
2114 +
},
2115 +
"node_modules/babel-plugin-transform-es2015-classes": {
2116 +
"version": "6.24.1",
2117 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
2118 +
"integrity": "sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==",
2119 +
"dev": true,
2120 +
"license": "MIT",
2121 +
"dependencies": {
2122 +
"babel-helper-define-map": "^6.24.1",
2123 +
"babel-helper-function-name": "^6.24.1",
2124 +
"babel-helper-optimise-call-expression": "^6.24.1",
2125 +
"babel-helper-replace-supers": "^6.24.1",
2126 +
"babel-messages": "^6.23.0",
2127 +
"babel-runtime": "^6.22.0",
2128 +
"babel-template": "^6.24.1",
2129 +
"babel-traverse": "^6.24.1",
2130 +
"babel-types": "^6.24.1"
2131 +
}
2132 +
},
2133 +
"node_modules/babel-plugin-transform-es2015-computed-properties": {
2134 +
"version": "6.24.1",
2135 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
2136 +
"integrity": "sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==",
2137 +
"dev": true,
2138 +
"license": "MIT",
2139 +
"dependencies": {
2140 +
"babel-runtime": "^6.22.0",
2141 +
"babel-template": "^6.24.1"
2142 +
}
2143 +
},
2144 +
"node_modules/babel-plugin-transform-es2015-destructuring": {
2145 +
"version": "6.23.0",
2146 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
2147 +
"integrity": "sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==",
2148 +
"dev": true,
2149 +
"license": "MIT",
2150 +
"dependencies": {
2151 +
"babel-runtime": "^6.22.0"
2152 +
}
2153 +
},
2154 +
"node_modules/babel-plugin-transform-es2015-duplicate-keys": {
2155 +
"version": "6.24.1",
2156 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
2157 +
"integrity": "sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==",
2158 +
"dev": true,
2159 +
"license": "MIT",
2160 +
"dependencies": {
2161 +
"babel-runtime": "^6.22.0",
2162 +
"babel-types": "^6.24.1"
2163 +
}
2164 +
},
2165 +
"node_modules/babel-plugin-transform-es2015-for-of": {
2166 +
"version": "6.23.0",
2167 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
2168 +
"integrity": "sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==",
2169 +
"dev": true,
2170 +
"license": "MIT",
2171 +
"dependencies": {
2172 +
"babel-runtime": "^6.22.0"
2173 +
}
2174 +
},
2175 +
"node_modules/babel-plugin-transform-es2015-function-name": {
2176 +
"version": "6.24.1",
2177 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
2178 +
"integrity": "sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==",
2179 +
"dev": true,
2180 +
"license": "MIT",
2181 +
"dependencies": {
2182 +
"babel-helper-function-name": "^6.24.1",
2183 +
"babel-runtime": "^6.22.0",
2184 +
"babel-types": "^6.24.1"
2185 +
}
2186 +
},
2187 +
"node_modules/babel-plugin-transform-es2015-literals": {
2188 +
"version": "6.22.0",
2189 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
2190 +
"integrity": "sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==",
2191 +
"dev": true,
2192 +
"license": "MIT",
2193 +
"dependencies": {
2194 +
"babel-runtime": "^6.22.0"
2195 +
}
2196 +
},
2197 +
"node_modules/babel-plugin-transform-es2015-modules-amd": {
2198 +
"version": "6.24.1",
2199 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
2200 +
"integrity": "sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==",
2201 +
"dev": true,
2202 +
"license": "MIT",
2203 +
"dependencies": {
2204 +
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
2205 +
"babel-runtime": "^6.22.0",
2206 +
"babel-template": "^6.24.1"
2207 +
}
2208 +
},
2209 +
"node_modules/babel-plugin-transform-es2015-modules-commonjs": {
2210 +
"version": "6.26.2",
2211 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
2212 +
"integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==",
2213 +
"dev": true,
2214 +
"license": "MIT",
2215 +
"dependencies": {
2216 +
"babel-plugin-transform-strict-mode": "^6.24.1",
2217 +
"babel-runtime": "^6.26.0",
2218 +
"babel-template": "^6.26.0",
2219 +
"babel-types": "^6.26.0"
2220 +
}
2221 +
},
2222 +
"node_modules/babel-plugin-transform-es2015-modules-systemjs": {
2223 +
"version": "6.24.1",
2224 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
2225 +
"integrity": "sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==",
2226 +
"dev": true,
2227 +
"license": "MIT",
2228 +
"dependencies": {
2229 +
"babel-helper-hoist-variables": "^6.24.1",
2230 +
"babel-runtime": "^6.22.0",
2231 +
"babel-template": "^6.24.1"
2232 +
}
2233 +
},
2234 +
"node_modules/babel-plugin-transform-es2015-modules-umd": {
2235 +
"version": "6.24.1",
2236 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
2237 +
"integrity": "sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==",
2238 +
"dev": true,
2239 +
"license": "MIT",
2240 +
"dependencies": {
2241 +
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
2242 +
"babel-runtime": "^6.22.0",
2243 +
"babel-template": "^6.24.1"
2244 +
}
2245 +
},
2246 +
"node_modules/babel-plugin-transform-es2015-object-super": {
2247 +
"version": "6.24.1",
2248 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
2249 +
"integrity": "sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==",
2250 +
"dev": true,
2251 +
"license": "MIT",
2252 +
"dependencies": {
2253 +
"babel-helper-replace-supers": "^6.24.1",
2254 +
"babel-runtime": "^6.22.0"
2255 +
}
2256 +
},
2257 +
"node_modules/babel-plugin-transform-es2015-parameters": {
2258 +
"version": "6.24.1",
2259 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
2260 +
"integrity": "sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==",
2261 +
"dev": true,
2262 +
"license": "MIT",
2263 +
"dependencies": {
2264 +
"babel-helper-call-delegate": "^6.24.1",
2265 +
"babel-helper-get-function-arity": "^6.24.1",
2266 +
"babel-runtime": "^6.22.0",
2267 +
"babel-template": "^6.24.1",
2268 +
"babel-traverse": "^6.24.1",
2269 +
"babel-types": "^6.24.1"
2270 +
}
2271 +
},
2272 +
"node_modules/babel-plugin-transform-es2015-shorthand-properties": {
2273 +
"version": "6.24.1",
2274 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
2275 +
"integrity": "sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==",
2276 +
"dev": true,
2277 +
"license": "MIT",
2278 +
"dependencies": {
2279 +
"babel-runtime": "^6.22.0",
2280 +
"babel-types": "^6.24.1"
2281 +
}
2282 +
},
2283 +
"node_modules/babel-plugin-transform-es2015-spread": {
2284 +
"version": "6.22.0",
2285 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
2286 +
"integrity": "sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==",
2287 +
"dev": true,
2288 +
"license": "MIT",
2289 +
"dependencies": {
2290 +
"babel-runtime": "^6.22.0"
2291 +
}
2292 +
},
2293 +
"node_modules/babel-plugin-transform-es2015-sticky-regex": {
2294 +
"version": "6.24.1",
2295 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
2296 +
"integrity": "sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==",
2297 +
"dev": true,
2298 +
"license": "MIT",
2299 +
"dependencies": {
2300 +
"babel-helper-regex": "^6.24.1",
2301 +
"babel-runtime": "^6.22.0",
2302 +
"babel-types": "^6.24.1"
2303 +
}
2304 +
},
2305 +
"node_modules/babel-plugin-transform-es2015-template-literals": {
2306 +
"version": "6.22.0",
2307 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
2308 +
"integrity": "sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==",
2309 +
"dev": true,
2310 +
"license": "MIT",
2311 +
"dependencies": {
2312 +
"babel-runtime": "^6.22.0"
2313 +
}
2314 +
},
2315 +
"node_modules/babel-plugin-transform-es2015-typeof-symbol": {
2316 +
"version": "6.23.0",
2317 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
2318 +
"integrity": "sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==",
2319 +
"dev": true,
2320 +
"license": "MIT",
2321 +
"dependencies": {
2322 +
"babel-runtime": "^6.22.0"
2323 +
}
2324 +
},
2325 +
"node_modules/babel-plugin-transform-es2015-unicode-regex": {
2326 +
"version": "6.24.1",
2327 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
2328 +
"integrity": "sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==",
2329 +
"dev": true,
2330 +
"license": "MIT",
2331 +
"dependencies": {
2332 +
"babel-helper-regex": "^6.24.1",
2333 +
"babel-runtime": "^6.22.0",
2334 +
"regexpu-core": "^2.0.0"
2335 +
}
2336 +
},
2337 +
"node_modules/babel-plugin-transform-exponentiation-operator": {
2338 +
"version": "6.24.1",
2339 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
2340 +
"integrity": "sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==",
2341 +
"dev": true,
2342 +
"license": "MIT",
2343 +
"dependencies": {
2344 +
"babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1",
2345 +
"babel-plugin-syntax-exponentiation-operator": "^6.8.0",
2346 +
"babel-runtime": "^6.22.0"
2347 +
}
2348 +
},
2349 +
"node_modules/babel-plugin-transform-export-extensions": {
2350 +
"version": "6.22.0",
2351 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz",
2352 +
"integrity": "sha512-mtzELzINaYqdVglyZrDDVwkcFRuE7s6QUFWXxwffKAHB/NkfbJ2NJSytugB43ytIC8UVt30Ereyx+7gNyTkDLg==",
2353 +
"dev": true,
2354 +
"license": "MIT",
2355 +
"dependencies": {
2356 +
"babel-plugin-syntax-export-extensions": "^6.8.0",
2357 +
"babel-runtime": "^6.22.0"
2358 +
}
2359 +
},
2360 +
"node_modules/babel-plugin-transform-function-bind": {
2361 +
"version": "6.22.0",
2362 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz",
2363 +
"integrity": "sha512-9Ec4KYf1GurT39mlUjDSlN7HWSlB3u3mWRMogQbb+Y88lO0ZM3rJ0ADhPnQwWK9TbO6e/4E+Et1rrfGY9mFimA==",
2364 +
"dev": true,
2365 +
"license": "MIT",
2366 +
"dependencies": {
2367 +
"babel-plugin-syntax-function-bind": "^6.8.0",
2368 +
"babel-runtime": "^6.22.0"
2369 +
}
2370 +
},
2371 +
"node_modules/babel-plugin-transform-object-rest-spread": {
2372 +
"version": "6.26.0",
2373 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
2374 +
"integrity": "sha512-ocgA9VJvyxwt+qJB0ncxV8kb/CjfTcECUY4tQ5VT7nP6Aohzobm8CDFaQ5FHdvZQzLmf0sgDxB8iRXZXxwZcyA==",
2375 +
"dev": true,
2376 +
"license": "MIT",
2377 +
"dependencies": {
2378 +
"babel-plugin-syntax-object-rest-spread": "^6.8.0",
2379 +
"babel-runtime": "^6.26.0"
2380 +
}
2381 +
},
2382 +
"node_modules/babel-plugin-transform-regenerator": {
2383 +
"version": "6.26.0",
2384 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
2385 +
"integrity": "sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==",
2386 +
"dev": true,
2387 +
"license": "MIT",
2388 +
"dependencies": {
2389 +
"regenerator-transform": "^0.10.0"
2390 +
}
2391 +
},
2392 +
"node_modules/babel-plugin-transform-strict-mode": {
2393 +
"version": "6.24.1",
2394 +
"resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
2395 +
"integrity": "sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==",
2396 +
"dev": true,
2397 +
"license": "MIT",
2398 +
"dependencies": {
2399 +
"babel-runtime": "^6.22.0",
2400 +
"babel-types": "^6.24.1"
2401 +
}
2402 +
},
2403 +
"node_modules/babel-preset-es2015": {
2404 +
"version": "6.24.1",
2405 +
"resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
2406 +
"integrity": "sha512-XfwUqG1Ry6R43m4Wfob+vHbIVBIqTg/TJY4Snku1iIzeH7mUnwHA8Vagmv+ZQbPwhS8HgsdQvy28Py3k5zpoFQ==",
2407 +
"deprecated": "🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read https://babeljs.io/env to update!",
2408 +
"dev": true,
2409 +
"license": "MIT",
2410 +
"dependencies": {
2411 +
"babel-plugin-check-es2015-constants": "^6.22.0",
2412 +
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
2413 +
"babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
2414 +
"babel-plugin-transform-es2015-block-scoping": "^6.24.1",
2415 +
"babel-plugin-transform-es2015-classes": "^6.24.1",
2416 +
"babel-plugin-transform-es2015-computed-properties": "^6.24.1",
2417 +
"babel-plugin-transform-es2015-destructuring": "^6.22.0",
2418 +
"babel-plugin-transform-es2015-duplicate-keys": "^6.24.1",
2419 +
"babel-plugin-transform-es2015-for-of": "^6.22.0",
2420 +
"babel-plugin-transform-es2015-function-name": "^6.24.1",
2421 +
"babel-plugin-transform-es2015-literals": "^6.22.0",
2422 +
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
2423 +
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
2424 +
"babel-plugin-transform-es2015-modules-systemjs": "^6.24.1",
2425 +
"babel-plugin-transform-es2015-modules-umd": "^6.24.1",
2426 +
"babel-plugin-transform-es2015-object-super": "^6.24.1",
2427 +
"babel-plugin-transform-es2015-parameters": "^6.24.1",
2428 +
"babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
2429 +
"babel-plugin-transform-es2015-spread": "^6.22.0",
2430 +
"babel-plugin-transform-es2015-sticky-regex": "^6.24.1",
2431 +
"babel-plugin-transform-es2015-template-literals": "^6.22.0",
2432 +
"babel-plugin-transform-es2015-typeof-symbol": "^6.22.0",
2433 +
"babel-plugin-transform-es2015-unicode-regex": "^6.24.1",
2434 +
"babel-plugin-transform-regenerator": "^6.24.1"
2435 +
}
2436 +
},
2437 +
"node_modules/babel-preset-stage-0": {
2438 +
"version": "6.24.1",
2439 +
"resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz",
2440 +
"integrity": "sha512-MJD+xBbpsApbKlzAX0sOBF+VeFaUmv5s8FSOO7SSZpes1QgphCjq/UIGRFWSmQ/0i5bqQjLGCTXGGXqcLQ9JDA==",
2441 +
"dev": true,
2442 +
"license": "MIT",
2443 +
"dependencies": {
2444 +
"babel-plugin-transform-do-expressions": "^6.22.0",
2445 +
"babel-plugin-transform-function-bind": "^6.22.0",
2446 +
"babel-preset-stage-1": "^6.24.1"
2447 +
}
2448 +
},
2449 +
"node_modules/babel-preset-stage-1": {
2450 +
"version": "6.24.1",
2451 +
"resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz",
2452 +
"integrity": "sha512-rn+UOcd7BHDniq1SVxv2/AVVSVI1NK+hfS0I/iR6m6KbOi/aeBRcqBilqO73pd9VUpRXF2HFtlDuC9F2BEQqmg==",
2453 +
"dev": true,
2454 +
"license": "MIT",
2455 +
"dependencies": {
2456 +
"babel-plugin-transform-class-constructor-call": "^6.24.1",
2457 +
"babel-plugin-transform-export-extensions": "^6.22.0",
2458 +
"babel-preset-stage-2": "^6.24.1"
2459 +
}
2460 +
},
2461 +
"node_modules/babel-preset-stage-2": {
2462 +
"version": "6.24.1",
2463 +
"resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz",
2464 +
"integrity": "sha512-9F+nquz+37PrlTSBdpeQBKnQfAMNBnryXw+m4qBh35FNbJPfzZz+sjN2G5Uf1CRedU9PH7fJkTbYijxmkLX8Og==",
2465 +
"dev": true,
2466 +
"license": "MIT",
2467 +
"dependencies": {
2468 +
"babel-plugin-syntax-dynamic-import": "^6.18.0",
2469 +
"babel-plugin-transform-class-properties": "^6.24.1",
2470 +
"babel-plugin-transform-decorators": "^6.24.1",
2471 +
"babel-preset-stage-3": "^6.24.1"
2472 +
}
2473 +
},
2474 +
"node_modules/babel-preset-stage-3": {
2475 +
"version": "6.24.1",
2476 +
"resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz",
2477 +
"integrity": "sha512-eCbEOF8uN0KypFXJmZXn2sTk7bPV9uM5xov7G/7BM08TbQEObsVs0cEWfy6NQySlfk7JBi/t+XJP1JkruYfthA==",
2478 +
"dev": true,
2479 +
"license": "MIT",
2480 +
"dependencies": {
2481 +
"babel-plugin-syntax-trailing-function-commas": "^6.22.0",
2482 +
"babel-plugin-transform-async-generator-functions": "^6.24.1",
2483 +
"babel-plugin-transform-async-to-generator": "^6.24.1",
2484 +
"babel-plugin-transform-exponentiation-operator": "^6.24.1",
2485 +
"babel-plugin-transform-object-rest-spread": "^6.22.0"
2486 +
}
2487 +
},
2488 +
"node_modules/babel-register": {
2489 +
"version": "6.26.0",
2490 +
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
2491 +
"integrity": "sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==",
2492 +
"dev": true,
2493 +
"license": "MIT",
2494 +
"dependencies": {
2495 +
"babel-core": "^6.26.0",
2496 +
"babel-runtime": "^6.26.0",
2497 +
"core-js": "^2.5.0",
2498 +
"home-or-tmp": "^2.0.0",
2499 +
"lodash": "^4.17.4",
2500 +
"mkdirp": "^0.5.1",
2501 +
"source-map-support": "^0.4.15"
2502 +
}
2503 +
},
2504 +
"node_modules/babel-runtime": {
2505 +
"version": "6.26.0",
2506 +
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
2507 +
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
2508 +
"dev": true,
2509 +
"license": "MIT",
2510 +
"dependencies": {
2511 +
"core-js": "^2.4.0",
2512 +
"regenerator-runtime": "^0.11.0"
2513 +
}
2514 +
},
2515 +
"node_modules/babel-template": {
2516 +
"version": "6.26.0",
2517 +
"resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
2518 +
"integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==",
2519 +
"dev": true,
2520 +
"license": "MIT",
2521 +
"dependencies": {
2522 +
"babel-runtime": "^6.26.0",
2523 +
"babel-traverse": "^6.26.0",
2524 +
"babel-types": "^6.26.0",
2525 +
"babylon": "^6.18.0",
2526 +
"lodash": "^4.17.4"
2527 +
}
2528 +
},
2529 +
"node_modules/babel-traverse": {
2530 +
"version": "6.26.0",
2531 +
"resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
2532 +
"integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==",
2533 +
"dev": true,
2534 +
"license": "MIT",
2535 +
"dependencies": {
2536 +
"babel-code-frame": "^6.26.0",
2537 +
"babel-messages": "^6.23.0",
2538 +
"babel-runtime": "^6.26.0",
2539 +
"babel-types": "^6.26.0",
2540 +
"babylon": "^6.18.0",
2541 +
"debug": "^2.6.8",
2542 +
"globals": "^9.18.0",
2543 +
"invariant": "^2.2.2",
2544 +
"lodash": "^4.17.4"
2545 +
}
2546 +
},
2547 +
"node_modules/babel-traverse/node_modules/debug": {
2548 +
"version": "2.6.9",
2549 +
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
2550 +
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
2551 +
"dev": true,
2552 +
"license": "MIT",
2553 +
"dependencies": {
2554 +
"ms": "2.0.0"
2555 +
}
2556 +
},
2557 +
"node_modules/babel-traverse/node_modules/ms": {
2558 +
"version": "2.0.0",
2559 +
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
2560 +
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
2561 +
"dev": true,
2562 +
"license": "MIT"
2563 +
},
2564 +
"node_modules/babel-types": {
2565 +
"version": "6.26.0",
2566 +
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
2567 +
"integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==",
2568 +
"dev": true,
2569 +
"license": "MIT",
2570 +
"dependencies": {
2571 +
"babel-runtime": "^6.26.0",
2572 +
"esutils": "^2.0.2",
2573 +
"lodash": "^4.17.4",
2574 +
"to-fast-properties": "^1.0.3"
2575 +
}
2576 +
},
2577 +
"node_modules/babylon": {
2578 +
"version": "6.18.0",
2579 +
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
2580 +
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
2581 +
"dev": true,
2582 +
"license": "MIT",
2583 +
"bin": {
2584 +
"babylon": "bin/babylon.js"
2585 +
}
2586 +
},
1549 2587
"node_modules/balanced-match": {
1550 2588
"version": "1.0.2",
1551 2589
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1552 2590
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
1553 2591
"dev": true,
2106 3144
"license": "MIT",
2107 3145
"funding": {
2108 3146
"url": "https://github.com/sponsors/sindresorhus"
2109 3147
}
2110 3148
},
3149 +
"node_modules/concat-map": {
3150 +
"version": "0.0.1",
3151 +
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
3152 +
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
3153 +
"dev": true,
3154 +
"license": "MIT"
3155 +
},
2111 3156
"node_modules/concordance": {
2112 3157
"version": "5.0.4",
2113 3158
"resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz",
2114 3159
"integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==",
2115 3160
"dev": true,
2165 3210
"license": "MIT",
2166 3211
"engines": {
2167 3212
"node": ">= 0.6"
2168 3213
}
2169 3214
},
3215 +
"node_modules/convert-source-map": {
3216 +
"version": "1.9.0",
3217 +
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
3218 +
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
3219 +
"dev": true,
3220 +
"license": "MIT"
3221 +
},
2170 3222
"node_modules/convert-to-spaces": {
2171 3223
"version": "2.0.1",
2172 3224
"resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz",
2173 3225
"integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==",
2174 3226
"dev": true,
2200 3252
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
2201 3253
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
2202 3254
"dev": true,
2203 3255
"license": "MIT"
2204 3256
},
3257 +
"node_modules/core-js": {
3258 +
"version": "2.6.12",
3259 +
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
3260 +
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
3261 +
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
3262 +
"dev": true,
3263 +
"hasInstallScript": true,
3264 +
"license": "MIT"
3265 +
},
2205 3266
"node_modules/cors": {
2206 3267
"version": "2.8.6",
2207 3268
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
2208 3269
"integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
2209 3270
"license": "MIT",
2239 3300
},
2240 3301
"engines": {
2241 3302
"node": ">= 8"
2242 3303
}
2243 3304
},
3305 +
"node_modules/cross-var": {
3306 +
"version": "1.1.0",
3307 +
"resolved": "https://registry.npmjs.org/cross-var/-/cross-var-1.1.0.tgz",
3308 +
"integrity": "sha512-wIcFax9RNm5ayuORUeJ5MLxPbfh8XdZhhUpKutIszU46Fs9UIhEdPJ7+YguM+7FxEj+68hSQVyathVsIu84SiA==",
3309 +
"dev": true,
3310 +
"license": "MIT",
3311 +
"dependencies": {
3312 +
"babel-preset-es2015": "^6.18.0",
3313 +
"babel-preset-stage-0": "^6.16.0",
3314 +
"babel-register": "^6.18.0",
3315 +
"cross-spawn": "^5.0.1",
3316 +
"exit": "^0.1.2"
3317 +
},
3318 +
"bin": {
3319 +
"cross-var": "index.js"
3320 +
}
3321 +
},
3322 +
"node_modules/cross-var/node_modules/cross-spawn": {
3323 +
"version": "5.1.0",
3324 +
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
3325 +
"integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
3326 +
"dev": true,
3327 +
"license": "MIT",
3328 +
"dependencies": {
3329 +
"lru-cache": "^4.0.1",
3330 +
"shebang-command": "^1.2.0",
3331 +
"which": "^1.2.9"
3332 +
}
3333 +
},
3334 +
"node_modules/cross-var/node_modules/lru-cache": {
3335 +
"version": "4.1.5",
3336 +
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
3337 +
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
3338 +
"dev": true,
3339 +
"license": "ISC",
3340 +
"dependencies": {
3341 +
"pseudomap": "^1.0.2",
3342 +
"yallist": "^2.1.2"
3343 +
}
3344 +
},
3345 +
"node_modules/cross-var/node_modules/shebang-command": {
3346 +
"version": "1.2.0",
3347 +
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
3348 +
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
3349 +
"dev": true,
3350 +
"license": "MIT",
3351 +
"dependencies": {
3352 +
"shebang-regex": "^1.0.0"
3353 +
},
3354 +
"engines": {
3355 +
"node": ">=0.10.0"
3356 +
}
3357 +
},
3358 +
"node_modules/cross-var/node_modules/shebang-regex": {
3359 +
"version": "1.0.0",
3360 +
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
3361 +
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
3362 +
"dev": true,
3363 +
"license": "MIT",
3364 +
"engines": {
3365 +
"node": ">=0.10.0"
3366 +
}
3367 +
},
3368 +
"node_modules/cross-var/node_modules/which": {
3369 +
"version": "1.3.1",
3370 +
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
3371 +
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
3372 +
"dev": true,
3373 +
"license": "ISC",
3374 +
"dependencies": {
3375 +
"isexe": "^2.0.0"
3376 +
},
3377 +
"bin": {
3378 +
"which": "bin/which"
3379 +
}
3380 +
},
3381 +
"node_modules/cross-var/node_modules/yallist": {
3382 +
"version": "2.1.2",
3383 +
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
3384 +
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
3385 +
"dev": true,
3386 +
"license": "ISC"
3387 +
},
2244 3388
"node_modules/csstype": {
2245 3389
"version": "3.2.3",
2246 3390
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
2247 3391
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
2248 3392
"devOptional": true,
2377 3521
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
2378 3522
"integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
2379 3523
"devOptional": true,
2380 3524
"license": "MIT"
2381 3525
},
3526 +
"node_modules/detect-indent": {
3527 +
"version": "4.0.0",
3528 +
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
3529 +
"integrity": "sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==",
3530 +
"dev": true,
3531 +
"license": "MIT",
3532 +
"dependencies": {
3533 +
"repeating": "^2.0.0"
3534 +
},
3535 +
"engines": {
3536 +
"node": ">=0.10.0"
3537 +
}
3538 +
},
2382 3539
"node_modules/detect-libc": {
2383 3540
"version": "2.1.2",
2384 3541
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
2385 3542
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
2386 3543
"license": "Apache-2.0",
2443 3600
},
2444 3601
"funding": {
2445 3602
"url": "https://dotenvx.com"
2446 3603
}
2447 3604
},
3605 +
"node_modules/dotenv-cli": {
3606 +
"version": "11.0.0",
3607 +
"resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-11.0.0.tgz",
3608 +
"integrity": "sha512-r5pA8idbk7GFWuHEU7trSTflWcdBpQEK+Aw17UrSHjS6CReuhrrPcyC3zcQBPQvhArRHnBo/h6eLH1fkCvNlww==",
3609 +
"dev": true,
3610 +
"license": "MIT",
3611 +
"dependencies": {
3612 +
"cross-spawn": "^7.0.6",
3613 +
"dotenv": "^17.1.0",
3614 +
"dotenv-expand": "^12.0.0",
3615 +
"minimist": "^1.2.6"
3616 +
},
3617 +
"bin": {
3618 +
"dotenv": "cli.js"
3619 +
}
3620 +
},
3621 +
"node_modules/dotenv-cli/node_modules/dotenv": {
3622 +
"version": "17.4.1",
3623 +
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz",
3624 +
"integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==",
3625 +
"dev": true,
3626 +
"license": "BSD-2-Clause",
3627 +
"engines": {
3628 +
"node": ">=12"
3629 +
},
3630 +
"funding": {
3631 +
"url": "https://dotenvx.com"
3632 +
}
3633 +
},
3634 +
"node_modules/dotenv-expand": {
3635 +
"version": "12.0.3",
3636 +
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-12.0.3.tgz",
3637 +
"integrity": "sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA==",
3638 +
"dev": true,
3639 +
"license": "BSD-2-Clause",
3640 +
"dependencies": {
3641 +
"dotenv": "^16.4.5"
3642 +
},
3643 +
"engines": {
3644 +
"node": ">=12"
3645 +
},
3646 +
"funding": {
3647 +
"url": "https://dotenvx.com"
3648 +
}
3649 +
},
2448 3650
"node_modules/dunder-proto": {
2449 3651
"version": "1.0.1",
2450 3652
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
2451 3653
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
2452 3654
"license": "MIT",
2733 3935
"engines": {
2734 3936
"node": ">=18"
2735 3937
},
2736 3938
"funding": {
2737 3939
"url": "https://github.com/sponsors/sindresorhus"
3940 +
}
3941 +
},
3942 +
"node_modules/exit": {
3943 +
"version": "0.1.2",
3944 +
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
3945 +
"integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
3946 +
"dev": true,
3947 +
"engines": {
3948 +
"node": ">= 0.8.0"
2738 3949
}
2739 3950
},
2740 3951
"node_modules/expand-template": {
2741 3952
"version": "2.0.3",
2742 3953
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
3215 4426
},
3216 4427
"engines": {
3217 4428
"node": ">= 6"
3218 4429
}
3219 4430
},
4431 +
"node_modules/globals": {
4432 +
"version": "9.18.0",
4433 +
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
4434 +
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
4435 +
"dev": true,
4436 +
"license": "MIT",
4437 +
"engines": {
4438 +
"node": ">=0.10.0"
4439 +
}
4440 +
},
3220 4441
"node_modules/globby": {
3221 4442
"version": "14.1.0",
3222 4443
"resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz",
3223 4444
"integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==",
3224 4445
"dev": true,
3269 4490
"resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz",
3270 4491
"integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==",
3271 4492
"devOptional": true,
3272 4493
"license": "MIT"
3273 4494
},
4495 +
"node_modules/has-ansi": {
4496 +
"version": "2.0.0",
4497 +
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
4498 +
"integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
4499 +
"dev": true,
4500 +
"license": "MIT",
4501 +
"dependencies": {
4502 +
"ansi-regex": "^2.0.0"
4503 +
},
4504 +
"engines": {
4505 +
"node": ">=0.10.0"
4506 +
}
4507 +
},
4508 +
"node_modules/has-ansi/node_modules/ansi-regex": {
4509 +
"version": "2.1.1",
4510 +
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
4511 +
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
4512 +
"dev": true,
4513 +
"license": "MIT",
4514 +
"engines": {
4515 +
"node": ">=0.10.0"
4516 +
}
4517 +
},
3274 4518
"node_modules/has-symbols": {
3275 4519
"version": "1.1.0",
3276 4520
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
3277 4521
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
3278 4522
"license": "MIT",
3307 4551
"dependencies": {
3308 4552
"function-bind": "^1.1.2"
3309 4553
},
3310 4554
"engines": {
3311 4555
"node": ">= 0.4"
4556 +
}
4557 +
},
4558 +
"node_modules/home-or-tmp": {
4559 +
"version": "2.0.0",
4560 +
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
4561 +
"integrity": "sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==",
4562 +
"dev": true,
4563 +
"license": "MIT",
4564 +
"dependencies": {
4565 +
"os-homedir": "^1.0.0",
4566 +
"os-tmpdir": "^1.0.1"
4567 +
},
4568 +
"engines": {
4569 +
"node": ">=0.10.0"
3312 4570
}
3313 4571
},
3314 4572
"node_modules/hono": {
3315 4573
"version": "4.11.4",
3316 4574
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz",
3461 4719
"version": "1.3.8",
3462 4720
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
3463 4721
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
3464 4722
"license": "ISC"
3465 4723
},
4724 +
"node_modules/invariant": {
4725 +
"version": "2.2.4",
4726 +
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
4727 +
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
4728 +
"dev": true,
4729 +
"license": "MIT",
4730 +
"dependencies": {
4731 +
"loose-envify": "^1.0.0"
4732 +
}
4733 +
},
3466 4734
"node_modules/ipaddr.js": {
3467 4735
"version": "1.9.1",
3468 4736
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
3469 4737
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
3470 4738
"license": "MIT",
3501 4769
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
3502 4770
"dev": true,
3503 4771
"license": "MIT",
3504 4772
"engines": {
3505 4773
"node": ">=0.10.0"
4774 +
}
4775 +
},
4776 +
"node_modules/is-finite": {
4777 +
"version": "1.1.0",
4778 +
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
4779 +
"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
4780 +
"dev": true,
4781 +
"license": "MIT",
4782 +
"engines": {
4783 +
"node": ">=0.10.0"
4784 +
},
4785 +
"funding": {
4786 +
"url": "https://github.com/sponsors/sindresorhus"
3506 4787
}
3507 4788
},
3508 4789
"node_modules/is-fullwidth-code-point": {
3509 4790
"version": "4.0.0",
3510 4791
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
3644 4925
"license": "MIT",
3645 4926
"engines": {
3646 4927
"node": ">= 0.8"
3647 4928
}
3648 4929
},
4930 +
"node_modules/js-tokens": {
4931 +
"version": "3.0.2",
4932 +
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
4933 +
"integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==",
4934 +
"dev": true,
4935 +
"license": "MIT"
4936 +
},
3649 4937
"node_modules/js-yaml": {
3650 4938
"version": "3.14.2",
3651 4939
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
3652 4940
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
3653 4941
"dev": true,
3658 4946
},
3659 4947
"bin": {
3660 4948
"js-yaml": "bin/js-yaml.js"
3661 4949
}
3662 4950
},
4951 +
"node_modules/jsesc": {
4952 +
"version": "1.3.0",
4953 +
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
4954 +
"integrity": "sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==",
4955 +
"dev": true,
4956 +
"license": "MIT",
4957 +
"bin": {
4958 +
"jsesc": "bin/jsesc"
4959 +
}
4960 +
},
3663 4961
"node_modules/json5": {
3664 4962
"version": "2.2.3",
3665 4963
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
3666 4964
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
3667 4965
"dev": true,
3792 5090
"version": "5.3.2",
3793 5091
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
3794 5092
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
3795 5093
"devOptional": true,
3796 5094
"license": "Apache-2.0"
5095 +
},
5096 +
"node_modules/loose-envify": {
5097 +
"version": "1.4.0",
5098 +
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
5099 +
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
5100 +
"dev": true,
5101 +
"license": "MIT",
5102 +
"dependencies": {
5103 +
"js-tokens": "^3.0.0 || ^4.0.0"
5104 +
},
5105 +
"bin": {
5106 +
"loose-envify": "cli.js"
5107 +
}
3797 5108
},
3798 5109
"node_modules/lru-cache": {
3799 5110
"version": "10.4.3",
3800 5111
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
3801 5112
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
4056 5367
},
4057 5368
"engines": {
4058 5369
"node": ">= 18"
4059 5370
}
4060 5371
},
5372 +
"node_modules/mkdirp": {
5373 +
"version": "0.5.6",
5374 +
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
5375 +
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
5376 +
"dev": true,
5377 +
"license": "MIT",
5378 +
"dependencies": {
5379 +
"minimist": "^1.2.6"
5380 +
},
5381 +
"bin": {
5382 +
"mkdirp": "bin/cmd.js"
5383 +
}
5384 +
},
4061 5385
"node_modules/mkdirp-classic": {
4062 5386
"version": "0.5.3",
4063 5387
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
4064 5388
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
4065 5389
"license": "MIT"
4375 5699
"license": "ISC",
4376 5700
"dependencies": {
4377 5701
"wrappy": "1"
4378 5702
}
4379 5703
},
5704 +
"node_modules/os-homedir": {
5705 +
"version": "1.0.2",
5706 +
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
5707 +
"integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==",
5708 +
"dev": true,
5709 +
"license": "MIT",
5710 +
"engines": {
5711 +
"node": ">=0.10.0"
5712 +
}
5713 +
},
5714 +
"node_modules/os-tmpdir": {
5715 +
"version": "1.0.2",
5716 +
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
5717 +
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
5718 +
"dev": true,
5719 +
"license": "MIT",
5720 +
"engines": {
5721 +
"node": ">=0.10.0"
5722 +
}
5723 +
},
4380 5724
"node_modules/p-map": {
4381 5725
"version": "7.0.4",
4382 5726
"resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz",
4383 5727
"integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==",
4384 5728
"dev": true,
4432 5776
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
4433 5777
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
4434 5778
"license": "MIT",
4435 5779
"engines": {
4436 5780
"node": ">= 0.8"
5781 +
}
5782 +
},
5783 +
"node_modules/path-is-absolute": {
5784 +
"version": "1.0.1",
5785 +
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
5786 +
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
5787 +
"dev": true,
5788 +
"license": "MIT",
5789 +
"engines": {
5790 +
"node": ">=0.10.0"
4437 5791
}
4438 5792
},
4439 5793
"node_modules/path-key": {
4440 5794
"version": "3.1.1",
4441 5795
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
4779 6133
"typescript": {
4780 6134
"optional": true
4781 6135
}
4782 6136
}
4783 6137
},
6138 +
"node_modules/private": {
6139 +
"version": "0.1.8",
6140 +
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
6141 +
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
6142 +
"dev": true,
6143 +
"license": "MIT",
6144 +
"engines": {
6145 +
"node": ">= 0.6"
6146 +
}
6147 +
},
4784 6148
"node_modules/proper-lockfile": {
4785 6149
"version": "4.1.2",
4786 6150
"resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
4787 6151
"integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
4788 6152
"devOptional": true,
4810 6174
"ipaddr.js": "1.9.1"
4811 6175
},
4812 6176
"engines": {
4813 6177
"node": ">= 0.10"
4814 6178
}
6179 +
},
6180 +
"node_modules/pseudomap": {
6181 +
"version": "1.0.2",
6182 +
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
6183 +
"integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
6184 +
"dev": true,
6185 +
"license": "ISC"
4815 6186
},
4816 6187
"node_modules/pump": {
4817 6188
"version": "3.0.3",
4818 6189
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
4819 6190
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
4987 6358
"funding": {
4988 6359
"type": "individual",
4989 6360
"url": "https://paulmillr.com/funding/"
4990 6361
}
4991 6362
},
6363 +
"node_modules/regenerate": {
6364 +
"version": "1.4.2",
6365 +
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
6366 +
"integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
6367 +
"dev": true,
6368 +
"license": "MIT"
6369 +
},
6370 +
"node_modules/regenerator-runtime": {
6371 +
"version": "0.11.1",
6372 +
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
6373 +
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
6374 +
"dev": true,
6375 +
"license": "MIT"
6376 +
},
6377 +
"node_modules/regenerator-transform": {
6378 +
"version": "0.10.1",
6379 +
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
6380 +
"integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
6381 +
"dev": true,
6382 +
"license": "BSD",
6383 +
"dependencies": {
6384 +
"babel-runtime": "^6.18.0",
6385 +
"babel-types": "^6.19.0",
6386 +
"private": "^0.1.6"
6387 +
}
6388 +
},
4992 6389
"node_modules/regexp-to-ast": {
4993 6390
"version": "0.5.0",
4994 6391
"resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz",
4995 6392
"integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==",
4996 6393
"devOptional": true,
4997 6394
"license": "MIT"
4998 6395
},
6396 +
"node_modules/regexpu-core": {
6397 +
"version": "2.0.0",
6398 +
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
6399 +
"integrity": "sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==",
6400 +
"dev": true,
6401 +
"license": "MIT",
6402 +
"dependencies": {
6403 +
"regenerate": "^1.2.1",
6404 +
"regjsgen": "^0.2.0",
6405 +
"regjsparser": "^0.1.4"
6406 +
}
6407 +
},
6408 +
"node_modules/regjsgen": {
6409 +
"version": "0.2.0",
6410 +
"resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
6411 +
"integrity": "sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==",
6412 +
"dev": true,
6413 +
"license": "MIT"
6414 +
},
6415 +
"node_modules/regjsparser": {
6416 +
"version": "0.1.5",
6417 +
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
6418 +
"integrity": "sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==",
6419 +
"dev": true,
6420 +
"license": "BSD",
6421 +
"dependencies": {
6422 +
"jsesc": "~0.5.0"
6423 +
},
6424 +
"bin": {
6425 +
"regjsparser": "bin/parser"
6426 +
}
6427 +
},
6428 +
"node_modules/regjsparser/node_modules/jsesc": {
6429 +
"version": "0.5.0",
6430 +
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
6431 +
"integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
6432 +
"dev": true,
6433 +
"bin": {
6434 +
"jsesc": "bin/jsesc"
6435 +
}
6436 +
},
4999 6437
"node_modules/remeda": {
5000 6438
"version": "2.33.4",
5001 6439
"resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz",
5002 6440
"integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==",
5003 6441
"devOptional": true,
5004 6442
"license": "MIT",
5005 6443
"funding": {
5006 6444
"url": "https://github.com/sponsors/remeda"
6445 +
}
6446 +
},
6447 +
"node_modules/repeating": {
6448 +
"version": "2.0.1",
6449 +
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
6450 +
"integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==",
6451 +
"dev": true,
6452 +
"license": "MIT",
6453 +
"dependencies": {
6454 +
"is-finite": "^1.0.0"
6455 +
},
6456 +
"engines": {
6457 +
"node": ">=0.10.0"
5007 6458
}
5008 6459
},
5009 6460
"node_modules/require-directory": {
5010 6461
"version": "2.1.1",
5011 6462
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
5402 6853
},
5403 6854
"funding": {
5404 6855
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
5405 6856
}
5406 6857
},
6858 +
"node_modules/source-map": {
6859 +
"version": "0.5.7",
6860 +
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
6861 +
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
6862 +
"dev": true,
6863 +
"license": "BSD-3-Clause",
6864 +
"engines": {
6865 +
"node": ">=0.10.0"
6866 +
}
6867 +
},
6868 +
"node_modules/source-map-support": {
6869 +
"version": "0.4.18",
6870 +
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
6871 +
"integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
6872 +
"dev": true,
6873 +
"license": "MIT",
6874 +
"dependencies": {
6875 +
"source-map": "^0.5.6"
6876 +
}
6877 +
},
5407 6878
"node_modules/split2": {
5408 6879
"version": "4.2.0",
5409 6880
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
5410 6881
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
5411 6882
"license": "ISC",
5673 7144
},
5674 7145
"engines": {
5675 7146
"node": ">=14.18.0"
5676 7147
}
5677 7148
},
7149 +
"node_modules/supports-color": {
7150 +
"version": "2.0.0",
7151 +
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
7152 +
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
7153 +
"dev": true,
7154 +
"license": "MIT",
7155 +
"engines": {
7156 +
"node": ">=0.8.0"
7157 +
}
7158 +
},
5678 7159
"node_modules/tar": {
5679 7160
"version": "7.5.2",
5680 7161
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz",
5681 7162
"integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==",
5682 7163
"dev": true,
5758 7239
"license": "MIT",
5759 7240
"engines": {
5760 7241
"node": ">=18"
5761 7242
}
5762 7243
},
7244 +
"node_modules/to-fast-properties": {
7245 +
"version": "1.0.3",
7246 +
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
7247 +
"integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==",
7248 +
"dev": true,
7249 +
"license": "MIT",
7250 +
"engines": {
7251 +
"node": ">=0.10.0"
7252 +
}
7253 +
},
5763 7254
"node_modules/to-regex-range": {
5764 7255
"version": "5.0.1",
5765 7256
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
5766 7257
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
5767 7258
"dev": true,
5786 7277
"version": "0.0.3",
5787 7278
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
5788 7279
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
5789 7280
"dev": true,
5790 7281
"license": "MIT"
7282 +
},
7283 +
"node_modules/trim-right": {
7284 +
"version": "1.0.1",
7285 +
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
7286 +
"integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==",
7287 +
"dev": true,
7288 +
"license": "MIT",
7289 +
"engines": {
7290 +
"node": ">=0.10.0"
7291 +
}
5791 7292
},
5792 7293
"node_modules/ts-node": {
5793 7294
"version": "10.9.2",
5794 7295
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
5795 7296
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
6444 7945
"graphmatch": "^1.1.0"
6445 7946
}
6446 7947
}
6447 7948
}
6448 7949
}
api/package.json
1 1
{
2 2
"name": "orbit-api",
3 3
"version": "0.0.0",
4 4
"description": "",
5 5
"license": "ISC",
9 9
"test": "tests"
10 10
},
11 11
"scripts": {
12 12
"build": "tsc && tsc-alias",
13 13
"start": "ts-node -r tsconfig-paths/register src/index.ts",
14 -
"test": "npm run test:setup && NODE_ENV=test npx ava tests/database.test.ts",
14 +
"test": "npm run test:setup && NODE_ENV=test npx ava",
15 15
"test:setup": "npm run test:setup:generate && npm run test:setup:migrate",
16 -
"test:setup:generate": "DATABASE_URL='postgres://user:password@orbit_db:5432/orbit_test' npx prisma generate",
17 -
"test:setup:migrate": "DATABASE_URL='postgres://user:password@orbit_db:5432/orbit_test' npx prisma migrate deploy",
16 +
"test:setup:generate": "dotenv -e .env.test npx prisma generate",
17 +
"test:setup:migrate": "dotenv -e .env.test npx prisma db push",
18 18
"test:watch": "npm run test:setup && NODE_ENV=test npx ava --watch",
19 19
"dev": "prisma generate && prisma migrate deploy && npm run start"
20 20
},
21 21
"dependencies": {
22 22
"@prisma/adapter-better-sqlite3": "^7.5.0",
38 38
"@types/better-sqlite3": "^7.6.13",
39 39
"@types/express": "^5.0.6",
40 40
"@types/morgan": "^1.9.10",
41 41
"@types/node": "^25.5.2",
42 42
"ava": "^6.4.1",
43 +
"cross-var": "^1.1.0",
44 +
"dotenv-cli": "^11.0.0",
43 45
"prisma": "^7.5.0",
44 46
"supertest": "^7.1.4",
45 47
"ts-node": "^10.9.2",
46 48
"tsc-alias": "^1.8.16",
47 49
"tsconfig-paths": "^4.2.0",
48 50
"tsx": "^4.21.0",
49 51
"typescript": "^6.0.2"
50 52
}
51 53
}
/dev/null → api/tests/database-auth.test.ts
1 +
import test from "ava";
2 +
import { PrismaClient } from '@prisma/client';
3 +
import { PrismaPg } from '@prisma/adapter-pg';
4 +
import bcrypt from 'bcryptjs';
5 +
import 'dotenv/config';
6 +
7 +
let prisma: PrismaClient;
8 +
9 +
test.before(() => {
10 +
process.env.NODE_ENV = 'test';
11 +
12 +
const connectionString = process.env.DATABASE_URL || 'postgres://user:password@orbit_db:5432/orbit_test';
13 +
const adapter = new PrismaPg({ connectionString });
14 +
prisma = new PrismaClient({ adapter });
15 +
});
16 +
17 +
test.beforeEach(async () => {
18 +
// Clean database before each test
19 +
try {
20 +
await prisma.user.deleteMany({});
21 +
} catch (err) {
22 +
console.error('Error cleaning test DB:', err);
23 +
}
24 +
});
25 +
26 +
test.after.always(async () => {
27 +
await prisma?.$disconnect();
28 +
});
29 +
30 +
// Basic database connectivity test
31 +
test("database connection works", async (t) => {
32 +
const result = await prisma.$queryRaw`SELECT 1 as test`;
33 +
t.truthy(result);
34 +
});
35 +
36 +
// User creation and authentication tests
37 +
test("can create user with encrypted password", async (t) => {
38 +
const encryptedPassword = bcrypt.hashSync("testPassword123", 10);
39 +
40 +
const user = await prisma.user.create({
41 +
data: {
42 +
email: "test@example.com",
43 +
firstName: "Test",
44 +
lastName: "User",
45 +
encryptedPassword: encryptedPassword
46 +
}
47 +
});
48 +
49 +
t.is(user.email, "test@example.com");
50 +
t.is(user.firstName, "Test");
51 +
t.truthy(user.id);
52 +
53 +
// Verify password can be validated
54 +
t.true(bcrypt.compareSync("testPassword123", user.encryptedPassword));
55 +
t.false(bcrypt.compareSync("wrongPassword", user.encryptedPassword));
56 +
});
57 +
58 +
test("can find user by email for authentication", async (t) => {
59 +
// Create user
60 +
await prisma.user.create({
61 +
data: {
62 +
email: "login@example.com",
63 +
firstName: "Login",
64 +
lastName: "User",
65 +
encryptedPassword: bcrypt.hashSync("password123", 10)
66 +
}
67 +
});
68 +
69 +
// Simulate login lookup
70 +
const foundUser = await prisma.user.findUnique({
71 +
where: { email: "login@example.com" }
72 +
});
73 +
74 +
t.truthy(foundUser);
75 +
t.is(foundUser!.email, "login@example.com");
76 +
t.true(bcrypt.compareSync("password123", foundUser!.encryptedPassword));
77 +
t.false(bcrypt.compareSync("wrongPassword", foundUser!.encryptedPassword));
78 +
});
79 +
80 +
test("email uniqueness constraint prevents duplicate registrations", async (t) => {
81 +
const email = "duplicate@example.com";
82 +
83 +
// Create first user
84 +
await prisma.user.create({
85 +
data: {
86 +
email,
87 +
firstName: "First",
88 +
lastName: "User",
89 +
encryptedPassword: bcrypt.hashSync("password", 10)
90 +
}
91 +
});
92 +
93 +
// Try to create second user with same email - should fail
94 +
await t.throwsAsync(
95 +
async () => {
96 +
await prisma.user.create({
97 +
data: {
98 +
email,
99 +
firstName: "Second",
100 +
lastName: "User",
101 +
encryptedPassword: bcrypt.hashSync("password", 10)
102 +
}
103 +
});
104 +
}
105 +
);
106 +
});
107 +
108 +
test("password reset flow works with database", async (t) => {
109 +
const resetToken = "reset-token-123";
110 +
const resetExpires = new Date(Date.now() + 3600000); // 1 hour from now
111 +
112 +
// Create user
113 +
const user = await prisma.user.create({
114 +
data: {
115 +
email: "reset@example.com",
116 +
firstName: "Reset",
117 +
lastName: "User",
118 +
encryptedPassword: bcrypt.hashSync("oldPassword", 10)
119 +
}
120 +
});
121 +
122 +
// Step 1: Set reset token (forgot password)
123 +
await prisma.user.update({
124 +
where: { id: user.id },
125 +
data: {
126 +
passwordResetToken: resetToken,
127 +
passwordResetExpires: resetExpires
128 +
}
129 +
});
130 +
131 +
// Step 2: Find user by reset token
132 +
const userWithToken = await prisma.user.findFirst({
133 +
where: {
134 +
passwordResetToken: resetToken,
135 +
passwordResetExpires: { gte: new Date() } // Token not expired
136 +
}
137 +
});
138 +
139 +
t.truthy(userWithToken);
140 +
t.is(userWithToken!.email, "reset@example.com");
141 +
142 +
// Step 3: Reset password
143 +
const newPassword = bcrypt.hashSync("newPassword123", 10);
144 +
const updatedUser = await prisma.user.update({
145 +
where: { id: user.id },
146 +
data: {
147 +
encryptedPassword: newPassword,
148 +
passwordResetToken: null,
149 +
passwordResetExpires: null
150 +
}
151 +
});
152 +
153 +
// Verify new password works and reset fields are cleared
154 +
t.true(bcrypt.compareSync("newPassword123", updatedUser.encryptedPassword));
155 +
t.false(bcrypt.compareSync("oldPassword", updatedUser.encryptedPassword));
156 +
t.is(updatedUser.passwordResetToken, null);
157 +
t.is(updatedUser.passwordResetExpires, null);
158 +
});
159 +
160 +
test("expired reset tokens are not found", async (t) => {
161 +
const expiredResetToken = "expired-token";
162 +
const pastDate = new Date(Date.now() - 3600000); // 1 hour ago
163 +
164 +
// Create user with expired token
165 +
const user = await prisma.user.create({
166 +
data: {
167 +
email: "expired@example.com",
168 +
firstName: "Expired",
169 +
lastName: "User",
170 +
encryptedPassword: bcrypt.hashSync("password", 10),
171 +
passwordResetToken: expiredResetToken,
172 +
passwordResetExpires: pastDate
173 +
}
174 +
});
175 +
176 +
// Try to find user by expired token
177 +
const foundUser = await prisma.user.findFirst({
178 +
where: {
179 +
passwordResetToken: expiredResetToken,
180 +
passwordResetExpires: { gte: new Date() } // Token not expired
181 +
}
182 +
});
183 +
184 +
// Should not find the user because token is expired
185 +
t.is(foundUser, null);
186 +
187 +
// But user still exists
188 +
const stillExists = await prisma.user.findUnique({ where: { id: user.id } });
189 +
t.truthy(stillExists);
190 +
});
191 +
192 +
test("user profile update works", async (t) => {
193 +
// Create user
194 +
const user = await prisma.user.create({
195 +
data: {
196 +
email: "profile@example.com",
197 +
firstName: "Original",
198 +
lastName: "Name",
199 +
encryptedPassword: bcrypt.hashSync("password", 10)
200 +
}
201 +
});
202 +
203 +
// Update profile
204 +
const updatedUser = await prisma.user.update({
205 +
where: { id: user.id },
206 +
data: {
207 +
firstName: "Updated",
208 +
lastName: "Profile"
209 +
}
210 +
});
211 +
212 +
t.is(updatedUser.firstName, "Updated");
213 +
t.is(updatedUser.lastName, "Profile");
214 +
t.is(updatedUser.email, "profile@example.com"); // Should remain unchanged
215 +
t.true(updatedUser.updatedAt > user.updatedAt); // updatedAt should be newer
216 +
});
217 +
218 +
test("timestamps are automatically managed", async (t) => {
219 +
const beforeCreate = new Date();
220 +
221 +
const user = await prisma.user.create({
222 +
data: {
223 +
email: "timestamps@example.com",
224 +
firstName: "Time",
225 +
lastName: "Stamps",
226 +
encryptedPassword: bcrypt.hashSync("password", 10)
227 +
}
228 +
});
229 +
230 +
const afterCreate = new Date();
231 +
232 +
// Check creation timestamps
233 +
t.true(user.createdAt >= beforeCreate);
234 +
t.true(user.createdAt <= afterCreate);
235 +
t.true(user.updatedAt >= beforeCreate);
236 +
t.true(user.updatedAt <= afterCreate);
237 +
238 +
// Wait and update to test updatedAt behavior
239 +
await new Promise(resolve => setTimeout(resolve, 100));
240 +
const beforeUpdate = new Date();
241 +
242 +
const updatedUser = await prisma.user.update({
243 +
where: { id: user.id },
244 +
data: { firstName: "Updated" }
245 +
});
246 +
247 +
const afterUpdate = new Date();
248 +
249 +
// createdAt should remain the same, updatedAt should be newer
250 +
t.deepEqual(updatedUser.createdAt, user.createdAt);
251 +
t.true(updatedUser.updatedAt >= beforeUpdate);
252 +
t.true(updatedUser.updatedAt <= afterUpdate);
253 +
t.true(updatedUser.updatedAt > user.updatedAt);
254 +
});
api/tests/mood.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "./test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
let userId;
9 -
10 -
test.before(() => {
11 -
db = setupTestDb();
12 -
app = createApp(db);
13 -
});
14 -
15 -
test.beforeEach(async () => {
16 -
cleanupTestDb();
17 -
18 -
// Create a user for the mood tests
19 -
const res = await request(app)
20 -
.post("/users")
21 -
.send({
22 -
email: "maria@example.com",
23 -
password: "123456",
24 -
first_name: "Maria",
25 -
last_name: "Silva",
26 -
});
27 -
28 -
userId = res.body.id;
29 -
});
30 -
31 -
test.serial("Registrar humor", async (t) => {
32 -
const res = await request(app).post("/mood").send({
33 -
user_id: userId,
34 -
stress_level: 3,
35 -
anxiety_level: 4,
36 -
energy_level: 5,
37 -
title: "Bad day",
38 -
description: "Stressado com a faculdade",
39 -
recorded_at: new Date().toISOString()
40 -
});
41 -
42 -
t.is(res.status, 201);
43 -
t.truthy(res.body.id);
44 -
});
45 -
46 -
test.serial("Listar humores do usuário", async (t) => {
47 -
const res = await request(app).get(`/mood/user/${userId}`);
48 -
t.is(res.status, 200);
49 -
t.true(Array.isArray(res.body.moods));
50 -
});
51 -
52 -
test.serial("Falha ao registrar humor sem stress_level", async (t) => {
53 -
const res = await request(app).post("/mood").send({
54 -
user_id: userId,
55 -
anxiety_level: 4,
56 -
energy_level: 5,
57 -
title: "Test",
58 -
recorded_at: new Date().toISOString()
59 -
});
60 -
61 -
t.is(res.status, 400);
62 -
t.is(res.body.error, "Campos faltantes");
63 -
});
64 -
65 -
test.serial("Listar múltiplos humores do usuário", async (t) => {
66 -
// Ensure we have a valid userId
67 -
t.truthy(userId, "userId should be defined");
68 -
69 -
// Create first mood entry
70 -
const res1 = await request(app).post("/mood").send({
71 -
user_id: userId,
72 -
stress_level: 3,
73 -
anxiety_level: 4,
74 -
energy_level: 6,
75 -
title: "Morning",
76 -
description: "Morning mood",
77 -
recorded_at: new Date().toISOString()
78 -
});
79 -
t.is(res1.status, 201);
80 -
81 -
// Create second mood entry
82 -
const res2 = await request(app).post("/mood").send({
83 -
user_id: userId,
84 -
stress_level: 2,
85 -
anxiety_level: 2,
86 -
energy_level: 8,
87 -
title: "Evening",
88 -
description: "Evening mood",
89 -
recorded_at: new Date().toISOString()
90 -
});
91 -
t.is(res2.status, 201);
92 -
93 -
const res = await request(app).get(`/mood/user/${userId}`);
94 -
t.is(res.status, 200);
95 -
t.true(Array.isArray(res.body.moods));
96 -
t.is(res.body.moods.length, 2);
97 -
});
98 -
api/tests/mood/creation.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "../test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
let userId;
9 -
10 -
test.before(() => {
11 -
db = setupTestDb();
12 -
app = createApp(db);
13 -
});
14 -
15 -
test.beforeEach(async () => {
16 -
cleanupTestDb();
17 -
18 -
// Create a test user with unique email
19 -
const uniqueEmail = `mood_${Date.now()}_${Math.random()}@example.com`;
20 -
const res = await request(app)
21 -
.post("/users")
22 -
.send({
23 -
email: uniqueEmail,
24 -
password: "senha123",
25 -
first_name: "Mood",
26 -
last_name: "Tester"
27 -
});
28 -
29 -
if (res.status !== 201) {
30 -
throw new Error(`Failed to create test user: ${JSON.stringify(res.body)}`);
31 -
}
32 -
33 -
userId = res.body.id;
34 -
});
35 -
36 -
test("Criar registro de humor com todos os campos obrigatórios", async (t) => {
37 -
const now = new Date().toISOString();
38 -
39 -
const res = await request(app)
40 -
.post("/mood")
41 -
.send({
42 -
user_id: userId,
43 -
stress_level: 3,
44 -
anxiety_level: 4,
45 -
energy_level: 7,
46 -
recorded_at: now
47 -
});
48 -
49 -
t.is(res.status, 201);
50 -
t.truthy(res.body.id);
51 -
});
52 -
53 -
test("Criar registro de humor com avaliação e descrição", async (t) => {
54 -
const now = new Date().toISOString();
55 -
56 -
const res = await request(app)
57 -
.post("/mood")
58 -
.send({
59 -
user_id: userId,
60 -
rating: 8,
61 -
stress_level: 2,
62 -
anxiety_level: 3,
63 -
energy_level: 9,
64 -
title: "Dia produtivo",
65 -
description: "Consegui terminar todas as tarefas",
66 -
recorded_at: now
67 -
});
68 -
69 -
t.is(res.status, 201);
70 -
71 -
// Verify data was saved correctly
72 -
const mood = db.prepare("SELECT * FROM mood WHERE id = ?").get(res.body.id);
73 -
t.is(mood.rating, 8);
74 -
t.is(mood.stress_level, 2);
75 -
t.is(mood.title, "Dia produtivo");
76 -
});
77 -
78 -
test("Criar registro de humor com componentes emocionais", async (t) => {
79 -
const now = new Date().toISOString();
80 -
81 -
const res = await request(app)
82 -
.post("/mood")
83 -
.send({
84 -
user_id: userId,
85 -
stress_level: 5,
86 -
anxiety_level: 6,
87 -
energy_level: 4,
88 -
recorded_at: now,
89 -
mood_components: [
90 -
{ emotion: "joy", intensity: 7 },
91 -
{ emotion: "anxiety", intensity: 6 },
92 -
{ emotion: "trust", intensity: 8 }
93 -
]
94 -
});
95 -
96 -
t.is(res.status, 201);
97 -
98 -
// Verify components were saved
99 -
const components = db.prepare("SELECT * FROM mood_components WHERE mood_id = ?").all(res.body.id);
100 -
t.is(components.length, 3);
101 -
102 -
const emotions = components.map(c => c.emotion);
103 -
t.true(emotions.includes('joy'));
104 -
t.true(emotions.includes('anxiety'));
105 -
t.true(emotions.includes('trust'));
106 -
});
107 -
108 -
test("Componentes emocionais devem aceitar maiúsculas e converter para minúsculas", async (t) => {
109 -
const now = new Date().toISOString();
110 -
111 -
const res = await request(app)
112 -
.post("/mood")
113 -
.send({
114 -
user_id: userId,
115 -
stress_level: 5,
116 -
anxiety_level: 6,
117 -
energy_level: 4,
118 -
recorded_at: now,
119 -
mood_components: [
120 -
{ emotion: "JOY", intensity: 7 },
121 -
{ emotion: "AnXiEtY", intensity: 6 }
122 -
]
123 -
});
124 -
125 -
t.is(res.status, 201);
126 -
127 -
// Verify emotions were lowercased
128 -
const components = db.prepare("SELECT emotion FROM mood_components WHERE mood_id = ? ORDER BY emotion ASC").all(res.body.id);
129 -
t.is(components[0].emotion, 'anxiety');
130 -
t.is(components[1].emotion, 'joy');
131 -
});
132 -
133 -
test("Falha ao criar registro de humor sem ID de usuário", async (t) => {
134 -
const now = new Date().toISOString();
135 -
136 -
const res = await request(app)
137 -
.post("/mood")
138 -
.send({
139 -
stress_level: 3,
140 -
anxiety_level: 4,
141 -
energy_level: 7,
142 -
recorded_at: now
143 -
});
144 -
145 -
t.is(res.status, 400);
146 -
t.is(res.body.error, "Campos faltantes");
147 -
t.true(res.body.missing.includes('user_id'));
148 -
});
149 -
150 -
test("Falha ao criar registro de humor sem nível de stress", async (t) => {
151 -
const now = new Date().toISOString();
152 -
153 -
const res = await request(app)
154 -
.post("/mood")
155 -
.send({
156 -
user_id: userId,
157 -
anxiety_level: 4,
158 -
energy_level: 7,
159 -
recorded_at: now
160 -
});
161 -
162 -
t.is(res.status, 400);
163 -
t.is(res.body.error, "Campos faltantes");
164 -
t.true(res.body.missing.includes('stress_level'));
165 -
});
166 -
167 -
test("Falha ao criar registro de humor sem nível de ansiedade", async (t) => {
168 -
const now = new Date().toISOString();
169 -
170 -
const res = await request(app)
171 -
.post("/mood")
172 -
.send({
173 -
user_id: userId,
174 -
stress_level: 3,
175 -
energy_level: 7,
176 -
recorded_at: now
177 -
});
178 -
179 -
t.is(res.status, 400);
180 -
t.is(res.body.error, "Campos faltantes");
181 -
t.true(res.body.missing.includes('anxiety_level'));
182 -
});
183 -
184 -
test("Falha ao criar registro de humor sem nível de energia", async (t) => {
185 -
const now = new Date().toISOString();
186 -
187 -
const res = await request(app)
188 -
.post("/mood")
189 -
.send({
190 -
user_id: userId,
191 -
stress_level: 3,
192 -
anxiety_level: 4,
193 -
recorded_at: now
194 -
});
195 -
196 -
t.is(res.status, 400);
197 -
t.is(res.body.error, "Campos faltantes");
198 -
t.true(res.body.missing.includes('energy_level'));
199 -
});
200 -
201 -
test("Falha ao criar registro de humor sem data de registro", async (t) => {
202 -
const res = await request(app)
203 -
.post("/mood")
204 -
.send({
205 -
user_id: userId,
206 -
stress_level: 3,
207 -
anxiety_level: 4,
208 -
energy_level: 7
209 -
});
210 -
211 -
t.is(res.status, 400);
212 -
t.is(res.body.error, "Campos faltantes");
213 -
t.true(res.body.missing.includes('recorded_at'));
214 -
});
215 -
216 -
test("Falha ao criar registro de humor com nível de estresse inválido (menor que 1)", async (t) => {
217 -
const now = new Date().toISOString();
218 -
219 -
const res = await request(app)
220 -
.post("/mood")
221 -
.send({
222 -
user_id: userId,
223 -
stress_level: 0,
224 -
anxiety_level: 4,
225 -
energy_level: 7,
226 -
recorded_at: now
227 -
});
228 -
229 -
t.is(res.status, 400);
230 -
t.is(res.body.error, "stress_level deve ser entre 1 e 10");
231 -
});
232 -
233 -
test("Falha ao criar registro de humor com nível de estresse inválido (maior que 10)", async (t) => {
234 -
const now = new Date().toISOString();
235 -
236 -
const res = await request(app)
237 -
.post("/mood")
238 -
.send({
239 -
user_id: userId,
240 -
stress_level: 11,
241 -
anxiety_level: 4,
242 -
energy_level: 7,
243 -
recorded_at: now
244 -
});
245 -
246 -
t.is(res.status, 400);
247 -
t.is(res.body.error, "stress_level deve ser entre 1 e 10");
248 -
});
249 -
250 -
test("Falha ao criar registro de humor com nível de ansiedade inválido", async (t) => {
251 -
const now = new Date().toISOString();
252 -
253 -
const res = await request(app)
254 -
.post("/mood")
255 -
.send({
256 -
user_id: userId,
257 -
stress_level: 3,
258 -
anxiety_level: 15,
259 -
energy_level: 7,
260 -
recorded_at: now
261 -
});
262 -
263 -
t.is(res.status, 400);
264 -
t.is(res.body.error, "anxiety_level deve ser entre 1 e 10");
265 -
});
266 -
267 -
test("Falha ao criar registro de humor com nível de energia inválido", async (t) => {
268 -
const now = new Date().toISOString();
269 -
270 -
const res = await request(app)
271 -
.post("/mood")
272 -
.send({
273 -
user_id: userId,
274 -
stress_level: 3,
275 -
anxiety_level: 4,
276 -
energy_level: -5,
277 -
recorded_at: now
278 -
});
279 -
280 -
t.is(res.status, 400);
281 -
t.is(res.body.error, "energy_level deve ser entre 1 e 10");
282 -
});
283 -
284 -
test("Falha ao criar registro de humor com avaliação inválido", async (t) => {
285 -
const now = new Date().toISOString();
286 -
287 -
const res = await request(app)
288 -
.post("/mood")
289 -
.send({
290 -
user_id: userId,
291 -
rating: 20,
292 -
stress_level: 3,
293 -
anxiety_level: 4,
294 -
energy_level: 7,
295 -
recorded_at: now
296 -
});
297 -
298 -
t.is(res.status, 400);
299 -
t.is(res.body.error, "rating deve ser entre 1 e 10");
300 -
});
301 -
302 -
test("Falha ao criar registro de humor com data inválida", async (t) => {
303 -
const res = await request(app)
304 -
.post("/mood")
305 -
.send({
306 -
user_id: userId,
307 -
stress_level: 3,
308 -
anxiety_level: 4,
309 -
energy_level: 7,
310 -
recorded_at: "data-invalida"
311 -
});
312 -
313 -
t.is(res.status, 400);
314 -
t.is(res.body.error, "recorded_at deve ser uma data válida");
315 -
});
316 -
317 -
test("Falha ao criar registro de humor com data no futuro", async (t) => {
318 -
const futureDate = new Date();
319 -
futureDate.setDate(futureDate.getDate() + 1);
320 -
321 -
const res = await request(app)
322 -
.post("/mood")
323 -
.send({
324 -
user_id: userId,
325 -
stress_level: 3,
326 -
anxiety_level: 4,
327 -
energy_level: 7,
328 -
recorded_at: futureDate.toISOString()
329 -
});
330 -
331 -
t.is(res.status, 400);
332 -
t.is(res.body.error, "recorded_at não pode ser no futuro");
333 -
});
334 -
335 -
test("Falha ao criar registro de humor com emoção inválida", async (t) => {
336 -
const now = new Date().toISOString();
337 -
338 -
const res = await request(app)
339 -
.post("/mood")
340 -
.send({
341 -
user_id: userId,
342 -
stress_level: 3,
343 -
anxiety_level: 4,
344 -
energy_level: 7,
345 -
recorded_at: now,
346 -
mood_components: [
347 -
{ emotion: "invalid_emotion", intensity: 5 }
348 -
]
349 -
});
350 -
351 -
t.is(res.status, 400);
352 -
t.regex(res.body.error, /Invalid emotion/);
353 -
});
354 -
355 -
test("Falha ao criar registro de humor com intensidade inválida (menor que 1)", async (t) => {
356 -
const now = new Date().toISOString();
357 -
358 -
const res = await request(app)
359 -
.post("/mood")
360 -
.send({
361 -
user_id: userId,
362 -
stress_level: 3,
363 -
anxiety_level: 4,
364 -
energy_level: 7,
365 -
recorded_at: now,
366 -
mood_components: [
367 -
{ emotion: "joy", intensity: 0 }
368 -
]
369 -
});
370 -
371 -
t.is(res.status, 400);
372 -
t.regex(res.body.error, /Invalid intensity/);
373 -
});
374 -
375 -
test("Falha ao criar registro de humor com intensidade inválida (maior que 10)", async (t) => {
376 -
const now = new Date().toISOString();
377 -
378 -
const res = await request(app)
379 -
.post("/mood")
380 -
.send({
381 -
user_id: userId,
382 -
stress_level: 3,
383 -
anxiety_level: 4,
384 -
energy_level: 7,
385 -
recorded_at: now,
386 -
mood_components: [
387 -
{ emotion: "sad", intensity: 11 }
388 -
]
389 -
});
390 -
391 -
t.is(res.status, 400);
392 -
t.regex(res.body.error, /Invalid intensity/);
393 -
});
394 -
395 -
test("Falha ao criar registro de humor com emoções duplicadas", async (t) => {
396 -
const now = new Date().toISOString();
397 -
398 -
const res = await request(app)
399 -
.post("/mood")
400 -
.send({
401 -
user_id: userId,
402 -
stress_level: 3,
403 -
anxiety_level: 4,
404 -
energy_level: 7,
405 -
recorded_at: now,
406 -
mood_components: [
407 -
{ emotion: "joy", intensity: 7 },
408 -
{ emotion: "joy", intensity: 5 }
409 -
]
410 -
});
411 -
412 -
t.is(res.status, 400);
413 -
t.regex(res.body.error, /Duplicate emotion/);
414 -
});
415 -
416 -
test("Falha ao criar registro de humor com componente sem emoção de referencia", async (t) => {
417 -
const now = new Date().toISOString();
418 -
419 -
const res = await request(app)
420 -
.post("/mood")
421 -
.send({
422 -
user_id: userId,
423 -
stress_level: 3,
424 -
anxiety_level: 4,
425 -
energy_level: 7,
426 -
recorded_at: now,
427 -
mood_components: [
428 -
{ intensity: 5 }
429 -
]
430 -
});
431 -
432 -
t.is(res.status, 400);
433 -
t.regex(res.body.error, /must have emotion and intensity/);
434 -
});
435 -
436 -
test("Falha ao criar registro de humor com componente sem intensidade", async (t) => {
437 -
const now = new Date().toISOString();
438 -
439 -
const res = await request(app)
440 -
.post("/mood")
441 -
.send({
442 -
user_id: userId,
443 -
stress_level: 3,
444 -
anxiety_level: 4,
445 -
energy_level: 7,
446 -
recorded_at: now,
447 -
mood_components: [
448 -
{ emotion: "joy" }
449 -
]
450 -
});
451 -
452 -
t.is(res.status, 400);
453 -
t.regex(res.body.error, /must have emotion and intensity/);
454 -
});
455 -
456 -
test("Criar registro de humor com lista vazia de componentes deve funcionar", async (t) => {
457 -
const now = new Date().toISOString();
458 -
459 -
const res = await request(app)
460 -
.post("/mood")
461 -
.send({
462 -
user_id: userId,
463 -
stress_level: 3,
464 -
anxiety_level: 4,
465 -
energy_level: 7,
466 -
recorded_at: now,
467 -
mood_components: []
468 -
});
469 -
470 -
t.is(res.status, 201);
471 -
472 -
// Verify no components were created
473 -
const components = db.prepare("SELECT * FROM mood_components WHERE mood_id = ?").all(res.body.id);
474 -
t.is(components.length, 0);
475 -
});
476 -
477 -
test("Descrição e título devem ser sanitizados (truncados em 500 caracteres)", async (t) => {
478 -
const now = new Date().toISOString();
479 -
const longText = "A".repeat(600);
480 -
481 -
const res = await request(app)
482 -
.post("/mood")
483 -
.send({
484 -
user_id: userId,
485 -
stress_level: 3,
486 -
anxiety_level: 4,
487 -
energy_level: 7,
488 -
recorded_at: now,
489 -
title: longText,
490 -
description: longText
491 -
});
492 -
493 -
t.is(res.status, 201);
494 -
495 -
const mood = db.prepare("SELECT title, description FROM mood WHERE id = ?").get(res.body.id);
496 -
t.is(mood.title.length, 500);
497 -
t.is(mood.description.length, 500);
498 -
});
api/tests/mood/queries.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "../test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
let userId;
9 -
let moodIds = [];
10 -
11 -
test.before(() => {
12 -
db = setupTestDb();
13 -
app = createApp(db);
14 -
});
15 -
16 -
test.beforeEach(async () => {
17 -
cleanupTestDb();
18 -
moodIds = [];
19 -
20 -
// Create a test user with unique email
21 -
const uniqueEmail = `mood_${Date.now()}_${Math.random()}@example.com`;
22 -
const userRes = await request(app)
23 -
.post("/users")
24 -
.send({
25 -
email: uniqueEmail,
26 -
password: "senha123",
27 -
first_name: "Mood",
28 -
last_name: "Tester"
29 -
});
30 -
31 -
if (userRes.status !== 201) {
32 -
throw new Error(`Failed to create test user: ${JSON.stringify(userRes.body)}`);
33 -
}
34 -
35 -
userId = userRes.body.id;
36 -
37 -
// Create multiple moods for testing
38 -
const dates = [
39 -
new Date('2024-01-15T10:00:00Z'),
40 -
new Date('2024-01-20T14:30:00Z'),
41 -
new Date('2024-02-01T08:00:00Z'),
42 -
new Date('2024-02-15T16:45:00Z'),
43 -
new Date('2024-03-01T12:00:00Z')
44 -
];
45 -
46 -
for (let i = 0; i < dates.length; i++) {
47 -
const moodRes = await request(app)
48 -
.post("/mood")
49 -
.send({
50 -
user_id: userId,
51 -
rating: 5 + i,
52 -
stress_level: 3 + i,
53 -
anxiety_level: 2 + i,
54 -
energy_level: 6 - i,
55 -
title: `Mood ${i + 1}`,
56 -
recorded_at: dates[i].toISOString(),
57 -
mood_components: i % 2 === 0 ? [
58 -
{ emotion: "joy", intensity: 5 + i },
59 -
{ emotion: "trust", intensity: 4 + i }
60 -
] : []
61 -
});
62 -
moodIds.push(moodRes.body.id);
63 -
}
64 -
});
65 -
66 -
test.serial("Obter mood específico por ID", async (t) => {
67 -
const res = await request(app).get(`/mood/${moodIds[0]}`);
68 -
69 -
t.is(res.status, 200);
70 -
t.is(Number(res.body.id), Number(moodIds[0]));
71 -
t.is(Number(res.body.user_id), Number(userId));
72 -
t.is(res.body.title, "Mood 1");
73 -
t.truthy(res.body.first_name);
74 -
t.truthy(res.body.last_name);
75 -
t.true(Array.isArray(res.body.mood_components));
76 -
});
77 -
78 -
test.serial("Mood deve incluir componentes emocionais", async (t) => {
79 -
const res = await request(app).get(`/mood/${moodIds[0]}`);
80 -
81 -
t.is(res.status, 200);
82 -
t.is(res.body.mood_components.length, 2);
83 -
84 -
const emotions = res.body.mood_components.map(c => c.emotion);
85 -
t.true(emotions.includes('joy'));
86 -
t.true(emotions.includes('trust'));
87 -
});
88 -
89 -
test.serial("Mood deve incluir estatísticas emocionais quando houver componentes", async (t) => {
90 -
const res = await request(app).get(`/mood/${moodIds[0]}`);
91 -
92 -
t.is(res.status, 200);
93 -
t.truthy(res.body.emotion_stats);
94 -
t.truthy(res.body.emotion_stats.dominant);
95 -
t.truthy(res.body.emotion_stats.average);
96 -
t.truthy(res.body.emotion_stats.breakdown);
97 -
});
98 -
99 -
test.serial("Falha ao obter mood inexistente", async (t) => {
100 -
const res = await request(app).get("/mood/99999");
101 -
102 -
t.is(res.status, 404);
103 -
t.is(res.body.error, "Humor não encontrado");
104 -
});
105 -
106 -
test.serial("Obter todos os moods de um usuário", async (t) => {
107 -
const res = await request(app).get(`/mood/user/${userId}`);
108 -
109 -
t.is(res.status, 200);
110 -
t.truthy(res.body.moods);
111 -
t.is(res.body.moods.length, 5);
112 -
t.truthy(res.body.pagination);
113 -
t.is(res.body.pagination.total, 5);
114 -
});
115 -
116 -
test.serial("Moods devem estar ordenados por data (mais recente primeiro)", async (t) => {
117 -
const res = await request(app).get(`/mood/user/${userId}`);
118 -
119 -
t.is(res.status, 200);
120 -
121 -
const dates = res.body.moods.map(m => new Date(m.recorded_at));
122 -
for (let i = 1; i < dates.length; i++) {
123 -
t.true(dates[i - 1] >= dates[i]);
124 -
}
125 -
});
126 -
127 -
test.serial("Filtrar registros de humor por intervalo de datas", async (t) => {
128 -
const res = await request(app).get(`/mood/user/${userId}`)
129 -
.query({
130 -
start_date: '2024-01-01',
131 -
end_date: '2024-01-31'
132 -
});
133 -
134 -
t.is(res.status, 200);
135 -
t.is(res.body.moods.length, 2); // Only January moods
136 -
});
137 -
138 -
test.serial("Filtrar registros de humor apenas por data de início", async (t) => {
139 -
const res = await request(app).get(`/mood/user/${userId}`)
140 -
.query({
141 -
start_date: '2024-02-01'
142 -
});
143 -
144 -
t.is(res.status, 200);
145 -
t.is(res.body.moods.length, 3); // Feb and March moods
146 -
});
147 -
148 -
test.serial("Filtrar registros de humor apenas por data de fim", async (t) => {
149 -
const res = await request(app).get(`/mood/user/${userId}`)
150 -
.query({
151 -
end_date: '2024-01-31'
152 -
});
153 -
154 -
t.is(res.status, 200);
155 -
t.is(res.body.moods.length, 2); // Only January moods
156 -
});
157 -
158 -
test.serial("Paginação de moods", async (t) => {
159 -
const res = await request(app).get(`/mood/user/${userId}`)
160 -
.query({
161 -
page: 2,
162 -
limit: 2
163 -
});
164 -
165 -
t.is(res.status, 200);
166 -
t.is(res.body.moods.length, 2);
167 -
t.is(res.body.pagination.page, 2);
168 -
t.is(res.body.pagination.limit, 2);
169 -
t.is(res.body.pagination.total_pages, 3);
170 -
});
171 -
172 -
test.serial("Paginação com limite máximo de 100", async (t) => {
173 -
const res = await request(app).get(`/mood/user/${userId}`)
174 -
.query({
175 -
limit: 200
176 -
});
177 -
178 -
t.is(res.status, 200);
179 -
t.is(res.body.pagination.limit, 100); // Should be capped at 100
180 -
});
181 -
182 -
test.serial("Falha ao filtrar com intervalo de datas inválido", async (t) => {
183 -
const res = await request(app).get(`/mood/user/${userId}`)
184 -
.query({
185 -
start_date: '2024-02-01',
186 -
end_date: '2024-01-01' // End before start
187 -
});
188 -
189 -
t.is(res.status, 400);
190 -
t.is(res.body.error, "Intervalo de datas inválido");
191 -
});
192 -
193 -
test.serial("Falha ao filtrar com data de início inválida", async (t) => {
194 -
const res = await request(app).get(`/mood/user/${userId}`)
195 -
.query({
196 -
start_date: 'data-invalida'
197 -
});
198 -
199 -
t.is(res.status, 400);
200 -
t.is(res.body.error, "Data de início inválida");
201 -
});
202 -
203 -
test.serial("Falha ao filtrar com data de fim inválida", async (t) => {
204 -
const res = await request(app).get(`/mood/user/${userId}`)
205 -
.query({
206 -
end_date: 'data-invalida'
207 -
});
208 -
209 -
t.is(res.status, 400);
210 -
t.is(res.body.error, "Data de fim inválida");
211 -
});
212 -
213 -
test.serial("Obter estatísticas de mood do usuário", async (t) => {
214 -
const res = await request(app).get(`/mood/user/${userId}/stats`);
215 -
216 -
t.is(res.status, 200);
217 -
t.truthy(res.body.overall);
218 -
t.is(res.body.overall.total_entries, 5);
219 -
t.truthy(res.body.overall.avg_rating);
220 -
t.truthy(res.body.overall.avg_stress);
221 -
t.truthy(res.body.overall.avg_anxiety);
222 -
t.truthy(res.body.overall.avg_energy);
223 -
t.truthy(res.body.emotions);
224 -
t.truthy(res.body.trends);
225 -
});
226 -
227 -
test.serial("Estatísticas devem incluir frequência de emoções", async (t) => {
228 -
const res = await request(app).get(`/mood/user/${userId}/stats`);
229 -
230 -
t.is(res.status, 200);
231 -
t.true(Array.isArray(res.body.emotions));
232 -
233 -
// We created 3 moods with components
234 -
const joyStats = res.body.emotions.find(e => e.emotion === 'joy');
235 -
t.truthy(joyStats);
236 -
t.is(joyStats.frequency, 3);
237 -
});
238 -
239 -
test.serial("Estatísticas com filtro de data", async (t) => {
240 -
const res = await request(app).get(`/mood/user/${userId}/stats`)
241 -
.query({
242 -
start_date: '2024-01-01',
243 -
end_date: '2024-01-31'
244 -
});
245 -
246 -
t.is(res.status, 200);
247 -
t.is(res.body.overall.total_entries, 2); // Only January
248 -
t.is(res.body.date_range.start, '2024-01-01');
249 -
t.is(res.body.date_range.end, '2024-01-31');
250 -
});
251 -
252 -
test.serial("Estatísticas devem incluir tendências por dia da semana", async (t) => {
253 -
const res = await request(app).get(`/mood/user/${userId}/stats`);
254 -
255 -
t.is(res.status, 200);
256 -
t.true(Array.isArray(res.body.trends.by_day_of_week));
257 -
258 -
const hasDay = res.body.trends.by_day_of_week.some(d =>
259 -
['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'].includes(d.day_of_week)
260 -
);
261 -
t.true(hasDay);
262 -
});
263 -
264 -
test.serial("Usuário sem moods deve retornar lista vazia", async (t) => {
265 -
// Create another user without moods
266 -
const newUserRes = await request(app)
267 -
.post("/users")
268 -
.send({
269 -
email: "nomood@example.com",
270 -
password: "senha123",
271 -
first_name: "No",
272 -
last_name: "Mood"
273 -
});
274 -
275 -
const res = await request(app).get(`/mood/user/${newUserRes.body.id}`);
276 -
277 -
t.is(res.status, 200);
278 -
t.is(res.body.moods.length, 0);
279 -
t.is(res.body.pagination.total, 0);
280 -
});
281 -
282 -
test.serial("Estatísticas de usuário sem moods", async (t) => {
283 -
// Create another user without moods
284 -
const newUserRes = await request(app)
285 -
.post("/users")
286 -
.send({
287 -
email: "nostats@example.com",
288 -
password: "senha123",
289 -
first_name: "No",
290 -
last_name: "Stats"
291 -
});
292 -
293 -
const res = await request(app).get(`/mood/user/${newUserRes.body.id}/stats`);
294 -
295 -
t.is(res.status, 200);
296 -
t.is(res.body.overall.total_entries, 0);
297 -
t.is(res.body.emotions.length, 0);
298 -
});
api/tests/mood/updates.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "../test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
let userId;
9 -
let moodId;
10 -
11 -
test.before(() => {
12 -
db = setupTestDb();
13 -
app = createApp(db);
14 -
});
15 -
16 -
test.beforeEach(async () => {
17 -
cleanupTestDb();
18 -
19 -
// Create a test user with unique email
20 -
const uniqueEmail = `mood_${Date.now()}_${Math.random()}@example.com`;
21 -
const userRes = await request(app)
22 -
.post("/users")
23 -
.send({
24 -
email: uniqueEmail,
25 -
password: "senha123",
26 -
first_name: "Mood",
27 -
last_name: "Tester"
28 -
});
29 -
30 -
if (userRes.status !== 201) {
31 -
throw new Error(`Failed to create test user: ${JSON.stringify(userRes.body)}`);
32 -
}
33 -
34 -
userId = userRes.body.id;
35 -
36 -
// Create a mood to update
37 -
const moodRes = await request(app)
38 -
.post("/mood")
39 -
.send({
40 -
user_id: userId,
41 -
rating: 5,
42 -
stress_level: 4,
43 -
anxiety_level: 3,
44 -
energy_level: 7,
45 -
title: "Original mood",
46 -
description: "Original description",
47 -
recorded_at: new Date().toISOString(),
48 -
mood_components: [
49 -
{ emotion: "joy", intensity: 6 },
50 -
{ emotion: "trust", intensity: 7 }
51 -
]
52 -
});
53 -
54 -
moodId = moodRes.body.id;
55 -
});
56 -
57 -
test.serial("Atualizar rating do mood", async (t) => {
58 -
const res = await request(app)
59 -
.put(`/mood/${moodId}`)
60 -
.send({
61 -
rating: 8
62 -
});
63 -
64 -
t.is(res.status, 200);
65 -
t.true(res.body.success);
66 -
67 -
// Verify update
68 -
const mood = db.prepare("SELECT rating FROM mood WHERE id = ?").get(moodId);
69 -
t.is(mood.rating, 8);
70 -
});
71 -
72 -
test.serial("Atualizar múltiplos níveis do mood", async (t) => {
73 -
const res = await request(app)
74 -
.put(`/mood/${moodId}`)
75 -
.send({
76 -
stress_level: 2,
77 -
anxiety_level: 1,
78 -
energy_level: 9
79 -
});
80 -
81 -
t.is(res.status, 200);
82 -
t.true(res.body.success);
83 -
84 -
// Verify updates
85 -
const mood = db.prepare("SELECT stress_level, anxiety_level, energy_level FROM mood WHERE id = ?").get(moodId);
86 -
t.is(mood.stress_level, 2);
87 -
t.is(mood.anxiety_level, 1);
88 -
t.is(mood.energy_level, 9);
89 -
});
90 -
91 -
test.serial("Atualizar título e descrição do mood", async (t) => {
92 -
const res = await request(app)
93 -
.put(`/mood/${moodId}`)
94 -
.send({
95 -
title: "Novo título",
96 -
description: "Nova descrição detalhada"
97 -
});
98 -
99 -
t.is(res.status, 200);
100 -
t.true(res.body.success);
101 -
102 -
// Verify updates
103 -
const mood = db.prepare("SELECT title, description FROM mood WHERE id = ?").get(moodId);
104 -
t.is(mood.title, "Novo título");
105 -
t.is(mood.description, "Nova descrição detalhada");
106 -
});
107 -
108 -
test.serial("Atualizar data do mood", async (t) => {
109 -
const newDate = new Date('2024-01-15T10:00:00Z');
110 -
111 -
const res = await request(app)
112 -
.put(`/mood/${moodId}`)
113 -
.send({
114 -
recorded_at: newDate.toISOString()
115 -
});
116 -
117 -
t.is(res.status, 200);
118 -
t.true(res.body.success);
119 -
120 -
// Verify update
121 -
const mood = db.prepare("SELECT recorded_at FROM mood WHERE id = ?").get(moodId);
122 -
t.truthy(mood.recorded_at.includes('2024-01-15'));
123 -
});
124 -
125 -
test.serial("Atualizar componentes emocionais do mood", async (t) => {
126 -
const res = await request(app)
127 -
.put(`/mood/${moodId}`)
128 -
.send({
129 -
mood_components: [
130 -
{ emotion: "sad", intensity: 4 },
131 -
{ emotion: "fear", intensity: 3 },
132 -
{ emotion: "angry", intensity: 2 }
133 -
]
134 -
});
135 -
136 -
t.is(res.status, 200);
137 -
t.true(res.body.success);
138 -
139 -
// Verify old components were replaced
140 -
const components = db.prepare("SELECT emotion, intensity FROM mood_components WHERE mood_id = ? ORDER BY emotion").all(moodId);
141 -
t.is(components.length, 3);
142 -
143 -
const emotions = components.map(c => c.emotion);
144 -
t.true(emotions.includes('sad'));
145 -
t.true(emotions.includes('fear'));
146 -
t.true(emotions.includes('angry'));
147 -
t.false(emotions.includes('joy')); // Old emotion should be gone
148 -
t.false(emotions.includes('trust')); // Old emotion should be gone
149 -
});
150 -
151 -
test.serial("Remover todos os componentes emocionais enviando array vazio", async (t) => {
152 -
const res = await request(app)
153 -
.put(`/mood/${moodId}`)
154 -
.send({
155 -
mood_components: []
156 -
});
157 -
158 -
t.is(res.status, 200);
159 -
t.true(res.body.success);
160 -
161 -
// Verify components were deleted
162 -
const components = db.prepare("SELECT * FROM mood_components WHERE mood_id = ?").all(moodId);
163 -
t.is(components.length, 0);
164 -
});
165 -
166 -
test.serial("Atualização deve modificar a coluna de atualização", async (t) => {
167 -
// Get original updated_at
168 -
const originalMood = db.prepare("SELECT updated_at FROM mood WHERE id = ?")
169 -
.get(moodId);
170 -
171 -
// Wait a bit to ensure timestamp difference
172 -
await new Promise(resolve => setTimeout(resolve, 1100));
173 -
174 -
const res = await request(app)
175 -
.put(`/mood/${moodId}`)
176 -
.send({
177 -
rating: 9
178 -
});
179 -
180 -
t.is(res.status, 200);
181 -
182 -
// Verify updated_at changed
183 -
const updatedMood = db.prepare("SELECT updated_at FROM mood WHERE id = ?")
184 -
.get(moodId);
185 -
186 -
t.not(updatedMood.updated_at, originalMood.updated_at);
187 -
});
188 -
189 -
test.serial("Falha ao atualizar humor inexistente", async (t) => {
190 -
const res = await request(app)
191 -
.put("/mood/99999")
192 -
.send({
193 -
rating: 8
194 -
});
195 -
196 -
t.is(res.status, 404);
197 -
t.is(res.body.error, "Humor não encontrado");
198 -
});
199 -
200 -
test.serial("Falha ao atualizar com avaliação inválida", async (t) => {
201 -
const res = await request(app)
202 -
.put(`/mood/${moodId}`)
203 -
.send({
204 -
rating: 15
205 -
});
206 -
207 -
t.is(res.status, 400);
208 -
t.is(res.body.error, "rating deve ser entre 1 e 10");
209 -
});
210 -
211 -
test.serial("Falha ao atualizar com nível de estresse inválido", async (t) => {
212 -
const res = await request(app)
213 -
.put(`/mood/${moodId}`)
214 -
.send({
215 -
stress_level: 0
216 -
});
217 -
218 -
t.is(res.status, 400);
219 -
t.is(res.body.error, "stress_level deve ser entre 1 e 10");
220 -
});
221 -
222 -
test.serial("Falha ao atualizar com nível de ansiedade inválido", async (t) => {
223 -
const res = await request(app)
224 -
.put(`/mood/${moodId}`)
225 -
.send({
226 -
anxiety_level: 11
227 -
});
228 -
229 -
t.is(res.status, 400);
230 -
t.is(res.body.error, "anxiety_level deve ser entre 1 e 10");
231 -
});
232 -
233 -
test.serial("Falha ao atualizar com nível de energia inválida", async (t) => {
234 -
const res = await request(app)
235 -
.put(`/mood/${moodId}`)
236 -
.send({
237 -
energy_level: -1
238 -
});
239 -
240 -
t.is(res.status, 400);
241 -
t.is(res.body.error, "energy_level deve ser entre 1 e 10");
242 -
});
243 -
244 -
test.serial("Falha ao atualizar com data inválida", async (t) => {
245 -
const res = await request(app)
246 -
.put(`/mood/${moodId}`)
247 -
.send({
248 -
recorded_at: "data-invalida"
249 -
});
250 -
251 -
t.is(res.status, 400);
252 -
t.is(res.body.error, "recorded_at deve ser uma data válida");
253 -
});
254 -
255 -
test.serial("Falha ao atualizar com data no futuro", async (t) => {
256 -
const futureDate = new Date();
257 -
futureDate.setDate(futureDate.getDate() + 1);
258 -
259 -
const res = await request(app)
260 -
.put(`/mood/${moodId}`)
261 -
.send({
262 -
recorded_at: futureDate.toISOString()
263 -
});
264 -
265 -
t.is(res.status, 400);
266 -
t.is(res.body.error, "recorded_at não pode ser no futuro");
267 -
});
268 -
269 -
test.serial("Falha ao atualizar com emoção inválida nos componentes", async (t) => {
270 -
const res = await request(app)
271 -
.put(`/mood/${moodId}`)
272 -
.send({
273 -
mood_components: [
274 -
{ emotion: "invalid", intensity: 5 }
275 -
]
276 -
});
277 -
278 -
t.is(res.status, 400);
279 -
t.regex(res.body.error, /Invalid emotion/);
280 -
});
281 -
282 -
test.serial("Falha ao atualizar com emoções duplicadas", async (t) => {
283 -
const res = await request(app)
284 -
.put(`/mood/${moodId}`)
285 -
.send({
286 -
mood_components: [
287 -
{ emotion: "joy", intensity: 5 },
288 -
{ emotion: "joy", intensity: 7 }
289 -
]
290 -
});
291 -
292 -
t.is(res.status, 400);
293 -
t.regex(res.body.error, /Duplicate emotion/);
294 -
});
295 -
296 -
test.serial("Deletar humor existente", async (t) => {
297 -
const res = await request(app).delete(`/mood/${moodId}`);
298 -
299 -
t.is(res.status, 200);
300 -
t.true(res.body.success);
301 -
t.is(Number(res.body.deleted), Number(moodId));
302 -
303 -
// Verify mood is deleted
304 -
const mood = db.prepare("SELECT * FROM mood WHERE id = ?").get(moodId);
305 -
t.falsy(mood);
306 -
});
307 -
308 -
test.serial("Deletar humor deve deletar seus componentes (em cascata)", async (t) => {
309 -
// Verify components exist
310 -
const componentsBefore = db.prepare("SELECT * FROM mood_components WHERE mood_id = ?").all(moodId);
311 -
t.true(componentsBefore.length > 0);
312 -
313 -
const res = await request(app).delete(`/mood/${moodId}`);
314 -
t.is(res.status, 200);
315 -
316 -
// Verify components are deleted
317 -
const componentsAfter = db.prepare("SELECT * FROM mood_components WHERE mood_id = ?").all(moodId);
318 -
t.is(componentsAfter.length, 0);
319 -
});
320 -
321 -
test.serial("Falha ao deletar mood inexistente", async (t) => {
322 -
const res = await request(app).delete("/mood/99999");
323 -
324 -
t.is(res.status, 404);
325 -
t.is(res.body.error, "Humor não encontrado");
326 -
});
327 -
328 -
test.serial("Atualização parcial mantém valores não alterados", async (t) => {
329 -
// Get original values
330 -
const originalMood = db.prepare("SELECT * FROM mood WHERE id = ?").get(moodId);
331 -
332 -
// Update only rating
333 -
const res = await request(app)
334 -
.put(`/mood/${moodId}`)
335 -
.send({
336 -
rating: 10
337 -
});
338 -
339 -
t.is(res.status, 200);
340 -
341 -
// Verify only rating changed, others remained
342 -
const updatedMood = db.prepare("SELECT * FROM mood WHERE id = ?").get(moodId);
343 -
t.is(updatedMood.rating, 10);
344 -
t.is(updatedMood.stress_level, originalMood.stress_level);
345 -
t.is(updatedMood.anxiety_level, originalMood.anxiety_level);
346 -
t.is(updatedMood.energy_level, originalMood.energy_level);
347 -
t.is(updatedMood.title, originalMood.title);
348 -
t.is(updatedMood.description, originalMood.description);
349 -
});
api/tests/test-helper.js → /dev/null
1 -
import { setupTestDatabase } from '../src/setup-db.js';
2 -
3 -
// Store a single test database instance
4 -
let globalTestDb = null;
5 -
6 -
// Setup the test database
7 -
export function setupTestDb() {
8 -
if (!globalTestDb) {
9 -
globalTestDb = setupTestDatabase();
10 -
}
11 -
return globalTestDb;
12 -
}
13 -
14 -
// Get the test database
15 -
export function getTestDb() {
16 -
return globalTestDb;
17 -
}
18 -
19 -
// Cleanup test database
20 -
export function cleanupTestDb() {
21 -
if (globalTestDb) {
22 -
try {
23 -
// Delete in correct order due to foreign keys
24 -
globalTestDb.exec(`
25 -
DELETE FROM mood_components;
26 -
DELETE FROM mood;
27 -
DELETE FROM users;
28 -
`);
29 -
} catch (err) {
30 -
console.error('Error cleaning test DB:', err);
31 -
}
32 -
}
33 -
}
/dev/null → api/tests/test-helper.ts
1 +
import { PrismaClient } from '@prisma/client';
2 +
import { PrismaPg } from '@prisma/adapter-pg';
3 +
import 'dotenv/config';
4 +
5 +
let prismaTestClient: PrismaClient | null = null;
6 +
7 +
export function getTestPrisma(): PrismaClient {
8 +
if (!prismaTestClient) {
9 +
// Use test database URL
10 +
const connectionString = process.env.DATABASE_URL || 'postgres://user:password@localhost:5430/orbit_test';
11 +
const adapter = new PrismaPg({ connectionString });
12 +
prismaTestClient = new PrismaClient({ adapter });
13 +
}
14 +
return prismaTestClient;
15 +
}
16 +
17 +
export async function cleanupTestDb() {
18 +
const prisma = getTestPrisma();
19 +
20 +
// Delete in correct order due to foreign keys
21 +
// Add more tables as they're added to schema
22 +
try {
23 +
// When we add more models, delete them here in reverse order of dependencies
24 +
await prisma.user.deleteMany({});
25 +
} catch (err) {
26 +
console.error('Error cleaning test DB:', err);
27 +
}
28 +
}
29 +
30 +
export async function disconnectTestDb() {
31 +
if (prismaTestClient) {
32 +
await prismaTestClient.$disconnect();
33 +
prismaTestClient = null;
34 +
}
35 +
}
36 +
37 +
// Helper to create test users
38 +
export async function createTestUser(data?: {
39 +
email?: string;
40 +
firstName?: string;
41 +
lastName?: string;
42 +
encryptedPassword?: string;
43 +
}) {
44 +
const prisma = getTestPrisma();
45 +
return await prisma.user.create({
46 +
data: {
47 +
email: data?.email || 'test@example.com',
48 +
firstName: data?.firstName || 'Test',
49 +
lastName: data?.lastName || 'User',
50 +
encryptedPassword: data?.encryptedPassword || '$2a$10$test'
51 +
}
52 +
});
53 +
}api/tests/users.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "./test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
9 -
test.before(() => {
10 -
db = setupTestDb();
11 -
app = createApp(db);
12 -
});
13 -
14 -
test.beforeEach(() => {
15 -
cleanupTestDb();
16 -
});
17 -
18 -
test("Criar usuário", async (t) => {
19 -
const res = await request(app)
20 -
.post("/users")
21 -
.send({
22 -
email: "john@example.com",
23 -
password: "123456",
24 -
first_name: "John",
25 -
last_name: "Doe",
26 -
});
27 -
28 -
t.is(res.status, 201);
29 -
t.truthy(res.body.id);
30 -
});
31 -
32 -
test("Falha ao criar usuário sem email", async (t) => {
33 -
const res = await request(app)
34 -
.post("/users")
35 -
.send({
36 -
password: "123456",
37 -
first_name: "John",
38 -
last_name: "Doe",
39 -
});
40 -
41 -
t.is(res.status, 400);
42 -
t.is(res.body.error, "Campos faltantes");
43 -
});
44 -
45 -
test("Falha ao criar usuário com email duplicado", async (t) => {
46 -
// First user
47 -
await request(app)
48 -
.post("/users")
49 -
.send({
50 -
email: "duplicate@example.com",
51 -
password: "123456",
52 -
first_name: "John",
53 -
last_name: "Doe",
54 -
});
55 -
56 -
// Duplicate email
57 -
const res = await request(app)
58 -
.post("/users")
59 -
.send({
60 -
email: "duplicate@example.com",
61 -
password: "123456",
62 -
first_name: "Jane",
63 -
last_name: "Smith",
64 -
});
65 -
66 -
t.is(res.status, 400);
67 -
t.is(res.body.error, "Email já cadastrado");
68 -
});
api/tests/users/authentication.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import bcrypt from "bcryptjs";
4 -
import { createApp } from "../../src/create-app.js";
5 -
import { setupTestDb, cleanupTestDb } from "../test-helper.js";
6 -
7 -
let app;
8 -
let db;
9 -
10 -
test.before(() => {
11 -
db = setupTestDb();
12 -
app = createApp(db);
13 -
});
14 -
15 -
test.beforeEach(() => {
16 -
cleanupTestDb();
17 -
18 -
// Create a test user for login tests
19 -
const hashedPassword = bcrypt.hashSync("senha123", 10);
20 -
db.prepare(`
21 -
INSERT INTO users (email, password, first_name, last_name, timezone)
22 -
VALUES (?, ?, ?, ?, ?)
23 -
`).run("teste@example.com", hashedPassword, "Teste", "User", "UTC");
24 -
});
25 -
26 -
test("Login bem-sucedido com credenciais corretas", async (t) => {
27 -
const res = await request(app)
28 -
.post("/users/login")
29 -
.send({
30 -
email: "teste@example.com",
31 -
password: "senha123"
32 -
});
33 -
34 -
t.is(res.status, 200);
35 -
t.true(res.body.success);
36 -
t.truthy(res.body.user);
37 -
t.is(res.body.user.email, "teste@example.com");
38 -
t.is(res.body.user.first_name, "Teste");
39 -
t.is(res.body.user.last_name, "User");
40 -
t.falsy(res.body.user.password); // Password should not be in response
41 -
});
42 -
43 -
test("Login com email em maiúsculas deve funcionar", async (t) => {
44 -
const res = await request(app)
45 -
.post("/users/login")
46 -
.send({
47 -
email: "TESTE@EXAMPLE.COM",
48 -
password: "senha123"
49 -
});
50 -
51 -
t.is(res.status, 200);
52 -
t.true(res.body.success);
53 -
});
54 -
55 -
test("Falha no login com senha incorreta", async (t) => {
56 -
const res = await request(app)
57 -
.post("/users/login")
58 -
.send({
59 -
email: "teste@example.com",
60 -
password: "senhaerrada"
61 -
});
62 -
63 -
t.is(res.status, 401);
64 -
t.is(res.body.error, "Credenciais inválidas");
65 -
});
66 -
67 -
test("Falha no login com email não cadastrado", async (t) => {
68 -
const res = await request(app)
69 -
.post("/users/login")
70 -
.send({
71 -
email: "naocadastrado@example.com",
72 -
password: "senha123"
73 -
});
74 -
75 -
t.is(res.status, 401);
76 -
t.is(res.body.error, "Credenciais inválidas");
77 -
});
78 -
79 -
test("Falha no login sem email", async (t) => {
80 -
const res = await request(app)
81 -
.post("/users/login")
82 -
.send({
83 -
password: "senha123"
84 -
});
85 -
86 -
t.is(res.status, 400);
87 -
t.is(res.body.error, "Email e senha são obrigatórios");
88 -
});
89 -
90 -
test("Falha no login sem senha", async (t) => {
91 -
const res = await request(app)
92 -
.post("/users/login")
93 -
.send({
94 -
email: "teste@example.com"
95 -
});
96 -
97 -
t.is(res.status, 400);
98 -
t.is(res.body.error, "Email e senha são obrigatórios");
99 -
});
100 -
101 -
test("Falha no login sem credenciais", async (t) => {
102 -
const res = await request(app)
103 -
.post("/users/login")
104 -
.send({});
105 -
106 -
t.is(res.status, 400);
107 -
t.is(res.body.error, "Email e senha são obrigatórios");
108 -
});
109 -
110 -
test("Login não deve retornar a senha do usuário", async (t) => {
111 -
const res = await request(app)
112 -
.post("/users/login")
113 -
.send({
114 -
email: "teste@example.com",
115 -
password: "senha123"
116 -
});
117 -
118 -
t.is(res.status, 200);
119 -
t.falsy(res.body.user.password);
120 -
t.is(typeof res.body.user.password, 'undefined');
121 -
});
122 -
123 -
test("Login deve retornar informações completas do usuário", async (t) => {
124 -
const res = await request(app)
125 -
.post("/users/login")
126 -
.send({
127 -
email: "teste@example.com",
128 -
password: "senha123"
129 -
});
130 -
131 -
t.is(res.status, 200);
132 -
t.truthy(res.body.user.id);
133 -
t.is(res.body.user.email, "teste@example.com");
134 -
t.is(res.body.user.first_name, "Teste");
135 -
t.is(res.body.user.last_name, "User");
136 -
t.is(res.body.user.timezone, "UTC");
137 -
});
138 -
139 -
test("Login com espaços em branco deve ser tratado corretamente", async (t) => {
140 -
const res = await request(app)
141 -
.post("/users/login")
142 -
.send({
143 -
email: " teste@example.com ",
144 -
password: "senha123"
145 -
});
146 -
147 -
t.is(res.status, 401); // Should fail as email with spaces doesn't match
148 -
});api/tests/users/creation.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "../test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
9 -
test.before(() => {
10 -
db = setupTestDb();
11 -
app = createApp(db);
12 -
});
13 -
14 -
test.beforeEach(() => {
15 -
cleanupTestDb();
16 -
});
17 -
18 -
test("Criar usuário com todos os campos válidos", async (t) => {
19 -
const res = await request(app)
20 -
.post("/users")
21 -
.send({
22 -
email: "usuario@example.com",
23 -
password: "senha123",
24 -
first_name: "João",
25 -
last_name: "Silva",
26 -
timezone: "America/Sao_Paulo"
27 -
});
28 -
29 -
t.is(res.status, 201);
30 -
t.truthy(res.body.id);
31 -
});
32 -
33 -
test("Criar usuário com timezone padrão (UTC)", async (t) => {
34 -
const res = await request(app)
35 -
.post("/users")
36 -
.send({
37 -
email: "utc@example.com",
38 -
password: "senha123",
39 -
first_name: "Maria",
40 -
last_name: "Santos"
41 -
});
42 -
43 -
t.is(res.status, 201);
44 -
45 -
// Verify timezone was set to UTC
46 -
const user = db.prepare("SELECT timezone FROM users WHERE id = ?").get(res.body.id);
47 -
t.is(user.timezone, 'UTC');
48 -
});
49 -
50 -
test("Falha ao criar usuário sem email", async (t) => {
51 -
const res = await request(app)
52 -
.post("/users")
53 -
.send({
54 -
password: "senha123",
55 -
first_name: "João",
56 -
last_name: "Silva"
57 -
});
58 -
59 -
t.is(res.status, 400);
60 -
t.is(res.body.error, "Campos faltantes");
61 -
t.true(res.body.missing.includes('email'));
62 -
});
63 -
64 -
test("Falha ao criar usuário sem senha", async (t) => {
65 -
const res = await request(app)
66 -
.post("/users")
67 -
.send({
68 -
email: "usuario@example.com",
69 -
first_name: "João",
70 -
last_name: "Silva"
71 -
});
72 -
73 -
t.is(res.status, 400);
74 -
t.is(res.body.error, "Campos faltantes");
75 -
t.true(res.body.missing.includes('password'));
76 -
});
77 -
78 -
test("Falha ao criar usuário sem primeiro nome", async (t) => {
79 -
const res = await request(app)
80 -
.post("/users")
81 -
.send({
82 -
email: "usuario@example.com",
83 -
password: "senha123",
84 -
last_name: "Silva"
85 -
});
86 -
87 -
t.is(res.status, 400);
88 -
t.is(res.body.error, "Campos faltantes");
89 -
t.true(res.body.missing.includes('first_name'));
90 -
});
91 -
92 -
test("Falha ao criar usuário sem último nome", async (t) => {
93 -
const res = await request(app)
94 -
.post("/users")
95 -
.send({
96 -
email: "usuario@example.com",
97 -
password: "senha123",
98 -
first_name: "João"
99 -
});
100 -
101 -
t.is(res.status, 400);
102 -
t.is(res.body.error, "Campos faltantes");
103 -
t.true(res.body.missing.includes('last_name'));
104 -
});
105 -
106 -
test("Falha ao criar usuário com múltiplos campos faltantes", async (t) => {
107 -
const res = await request(app)
108 -
.post("/users")
109 -
.send({
110 -
first_name: "João"
111 -
});
112 -
113 -
t.is(res.status, 400);
114 -
t.is(res.body.error, "Campos faltantes");
115 -
t.true(res.body.missing.includes('email'));
116 -
t.true(res.body.missing.includes('password'));
117 -
t.true(res.body.missing.includes('last_name'));
118 -
});
119 -
120 -
test("Falha ao criar usuário com email inválido (sem @)", async (t) => {
121 -
const res = await request(app)
122 -
.post("/users")
123 -
.send({
124 -
email: "emailinvalido",
125 -
password: "senha123",
126 -
first_name: "João",
127 -
last_name: "Silva"
128 -
});
129 -
130 -
t.is(res.status, 400);
131 -
t.is(res.body.error, "Email inválido");
132 -
});
133 -
134 -
test("Falha ao criar usuário com email inválido (sem domínio)", async (t) => {
135 -
const res = await request(app)
136 -
.post("/users")
137 -
.send({
138 -
email: "usuario@",
139 -
password: "senha123",
140 -
first_name: "João",
141 -
last_name: "Silva"
142 -
});
143 -
144 -
t.is(res.status, 400);
145 -
t.is(res.body.error, "Email inválido");
146 -
});
147 -
148 -
test("Falha ao criar usuário com email inválido (formato incorreto)", async (t) => {
149 -
const res = await request(app)
150 -
.post("/users")
151 -
.send({
152 -
email: "@example.com",
153 -
password: "senha123",
154 -
first_name: "João",
155 -
last_name: "Silva"
156 -
});
157 -
158 -
t.is(res.status, 400);
159 -
t.is(res.body.error, "Email inválido");
160 -
});
161 -
162 -
test("Falha ao criar usuário com senha muito curta (menos de 6 caracteres)", async (t) => {
163 -
const res = await request(app)
164 -
.post("/users")
165 -
.send({
166 -
email: "usuario@example.com",
167 -
password: "123",
168 -
first_name: "João",
169 -
last_name: "Silva"
170 -
});
171 -
172 -
t.is(res.status, 400);
173 -
t.is(res.body.error, "Senha deve ter pelo menos 6 caracteres");
174 -
});
175 -
176 -
test("Falha ao criar usuário com senha vazia", async (t) => {
177 -
const res = await request(app)
178 -
.post("/users")
179 -
.send({
180 -
email: "usuario@example.com",
181 -
password: "",
182 -
first_name: "João",
183 -
last_name: "Silva"
184 -
});
185 -
186 -
t.is(res.status, 400);
187 -
t.is(res.body.error, "Campos faltantes");
188 -
});
189 -
190 -
test("Falha ao criar usuário com email duplicado", async (t) => {
191 -
// Create first user
192 -
await request(app)
193 -
.post("/users")
194 -
.send({
195 -
email: "duplicado@example.com",
196 -
password: "senha123",
197 -
first_name: "João",
198 -
last_name: "Silva"
199 -
});
200 -
201 -
// Try to create with same email
202 -
const res = await request(app)
203 -
.post("/users")
204 -
.send({
205 -
email: "duplicado@example.com",
206 -
password: "outrasenha",
207 -
first_name: "Maria",
208 -
last_name: "Santos"
209 -
});
210 -
211 -
t.is(res.status, 400);
212 -
t.is(res.body.error, "Email já cadastrado");
213 -
});
214 -
215 -
test("Email deve ser case-insensitive para duplicação", async (t) => {
216 -
// Create with lowercase
217 -
await request(app)
218 -
.post("/users")
219 -
.send({
220 -
email: "usuario@example.com",
221 -
password: "senha123",
222 -
first_name: "João",
223 -
last_name: "Silva"
224 -
});
225 -
226 -
// Try with uppercase
227 -
const res = await request(app)
228 -
.post("/users")
229 -
.send({
230 -
email: "USUARIO@EXAMPLE.COM",
231 -
password: "senha123",
232 -
first_name: "Maria",
233 -
last_name: "Santos"
234 -
});
235 -
236 -
t.is(res.status, 400);
237 -
t.is(res.body.error, "Email já cadastrado");
238 -
});
239 -
240 -
test("Sanitização de strings longas no nome", async (t) => {
241 -
const longName = "A".repeat(600); // 600 characters
242 -
243 -
const res = await request(app)
244 -
.post("/users")
245 -
.send({
246 -
email: "longname@example.com",
247 -
password: "senha123",
248 -
first_name: longName,
249 -
last_name: longName
250 -
});
251 -
252 -
t.is(res.status, 201);
253 -
254 -
// Check that name was truncated to 500 chars
255 -
const user = db.prepare("SELECT first_name, last_name FROM users WHERE id = ?").get(res.body.id);
256 -
t.is(user.first_name.length, 500);
257 -
t.is(user.last_name.length, 500);
258 -
});api/tests/users/profile.test.js → /dev/null
1 -
import test from "ava";
2 -
import request from "supertest";
3 -
import { createApp } from "../../src/create-app.js";
4 -
import { setupTestDb, cleanupTestDb } from "../test-helper.js";
5 -
6 -
let app;
7 -
let db;
8 -
let userId;
9 -
10 -
test.before(() => {
11 -
db = setupTestDb();
12 -
app = createApp(db);
13 -
});
14 -
15 -
let testEmail;
16 -
17 -
test.serial.beforeEach(async () => {
18 -
cleanupTestDb();
19 -
20 -
// Create a test user with unique email
21 -
testEmail = `perfil_${Date.now()}_${Math.random()}@example.com`;
22 -
const res = await request(app)
23 -
.post("/users")
24 -
.send({
25 -
email: testEmail,
26 -
password: "senha123",
27 -
first_name: "Perfil",
28 -
last_name: "Teste",
29 -
timezone: "America/Sao_Paulo"
30 -
});
31 -
32 -
if (res.status !== 201) {
33 -
throw new Error(`Failed to create test user: ${JSON.stringify(res.body)}`);
34 -
}
35 -
36 -
userId = res.body.id;
37 -
});
38 -
39 -
test.serial("Obter perfil de usuário existente", async (t) => {
40 -
const res = await request(app).get(`/users/${userId}`);
41 -
42 -
t.is(res.status, 200);
43 -
t.is(Number(res.body.id), Number(userId));
44 -
t.is(res.body.email, testEmail);
45 -
t.is(res.body.first_name, "Perfil");
46 -
t.is(res.body.last_name, "Teste");
47 -
t.is(res.body.timezone, "America/Sao_Paulo");
48 -
t.truthy(res.body.created_at);
49 -
t.truthy(res.body.updated_at);
50 -
t.is(typeof res.body.total_moods, 'number');
51 -
t.falsy(res.body.password); // Should not include password
52 -
});
53 -
54 -
test.serial("Perfil deve incluir contagem de registros de humor", async (t) => {
55 -
// Add some moods
56 -
const now = new Date().toISOString();
57 -
58 -
await db.prepare(`
59 -
INSERT INTO mood (user_id, rating, stress_level, anxiety_level, energy_level, recorded_at)
60 -
VALUES (?, ?, ?, ?, ?, ?)
61 -
`).run(userId, 7, 3, 4, 8, now);
62 -
63 -
await db.prepare(`
64 -
INSERT INTO mood (user_id, rating, stress_level, anxiety_level, energy_level, recorded_at)
65 -
VALUES (?, ?, ?, ?, ?, ?)
66 -
`).run(userId, 5, 6, 7, 4, now);
67 -
68 -
const res = await request(app).get(`/users/${userId}`);
69 -
70 -
t.is(res.status, 200);
71 -
t.is(res.body.total_moods, 2);
72 -
});
73 -
74 -
test.serial("Falha ao obter perfil de usuário inexistente", async (t) => {
75 -
const res = await request(app).get("/users/99999");
76 -
77 -
t.is(res.status, 404);
78 -
t.is(res.body.error, "Usuário não encontrado");
79 -
});
80 -
81 -
test.serial("Atualizar email do usuário", async (t) => {
82 -
const res = await request(app)
83 -
.put(`/users/${userId}`)
84 -
.send({
85 -
email: "novoemail@example.com"
86 -
});
87 -
88 -
t.is(res.status, 200);
89 -
t.true(res.body.success);
90 -
91 -
// Verify update
92 -
const user = db.prepare("SELECT email FROM users WHERE id = ?").get(userId);
93 -
t.is(user.email, "novoemail@example.com");
94 -
});
95 -
96 -
test.serial("Atualizar senha do usuário", async (t) => {
97 -
const res = await request(app)
98 -
.put(`/users/${userId}`)
99 -
.send({
100 -
password: "novasenha123"
101 -
});
102 -
103 -
t.is(res.status, 200);
104 -
t.true(res.body.success);
105 -
106 -
// Verify can login with new password
107 -
const loginRes = await request(app)
108 -
.post("/users/login")
109 -
.send({
110 -
email: testEmail,
111 -
password: "novasenha123"
112 -
});
113 -
114 -
t.is(loginRes.status, 200);
115 -
});
116 -
117 -
test.serial("Atualizar múltiplos campos do usuário", async (t) => {
118 -
const res = await request(app)
119 -
.put(`/users/${userId}`)
120 -
.send({
121 -
first_name: "NovoNome",
122 -
last_name: "NovoSobrenome",
123 -
timezone: "Europe/London"
124 -
});
125 -
126 -
t.is(res.status, 200);
127 -
t.true(res.body.success);
128 -
129 -
// Verify updates
130 -
const user = db.prepare("SELECT * FROM users WHERE id = ?").get(userId);
131 -
t.is(user.first_name, "NovoNome");
132 -
t.is(user.last_name, "NovoSobrenome");
133 -
t.is(user.timezone, "Europe/London");
134 -
});
135 -
136 -
test.serial("Falha ao atualizar com email inválido", async (t) => {
137 -
const res = await request(app)
138 -
.put(`/users/${userId}`)
139 -
.send({
140 -
email: "emailinvalido"
141 -
});
142 -
143 -
t.is(res.status, 400);
144 -
t.is(res.body.error, "Email inválido");
145 -
});
146 -
147 -
test.serial("Falha ao atualizar com senha muito curta", async (t) => {
148 -
const res = await request(app)
149 -
.put(`/users/${userId}`)
150 -
.send({
151 -
password: "123"
152 -
});
153 -
154 -
t.is(res.status, 400);
155 -
t.is(res.body.error, "Senha deve ter pelo menos 6 caracteres");
156 -
});
157 -
158 -
test.serial("Falha ao atualizar email para um já existente", async (t) => {
159 -
// Create another user
160 -
await request(app)
161 -
.post("/users")
162 -
.send({
163 -
email: "outro@example.com",
164 -
password: "senha123",
165 -
first_name: "Outro",
166 -
last_name: "Usuario"
167 -
});
168 -
169 -
// Try to update to existing email
170 -
const res = await request(app)
171 -
.put(`/users/${userId}`)
172 -
.send({
173 -
email: "outro@example.com"
174 -
});
175 -
176 -
t.is(res.status, 400);
177 -
t.is(res.body.error, "Email já está em uso");
178 -
});
179 -
180 -
test.serial("Falha ao atualizar usuário inexistente", async (t) => {
181 -
const res = await request(app)
182 -
.put("/users/99999")
183 -
.send({
184 -
first_name: "Novo"
185 -
});
186 -
187 -
t.is(res.status, 404);
188 -
t.is(res.body.error, "Usuário não encontrado");
189 -
});
190 -
191 -
test.serial("Falha ao atualizar sem campos", async (t) => {
192 -
const res = await request(app)
193 -
.put(`/users/${userId}`)
194 -
.send({});
195 -
196 -
t.is(res.status, 400);
197 -
t.is(res.body.error, "Nenhum campo para atualizar");
198 -
});
199 -
200 -
test.serial("Deletar usuário existente", async (t) => {
201 -
const res = await request(app).delete(`/users/${userId}`);
202 -
203 -
t.is(res.status, 200);
204 -
t.true(res.body.success);
205 -
t.is(Number(res.body.deleted), Number(userId));
206 -
207 -
// Verify user is deleted
208 -
const user = db.prepare("SELECT * FROM users WHERE id = ?").get(userId);
209 -
t.falsy(user);
210 -
});
211 -
212 -
test.serial("Deletar usuário deve deletar seus registros de humores (em cascata)", async (t) => {
213 -
// Add a mood
214 -
const now = new Date().toISOString();
215 -
const moodResult = db.prepare(`
216 -
INSERT INTO mood (user_id, rating, stress_level, anxiety_level, energy_level, recorded_at)
217 -
VALUES (?, ?, ?, ?, ?, ?)
218 -
`).run(userId, 7, 3, 4, 8, now);
219 -
220 -
const moodId = moodResult.lastInsertRowid;
221 -
222 -
// Add mood components
223 -
db.prepare(`
224 -
INSERT INTO mood_components (mood_id, emotion, intensity)
225 -
VALUES (?, ?, ?)
226 -
`).run(moodId, 'joy', 8);
227 -
228 -
// Delete user
229 -
const res = await request(app).delete(`/users/${userId}`);
230 -
t.is(res.status, 200);
231 -
232 -
// Verify moods are deleted
233 -
const mood = db.prepare("SELECT * FROM mood WHERE user_id = ?").get(userId);
234 -
t.falsy(mood);
235 -
236 -
// Verify mood components are deleted
237 -
const component = db.prepare("SELECT * FROM mood_components WHERE mood_id = ?").get(moodId);
238 -
t.falsy(component);
239 -
});
240 -
241 -
test.serial("Falha ao deletar usuário inexistente", async (t) => {
242 -
const res = await request(app).delete("/users/99999");
243 -
244 -
t.is(res.status, 404);
245 -
t.is(res.body.error, "Usuário não encontrado");
246 -
});