mnfst 0.5.272 → 0.5.274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/manifest.appwrite.data.js +41 -285
- package/lib/manifest.components.js +18 -0
- package/lib/manifest.data.js +240 -133
- package/lib/manifest.integrity.json +4 -4
- package/lib/manifest.sw.js +1 -1
- package/package.json +3 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
(function () {
|
|
4
4
|
|
|
5
|
-
const MANIFEST_BUILD_VERSION = '0.5.
|
|
5
|
+
const MANIFEST_BUILD_VERSION = '0.5.274';
|
|
6
6
|
|
|
7
7
|
/* Manifest Data Sources - Appwrite Integration */
|
|
8
8
|
|
|
@@ -1642,331 +1642,87 @@ window.ManifestDataQueries = {
|
|
|
1642
1642
|
|
|
1643
1643
|
/* Manifest Data Sources - Pagination (Appwrite) */
|
|
1644
1644
|
|
|
1645
|
-
//
|
|
1646
|
-
|
|
1647
|
-
async function getFirstPage(dataSourceName, limit, baseQueries = []) {
|
|
1645
|
+
// Resolve the source's table or bucket
|
|
1646
|
+
async function resolvePagedSource(dataSourceName) {
|
|
1648
1647
|
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
1649
1648
|
if (!manifest?.data) {
|
|
1650
1649
|
throw new Error('[Manifest Data] Manifest not available');
|
|
1651
1650
|
}
|
|
1652
|
-
|
|
1653
1651
|
const dataSource = manifest.data[dataSourceName];
|
|
1654
1652
|
if (!dataSource) {
|
|
1655
1653
|
throw new Error(`[Manifest Data] Data source "${dataSourceName}" not found`);
|
|
1656
1654
|
}
|
|
1657
|
-
|
|
1658
|
-
// Check if this is an Appwrite data source
|
|
1659
|
-
const isAppwriteTable = window.ManifestDataConfig.isAppwriteCollection(dataSource);
|
|
1660
|
-
if (!isAppwriteTable) {
|
|
1655
|
+
if (!window.ManifestDataConfig.isAppwriteCollection(dataSource)) {
|
|
1661
1656
|
throw new Error(`[Manifest Data] Pagination is only supported for Appwrite data sources`);
|
|
1662
1657
|
}
|
|
1663
|
-
|
|
1664
1658
|
const appwriteConfig = await window.ManifestDataConfig.getAppwriteConfig(dataSource);
|
|
1665
1659
|
if (!appwriteConfig) {
|
|
1666
1660
|
throw new Error(`[Manifest Data] Invalid Appwrite configuration for "${dataSourceName}"`);
|
|
1667
1661
|
}
|
|
1668
|
-
|
|
1669
1662
|
const tableId = window.ManifestDataConfig.getAppwriteTableId(dataSource);
|
|
1670
1663
|
const bucketId = window.ManifestDataConfig.getAppwriteBucketId(dataSource);
|
|
1664
|
+
if (!tableId && !bucketId) {
|
|
1665
|
+
throw new Error(`[Manifest Data] Data source "${dataSourceName}" is not a table or bucket`);
|
|
1666
|
+
}
|
|
1667
|
+
return { appwriteConfig, tableId, bucketId };
|
|
1668
|
+
}
|
|
1671
1669
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1670
|
+
// One page request. Asks for limit + 1 rows: the extra row only answers "is there more"
|
|
1671
|
+
async function fetchPage(dataSourceName, baseQueries, pageQueries, limit) {
|
|
1672
|
+
const { appwriteConfig, tableId, bucketId } = await resolvePagedSource(dataSourceName);
|
|
1673
|
+
const queries = [...baseQueries, ...pageQueries, window.Appwrite.Query.limit(limit + 1)];
|
|
1674
|
+
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1678
1675
|
let response;
|
|
1679
1676
|
if (tableId) {
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
if (!services?.tablesDB) {
|
|
1683
|
-
throw new Error('[Manifest Data] Appwrite TablesDB service not available');
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
const appwriteResponse = await services.tablesDB.listRows({
|
|
1687
|
-
databaseId: appwriteConfig.databaseId,
|
|
1688
|
-
tableId: tableId,
|
|
1689
|
-
queries: queries
|
|
1690
|
-
});
|
|
1691
|
-
|
|
1692
|
-
const items = appwriteResponse.rows || [];
|
|
1693
|
-
const total = appwriteResponse.total || 0;
|
|
1694
|
-
const cursor = items.length > 0 ? items[items.length - 1].$id : null;
|
|
1695
|
-
const hasMore = items.length === limit && total > limit;
|
|
1696
|
-
|
|
1697
|
-
return {
|
|
1698
|
-
items,
|
|
1699
|
-
cursor,
|
|
1700
|
-
total,
|
|
1701
|
-
hasMore
|
|
1702
|
-
};
|
|
1703
|
-
} else if (bucketId) {
|
|
1704
|
-
// Storage pagination
|
|
1705
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1706
|
-
if (!services?.storage) {
|
|
1707
|
-
throw new Error('[Manifest Data] Appwrite Storage service not available');
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
const storageResponse = await services.storage.listFiles(bucketId, queries);
|
|
1711
|
-
const items = storageResponse.files || [];
|
|
1712
|
-
const total = storageResponse.total || 0;
|
|
1713
|
-
const cursor = items.length > 0 ? items[items.length - 1].$id : null;
|
|
1714
|
-
const hasMore = items.length === limit && total > limit;
|
|
1715
|
-
|
|
1716
|
-
return {
|
|
1717
|
-
items,
|
|
1718
|
-
cursor,
|
|
1719
|
-
total,
|
|
1720
|
-
hasMore
|
|
1721
|
-
};
|
|
1677
|
+
if (!services?.tablesDB) throw new Error('[Manifest Data] Appwrite TablesDB service not available');
|
|
1678
|
+
response = await services.tablesDB.listRows({ databaseId: appwriteConfig.databaseId, tableId, queries });
|
|
1722
1679
|
} else {
|
|
1723
|
-
throw new Error(
|
|
1680
|
+
if (!services?.storage) throw new Error('[Manifest Data] Appwrite Storage service not available');
|
|
1681
|
+
response = await services.storage.listFiles(bucketId, queries);
|
|
1724
1682
|
}
|
|
1683
|
+
const rows = (tableId ? response.rows : response.files) || [];
|
|
1684
|
+
return { rows, total: response.total || 0, extra: rows.length > limit };
|
|
1725
1685
|
}
|
|
1726
1686
|
|
|
1727
|
-
//
|
|
1728
|
-
|
|
1687
|
+
// First page, cursor-based. Returns { items, cursor, total, hasMore }
|
|
1688
|
+
async function getFirstPage(dataSourceName, limit, baseQueries = []) {
|
|
1689
|
+
const { rows, total, extra } = await fetchPage(dataSourceName, baseQueries, [], limit);
|
|
1690
|
+
const items = rows.slice(0, limit);
|
|
1691
|
+
return { items, cursor: items.length ? items[items.length - 1].$id : null, total, hasMore: extra };
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// Next page after a cursor. Returns { items, cursor, total, hasMore }
|
|
1729
1695
|
async function getNextPage(dataSourceName, cursor, limit, baseQueries = []) {
|
|
1730
1696
|
if (!cursor) {
|
|
1731
1697
|
throw new Error('[Manifest Data] Cursor is required for next page');
|
|
1732
1698
|
}
|
|
1733
|
-
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
throw new Error('[Manifest Data] Manifest not available');
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
const dataSource = manifest.data[dataSourceName];
|
|
1740
|
-
if (!dataSource) {
|
|
1741
|
-
throw new Error(`[Manifest Data] Data source "${dataSourceName}" not found`);
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
|
-
const appwriteConfig = await window.ManifestDataConfig.getAppwriteConfig(dataSource);
|
|
1745
|
-
if (!appwriteConfig) {
|
|
1746
|
-
throw new Error(`[Manifest Data] Invalid Appwrite configuration for "${dataSourceName}"`);
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
const tableId = window.ManifestDataConfig.getAppwriteTableId(dataSource);
|
|
1750
|
-
const bucketId = window.ManifestDataConfig.getAppwriteBucketId(dataSource);
|
|
1751
|
-
|
|
1752
|
-
// Build queries with cursorAfter and limit
|
|
1753
|
-
const queries = [
|
|
1754
|
-
...baseQueries,
|
|
1755
|
-
window.Appwrite.Query.cursorAfter(cursor),
|
|
1756
|
-
window.Appwrite.Query.limit(limit)
|
|
1757
|
-
];
|
|
1758
|
-
|
|
1759
|
-
let response;
|
|
1760
|
-
if (tableId) {
|
|
1761
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1762
|
-
if (!services?.tablesDB) {
|
|
1763
|
-
throw new Error('[Manifest Data] Appwrite TablesDB service not available');
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
|
-
const appwriteResponse = await services.tablesDB.listRows({
|
|
1767
|
-
databaseId: appwriteConfig.databaseId,
|
|
1768
|
-
tableId: tableId,
|
|
1769
|
-
queries: queries
|
|
1770
|
-
});
|
|
1771
|
-
|
|
1772
|
-
const items = appwriteResponse.rows || [];
|
|
1773
|
-
const total = appwriteResponse.total || 0;
|
|
1774
|
-
const newCursor = items.length > 0 ? items[items.length - 1].$id : null;
|
|
1775
|
-
const hasMore = items.length === limit && total > limit;
|
|
1776
|
-
|
|
1777
|
-
return {
|
|
1778
|
-
items,
|
|
1779
|
-
cursor: newCursor,
|
|
1780
|
-
total,
|
|
1781
|
-
hasMore
|
|
1782
|
-
};
|
|
1783
|
-
} else if (bucketId) {
|
|
1784
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1785
|
-
if (!services?.storage) {
|
|
1786
|
-
throw new Error('[Manifest Data] Appwrite Storage service not available');
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
const storageResponse = await services.storage.listFiles(bucketId, queries);
|
|
1790
|
-
const items = storageResponse.files || [];
|
|
1791
|
-
const total = storageResponse.total || 0;
|
|
1792
|
-
const newCursor = items.length > 0 ? items[items.length - 1].$id : null;
|
|
1793
|
-
const hasMore = items.length === limit && total > (limit * 2); // Rough estimate
|
|
1794
|
-
|
|
1795
|
-
return {
|
|
1796
|
-
items,
|
|
1797
|
-
cursor: newCursor,
|
|
1798
|
-
total,
|
|
1799
|
-
hasMore
|
|
1800
|
-
};
|
|
1801
|
-
} else {
|
|
1802
|
-
throw new Error(`[Manifest Data] Data source "${dataSourceName}" is not a table or bucket`);
|
|
1803
|
-
}
|
|
1699
|
+
const { rows, total, extra } = await fetchPage(dataSourceName, baseQueries, [window.Appwrite.Query.cursorAfter(cursor)], limit);
|
|
1700
|
+
const items = rows.slice(0, limit);
|
|
1701
|
+
return { items, cursor: items.length ? items[items.length - 1].$id : null, total, hasMore: extra };
|
|
1804
1702
|
}
|
|
1805
1703
|
|
|
1806
|
-
// Previous page
|
|
1807
|
-
// Returns { items, cursor, total, hasMore }
|
|
1704
|
+
// Previous page before a cursor. hasMore: rows exist before this page. Returns { items, cursor, total, hasMore }
|
|
1808
1705
|
async function getPrevPage(dataSourceName, cursor, limit, baseQueries = []) {
|
|
1809
1706
|
if (!cursor) {
|
|
1810
1707
|
throw new Error('[Manifest Data] Cursor is required for previous page');
|
|
1811
1708
|
}
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
const dataSource = manifest.data[dataSourceName];
|
|
1819
|
-
if (!dataSource) {
|
|
1820
|
-
throw new Error(`[Manifest Data] Data source "${dataSourceName}" not found`);
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
const appwriteConfig = await window.ManifestDataConfig.getAppwriteConfig(dataSource);
|
|
1824
|
-
if (!appwriteConfig) {
|
|
1825
|
-
throw new Error(`[Manifest Data] Invalid Appwrite configuration for "${dataSourceName}"`);
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
const tableId = window.ManifestDataConfig.getAppwriteTableId(dataSource);
|
|
1829
|
-
const bucketId = window.ManifestDataConfig.getAppwriteBucketId(dataSource);
|
|
1830
|
-
|
|
1831
|
-
// Build queries with cursorBefore and limit
|
|
1832
|
-
const queries = [
|
|
1833
|
-
...baseQueries,
|
|
1834
|
-
window.Appwrite.Query.cursorBefore(cursor),
|
|
1835
|
-
window.Appwrite.Query.limit(limit)
|
|
1836
|
-
];
|
|
1837
|
-
|
|
1838
|
-
let response;
|
|
1839
|
-
if (tableId) {
|
|
1840
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1841
|
-
if (!services?.tablesDB) {
|
|
1842
|
-
throw new Error('[Manifest Data] Appwrite TablesDB service not available');
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
const appwriteResponse = await services.tablesDB.listRows({
|
|
1846
|
-
databaseId: appwriteConfig.databaseId,
|
|
1847
|
-
tableId: tableId,
|
|
1848
|
-
queries: queries
|
|
1849
|
-
});
|
|
1850
|
-
|
|
1851
|
-
const items = appwriteResponse.rows || [];
|
|
1852
|
-
const total = appwriteResponse.total || 0;
|
|
1853
|
-
const newCursor = items.length > 0 ? items[0].$id : null; // First item's ID for going back further
|
|
1854
|
-
const hasMore = true; // Can't easily determine if there's a previous page
|
|
1855
|
-
|
|
1856
|
-
return {
|
|
1857
|
-
items,
|
|
1858
|
-
cursor: newCursor,
|
|
1859
|
-
total,
|
|
1860
|
-
hasMore
|
|
1861
|
-
};
|
|
1862
|
-
} else if (bucketId) {
|
|
1863
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1864
|
-
if (!services?.storage) {
|
|
1865
|
-
throw new Error('[Manifest Data] Appwrite Storage service not available');
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
const storageResponse = await services.storage.listFiles(bucketId, queries);
|
|
1869
|
-
const items = storageResponse.files || [];
|
|
1870
|
-
const total = storageResponse.total || 0;
|
|
1871
|
-
const newCursor = items.length > 0 ? items[0].$id : null;
|
|
1872
|
-
const hasMore = true;
|
|
1873
|
-
|
|
1874
|
-
return {
|
|
1875
|
-
items,
|
|
1876
|
-
cursor: newCursor,
|
|
1877
|
-
total,
|
|
1878
|
-
hasMore
|
|
1879
|
-
};
|
|
1880
|
-
} else {
|
|
1881
|
-
throw new Error(`[Manifest Data] Data source "${dataSourceName}" is not a table or bucket`);
|
|
1882
|
-
}
|
|
1709
|
+
const { rows, total, extra } = await fetchPage(dataSourceName, baseQueries, [window.Appwrite.Query.cursorBefore(cursor)], limit);
|
|
1710
|
+
// cursorBefore returns the rows nearest the cursor last; the extra row is the first one
|
|
1711
|
+
const items = extra ? rows.slice(rows.length - limit) : rows;
|
|
1712
|
+
return { items, cursor: items.length ? items[0].$id : null, total, hasMore: extra };
|
|
1883
1713
|
}
|
|
1884
1714
|
|
|
1885
|
-
// Specific page (1-based), offset-based
|
|
1886
|
-
// Returns { items, page, total, totalPages, hasMore }
|
|
1715
|
+
// Specific page (1-based), offset-based. Returns { items, page, total, totalPages, hasMore }
|
|
1887
1716
|
async function getPage(dataSourceName, pageNumber, limit, baseQueries = []) {
|
|
1888
|
-
if (pageNumber < 1) {
|
|
1717
|
+
if (!pageNumber || pageNumber < 1) {
|
|
1889
1718
|
throw new Error('[Manifest Data] Page number must be >= 1');
|
|
1890
1719
|
}
|
|
1891
|
-
|
|
1892
|
-
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
1893
|
-
if (!manifest?.data) {
|
|
1894
|
-
throw new Error('[Manifest Data] Manifest not available');
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
const dataSource = manifest.data[dataSourceName];
|
|
1898
|
-
if (!dataSource) {
|
|
1899
|
-
throw new Error(`[Manifest Data] Data source "${dataSourceName}" not found`);
|
|
1900
|
-
}
|
|
1901
|
-
|
|
1902
|
-
const appwriteConfig = await window.ManifestDataConfig.getAppwriteConfig(dataSource);
|
|
1903
|
-
if (!appwriteConfig) {
|
|
1904
|
-
throw new Error(`[Manifest Data] Invalid Appwrite configuration for "${dataSourceName}"`);
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
|
-
const tableId = window.ManifestDataConfig.getAppwriteTableId(dataSource);
|
|
1908
|
-
const bucketId = window.ManifestDataConfig.getAppwriteBucketId(dataSource);
|
|
1909
|
-
|
|
1910
1720
|
const offset = (pageNumber - 1) * limit;
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
...baseQueries,
|
|
1915
|
-
window.Appwrite.Query.offset(offset),
|
|
1916
|
-
window.Appwrite.Query.limit(limit)
|
|
1917
|
-
];
|
|
1918
|
-
|
|
1919
|
-
let response;
|
|
1920
|
-
let total;
|
|
1921
|
-
if (tableId) {
|
|
1922
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1923
|
-
if (!services?.tablesDB) {
|
|
1924
|
-
throw new Error('[Manifest Data] Appwrite TablesDB service not available');
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
const appwriteResponse = await services.tablesDB.listRows({
|
|
1928
|
-
databaseId: appwriteConfig.databaseId,
|
|
1929
|
-
tableId: tableId,
|
|
1930
|
-
queries: queries
|
|
1931
|
-
});
|
|
1932
|
-
|
|
1933
|
-
const items = appwriteResponse.rows || [];
|
|
1934
|
-
total = appwriteResponse.total || 0;
|
|
1935
|
-
const totalPages = Math.ceil(total / limit);
|
|
1936
|
-
const hasMore = pageNumber < totalPages;
|
|
1937
|
-
|
|
1938
|
-
return {
|
|
1939
|
-
items,
|
|
1940
|
-
page: pageNumber,
|
|
1941
|
-
total,
|
|
1942
|
-
totalPages,
|
|
1943
|
-
hasMore
|
|
1944
|
-
};
|
|
1945
|
-
} else if (bucketId) {
|
|
1946
|
-
const services = await window.ManifestDataAppwrite._getAppwriteDataServices();
|
|
1947
|
-
if (!services?.storage) {
|
|
1948
|
-
throw new Error('[Manifest Data] Appwrite Storage service not available');
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
const storageResponse = await services.storage.listFiles(bucketId, queries);
|
|
1952
|
-
const items = storageResponse.files || [];
|
|
1953
|
-
total = storageResponse.total || 0;
|
|
1954
|
-
const totalPages = Math.ceil(total / limit);
|
|
1955
|
-
const hasMore = pageNumber < totalPages;
|
|
1956
|
-
|
|
1957
|
-
return {
|
|
1958
|
-
items,
|
|
1959
|
-
page: pageNumber,
|
|
1960
|
-
total,
|
|
1961
|
-
totalPages,
|
|
1962
|
-
hasMore
|
|
1963
|
-
};
|
|
1964
|
-
} else {
|
|
1965
|
-
throw new Error(`[Manifest Data] Data source "${dataSourceName}" is not a table or bucket`);
|
|
1966
|
-
}
|
|
1721
|
+
const { rows, total, extra } = await fetchPage(dataSourceName, baseQueries, [window.Appwrite.Query.offset(offset)], limit);
|
|
1722
|
+
const items = rows.slice(0, limit);
|
|
1723
|
+
return { items, page: pageNumber, total, totalPages: Math.ceil(total / limit), hasMore: extra };
|
|
1967
1724
|
}
|
|
1968
1725
|
|
|
1969
|
-
// Export functions
|
|
1970
1726
|
window.ManifestDataPagination = {
|
|
1971
1727
|
getFirstPage,
|
|
1972
1728
|
getNextPage,
|
|
@@ -205,6 +205,13 @@ function escapeForSingleQuotedJsString(s) {
|
|
|
205
205
|
// Framework web components (not project components) — never fetched.
|
|
206
206
|
const FRAMEWORK_COMPONENT_TAGS = new Set(['code', 'code-group']);
|
|
207
207
|
|
|
208
|
+
// Classic JS or module; anything else (JSON, templates) is a data block
|
|
209
|
+
function isExecutableScript(el) {
|
|
210
|
+
const type = (el.getAttribute('type') || '').split(';')[0].trim().toLowerCase();
|
|
211
|
+
return type === '' || type === 'module' || /^(text|application)\/(x-)?(javascript|ecmascript)$/.test(type) ||
|
|
212
|
+
/^text\/(javascript1\.[0-5]|jscript|livescript)$/.test(type);
|
|
213
|
+
}
|
|
214
|
+
|
|
208
215
|
// The <template x-if>/<template x-for> whose tracked clone is `el`, if any.
|
|
209
216
|
function findOwningTemplate(el) {
|
|
210
217
|
if (!el._x_dataStack) return null;
|
|
@@ -289,6 +296,8 @@ window.ManifestComponentsProcessor = {
|
|
|
289
296
|
const scripts = [];
|
|
290
297
|
const processScripts = (el) => {
|
|
291
298
|
if (el.tagName.toLowerCase() === 'script') {
|
|
299
|
+
// Data blocks (JSON, templates) are dropped, never run
|
|
300
|
+
if (!isExecutableScript(el)) { el.remove(); return; }
|
|
292
301
|
scripts.push({
|
|
293
302
|
content: el.textContent,
|
|
294
303
|
type: el.getAttribute('type') || 'text/javascript',
|
|
@@ -575,6 +584,15 @@ window.ManifestComponentsProcessor = {
|
|
|
575
584
|
if (script.async) scriptEl.async = true;
|
|
576
585
|
if (script.defer) scriptEl.defer = true;
|
|
577
586
|
document.head.appendChild(scriptEl);
|
|
587
|
+
} else if (script.content && script.type.trim().toLowerCase() === 'module') {
|
|
588
|
+
// Once per page, like an external module
|
|
589
|
+
const seen = Array.from(document.head.querySelectorAll('script[data-component-module]'));
|
|
590
|
+
if (seen.some(s => s.textContent === script.content)) return;
|
|
591
|
+
const scriptEl = document.createElement('script');
|
|
592
|
+
scriptEl.setAttribute('data-component-module', name);
|
|
593
|
+
scriptEl.type = 'module';
|
|
594
|
+
scriptEl.textContent = script.content;
|
|
595
|
+
document.head.appendChild(scriptEl);
|
|
578
596
|
} else if (script.content) {
|
|
579
597
|
// Inline script → run in global scope
|
|
580
598
|
try {
|
package/lib/manifest.data.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
(function () {
|
|
4
4
|
|
|
5
|
-
const MANIFEST_BUILD_VERSION = '0.5.
|
|
5
|
+
const MANIFEST_BUILD_VERSION = '0.5.274';
|
|
6
6
|
|
|
7
7
|
/* Manifest Data Sources - Configuration */
|
|
8
8
|
|
|
@@ -432,9 +432,12 @@ function sourceGeneration(dataSourceName) {
|
|
|
432
432
|
// next read hydrates/fetches for the new scope; older loads are discarded
|
|
433
433
|
function resetSource(dataSourceName) {
|
|
434
434
|
sourceGen.set(dataSourceName, sourceGeneration(dataSourceName) + 1);
|
|
435
|
+
latestRead.delete(dataSourceName);
|
|
436
|
+
window.ManifestDataMain?.forgetLiveSource?.(dataSourceName);
|
|
435
437
|
const prefix = `${dataSourceName}:`;
|
|
436
438
|
for (const key of [...dataSourceCache.keys()]) if (key.startsWith(prefix)) dataSourceCache.delete(key);
|
|
437
439
|
for (const key of [...loadingPromises.keys()]) if (key.startsWith(prefix)) loadingPromises.delete(key);
|
|
440
|
+
for (const key of [...loadReadTokens.keys()]) if (key.startsWith(prefix)) loadReadTokens.delete(key);
|
|
438
441
|
freshness.delete(dataSourceName);
|
|
439
442
|
pendingLocal.delete(dataSourceName);
|
|
440
443
|
for (let i = pendingLandings.length - 1; i >= 0; i--) {
|
|
@@ -468,6 +471,15 @@ function setSourceState(dataSourceName, patch) {
|
|
|
468
471
|
return next;
|
|
469
472
|
}
|
|
470
473
|
|
|
474
|
+
// Last-issued read per source: a slower earlier read ($query or load) never lands over a later one
|
|
475
|
+
const latestRead = new Map();
|
|
476
|
+
let readSeq = 0;
|
|
477
|
+
const loadReadTokens = new Map(); // source:locale → token of the load in flight under that key
|
|
478
|
+
function beginRead(dataSourceName) { const token = ++readSeq; latestRead.set(dataSourceName, token); return token; }
|
|
479
|
+
function adoptRead(dataSourceName, token) { if (token !== undefined) latestRead.set(dataSourceName, token); }
|
|
480
|
+
// A reset clears the record: generation stamps already drop the older reads
|
|
481
|
+
function isLatestRead(dataSourceName, token) { return token === undefined || !latestRead.has(dataSourceName) || latestRead.get(dataSourceName) === token; }
|
|
482
|
+
|
|
471
483
|
// Authoritative in-flight map: one promise per key, cleared on settle
|
|
472
484
|
function runDeduped(key, factory) {
|
|
473
485
|
if (loadingPromises.has(key)) return loadingPromises.get(key);
|
|
@@ -492,16 +504,74 @@ function ensureSourceArray(dataSourceName) {
|
|
|
492
504
|
return store[dataSourceName];
|
|
493
505
|
}
|
|
494
506
|
|
|
507
|
+
// Sort spec [[attr, 1|-1], ...] → comparator; nulls sort first ascending,
|
|
508
|
+
// strings case-insensitively (Appwrite's collation)
|
|
509
|
+
function compareBy(order) {
|
|
510
|
+
const norm = v => (typeof v === 'string' ? v.toLowerCase() : v);
|
|
511
|
+
return (a, b) => {
|
|
512
|
+
for (const [key, dir] of order) {
|
|
513
|
+
const x = norm(a?.[key]), y = norm(b?.[key]);
|
|
514
|
+
if (x === y) continue;
|
|
515
|
+
if (x === null || x === undefined) return -dir;
|
|
516
|
+
if (y === null || y === undefined) return dir;
|
|
517
|
+
return (x < y ? -1 : 1) * dir;
|
|
518
|
+
}
|
|
519
|
+
return 0;
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function sortedIndex(arr, row, cmp) {
|
|
524
|
+
let lo = 0, hi = arr.length;
|
|
525
|
+
while (lo < hi) {
|
|
526
|
+
const mid = (lo + hi) >> 1;
|
|
527
|
+
if (cmp(arr[mid], row) <= 0) lo = mid + 1; else hi = mid;
|
|
528
|
+
}
|
|
529
|
+
return lo;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Ordered append (realtime on a sorted source): new rows insert at their sort
|
|
533
|
+
// position; merged rows whose sort key moved are re-positioned. Structure is
|
|
534
|
+
// rebuilt on a raw copy and assigned once (one reactive write, not per splice)
|
|
535
|
+
function upsertOrdered(store, dataSourceName, rows, order) {
|
|
536
|
+
const cmp = compareBy(order);
|
|
537
|
+
const cur = store[dataSourceName];
|
|
538
|
+
const curRaw = rawOf(store)[dataSourceName];
|
|
539
|
+
let next = null;
|
|
540
|
+
for (const row of rows) {
|
|
541
|
+
const list = next || curRaw;
|
|
542
|
+
const id = rowKey(row);
|
|
543
|
+
const i = id !== null ? list.findIndex(r => rowKey(r) === id) : -1;
|
|
544
|
+
if (i !== -1) {
|
|
545
|
+
// Only a changed sort value moves a held row; the server's placement otherwise stands
|
|
546
|
+
const keyChanged = order.some(([key]) => Object.prototype.hasOwnProperty.call(row, key) && !sameScalarOrList(list[i][key], row[key]));
|
|
547
|
+
mergeRowFields(next ? (Alpine.reactive ? Alpine.reactive(list[i]) : list[i]) : cur[i], row, dataSourceName);
|
|
548
|
+
const misplaced = keyChanged && ((i > 0 && cmp(list[i - 1], list[i]) > 0) || (i < list.length - 1 && cmp(list[i], list[i + 1]) > 0));
|
|
549
|
+
if (!misplaced) continue;
|
|
550
|
+
if (!next) next = curRaw.slice();
|
|
551
|
+
const [moved] = next.splice(i, 1);
|
|
552
|
+
next.splice(sortedIndex(next, moved, cmp), 0, moved);
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
if (!next) next = curRaw.slice();
|
|
556
|
+
next.splice(sortedIndex(next, row, cmp), 0, rawOf(createReactiveReferences(row, dataSourceName)));
|
|
557
|
+
}
|
|
558
|
+
if (next) store[dataSourceName] = next;
|
|
559
|
+
}
|
|
560
|
+
|
|
495
561
|
// Identity-preserving upsert by $id: existing rows are merged in place, new
|
|
496
562
|
// rows created; append keeps the array, replace swaps it only when membership
|
|
497
563
|
// or order changed
|
|
498
|
-
function upsertRows(store, dataSourceName, rows, mode) {
|
|
564
|
+
function upsertRows(store, dataSourceName, rows, mode, order) {
|
|
499
565
|
const raw = rawOf(store);
|
|
500
566
|
const curRaw = Array.isArray(raw[dataSourceName]) ? raw[dataSourceName] : null;
|
|
501
567
|
if (!curRaw) {
|
|
502
568
|
store[dataSourceName] = rows.map(row => createReactiveReferences(row, dataSourceName));
|
|
503
569
|
return;
|
|
504
570
|
}
|
|
571
|
+
if (mode === 'append' && Array.isArray(order) && order.length) {
|
|
572
|
+
upsertOrdered(store, dataSourceName, rows, order);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
505
575
|
const cur = store[dataSourceName];
|
|
506
576
|
const index = new Map();
|
|
507
577
|
curRaw.forEach((row, i) => { const id = rowKey(row); if (id !== null) index.set(id, i); });
|
|
@@ -557,7 +627,7 @@ function writeSource(dataSourceName, data, options = {}) {
|
|
|
557
627
|
rawDataStore.set(dataSourceName, data);
|
|
558
628
|
}
|
|
559
629
|
} else if (Array.isArray(data)) {
|
|
560
|
-
upsertRows(store, dataSourceName, data, mode);
|
|
630
|
+
upsertRows(store, dataSourceName, data, mode, options.order);
|
|
561
631
|
const arr = rawOf(store)[dataSourceName];
|
|
562
632
|
rawDataStore.set(dataSourceName, arr);
|
|
563
633
|
attachMethods(arr, dataSourceName);
|
|
@@ -1523,6 +1593,10 @@ window.ManifestDataStore = {
|
|
|
1523
1593
|
// Stale-first + dedupe (§11.1)
|
|
1524
1594
|
setSourceState,
|
|
1525
1595
|
runDeduped,
|
|
1596
|
+
beginRead,
|
|
1597
|
+
adoptRead,
|
|
1598
|
+
loadReadTokens,
|
|
1599
|
+
isLatestRead,
|
|
1526
1600
|
sourceFreshness,
|
|
1527
1601
|
// Persistence (§12.2)
|
|
1528
1602
|
sourceGeneration,
|
|
@@ -2865,7 +2939,8 @@ window.ManifestDataLoaders = {
|
|
|
2865
2939
|
// Load from API endpoint (read-only)
|
|
2866
2940
|
async function loadFromAPI(dataSource) {
|
|
2867
2941
|
try {
|
|
2868
|
-
|
|
2942
|
+
// Relative urls resolve against the page
|
|
2943
|
+
const url = new URL(window.ManifestDataConfig.interpolateEnvVars(dataSource.url), window.location.href);
|
|
2869
2944
|
|
|
2870
2945
|
// Add query parameters
|
|
2871
2946
|
if (dataSource.params) {
|
|
@@ -3176,7 +3251,15 @@ async function executeMutation(mutationConfig) {
|
|
|
3176
3251
|
if (type === 'create') {
|
|
3177
3252
|
// Ack: swap the temp row for the server row in place (new $id → new $files binding)
|
|
3178
3253
|
const { store, arr, index } = findRawIndex(dataSourceName, optimisticData.$id);
|
|
3179
|
-
|
|
3254
|
+
// Realtime echo of this create may have landed first under the real $id
|
|
3255
|
+
const held = (arr && result.$id !== optimisticData.$id) ? arr.findIndex(r => r && r.$id === result.$id) : -1;
|
|
3256
|
+
if (store && arr && held !== -1) {
|
|
3257
|
+
const ds = window.ManifestDataStore;
|
|
3258
|
+
ds.mergeRowFields(store[dataSourceName][held], result, dataSourceName);
|
|
3259
|
+
if (index !== -1) store[dataSourceName].splice(index, 1);
|
|
3260
|
+
ds.touchSource(dataSourceName);
|
|
3261
|
+
clearSourceCaches(dataSourceName);
|
|
3262
|
+
} else if (store && arr) {
|
|
3180
3263
|
if (index !== -1) {
|
|
3181
3264
|
const ds = window.ManifestDataStore;
|
|
3182
3265
|
store[dataSourceName].splice(index, 1, ds.createReactiveReferences(result, dataSourceName));
|
|
@@ -4602,52 +4685,9 @@ function attachArrayMethods(array, dataSourceName, reloadDataSource) {
|
|
|
4602
4685
|
});
|
|
4603
4686
|
}
|
|
4604
4687
|
|
|
4605
|
-
// Attach pagination methods
|
|
4606
|
-
const createPaginationMethod = (methodName) =>
|
|
4607
|
-
|
|
4608
|
-
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
4609
|
-
if (!manifest?.data) {
|
|
4610
|
-
throw new Error('[Manifest Data] Manifest not available');
|
|
4611
|
-
}
|
|
4612
|
-
const dataSource = manifest.data[dataSourceName];
|
|
4613
|
-
if (!dataSource || !window.ManifestDataConfig.isAppwriteCollection(dataSource)) {
|
|
4614
|
-
throw new Error(`[Manifest Data] Pagination is only supported for Appwrite data sources`);
|
|
4615
|
-
}
|
|
4616
|
-
const scope = window.ManifestDataConfig.getScope(dataSource);
|
|
4617
|
-
const scopeColumns = window.ManifestDataConfig.getScopeColumns(dataSource);
|
|
4618
|
-
const queriesConfig = window.ManifestDataConfig.getQueries(dataSource);
|
|
4619
|
-
const baseQueries = queriesConfig
|
|
4620
|
-
? await window.ManifestDataQueries.buildAppwriteQueries(queriesConfig.default || queriesConfig, scope, scopeColumns)
|
|
4621
|
-
: await window.ManifestDataQueries.buildAppwriteQueries([], scope, scopeColumns);
|
|
4622
|
-
|
|
4623
|
-
if (baseQueries === null) {
|
|
4624
|
-
throw new Error(`[Manifest Data] "${dataSourceName}" pagination: auth not ready yet — retry after auth settles`);
|
|
4625
|
-
}
|
|
4626
|
-
|
|
4627
|
-
if (methodName === '$first') {
|
|
4628
|
-
const limit = args[0] || 10;
|
|
4629
|
-
return await window.ManifestDataPagination.getFirstPage(dataSourceName, limit, baseQueries);
|
|
4630
|
-
} else if (methodName === '$next') {
|
|
4631
|
-
const [cursor, limit = 10] = args;
|
|
4632
|
-
if (!cursor) {
|
|
4633
|
-
throw new Error('[Manifest Data] Cursor is required for $next');
|
|
4634
|
-
}
|
|
4635
|
-
return await window.ManifestDataPagination.getNextPage(dataSourceName, cursor, limit, baseQueries);
|
|
4636
|
-
} else if (methodName === '$prev') {
|
|
4637
|
-
const [cursor, limit = 10] = args;
|
|
4638
|
-
if (!cursor) {
|
|
4639
|
-
throw new Error('[Manifest Data] Cursor is required for $prev');
|
|
4640
|
-
}
|
|
4641
|
-
return await window.ManifestDataPagination.getPrevPage(dataSourceName, cursor, limit, baseQueries);
|
|
4642
|
-
} else if (methodName === '$page') {
|
|
4643
|
-
const [pageNumber, limit = 10] = args;
|
|
4644
|
-
if (!pageNumber || pageNumber < 1) {
|
|
4645
|
-
throw new Error('[Manifest Data] Page number must be >= 1');
|
|
4646
|
-
}
|
|
4647
|
-
return await window.ManifestDataPagination.getPage(dataSourceName, pageNumber, limit, baseQueries);
|
|
4648
|
-
}
|
|
4649
|
-
};
|
|
4650
|
-
};
|
|
4688
|
+
// Attach pagination methods (one implementation: magic.pagination)
|
|
4689
|
+
const createPaginationMethod = (methodName) => (...args) =>
|
|
4690
|
+
window.ManifestDataProxiesMagic.createPaginationMethod(methodName, dataSourceName)(...args);
|
|
4651
4691
|
|
|
4652
4692
|
['$first', '$next', '$prev', '$page'].forEach(methodName => {
|
|
4653
4693
|
Object.defineProperty(array, methodName, {
|
|
@@ -4952,52 +4992,7 @@ function createArrayProxyWithRoute(arrayTarget, dataSourceName = null, reloadDat
|
|
|
4952
4992
|
|
|
4953
4993
|
// Handle pagination methods
|
|
4954
4994
|
if (key === '$first' || key === '$next' || key === '$prev' || key === '$page') {
|
|
4955
|
-
return
|
|
4956
|
-
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
4957
|
-
if (!manifest?.data) {
|
|
4958
|
-
throw new Error('[Manifest Data] Manifest not available');
|
|
4959
|
-
}
|
|
4960
|
-
|
|
4961
|
-
const dataSource = manifest.data[dataSourceName];
|
|
4962
|
-
if (!dataSource || !window.ManifestDataConfig.isAppwriteCollection(dataSource)) {
|
|
4963
|
-
throw new Error(`[Manifest Data] Pagination is only supported for Appwrite data sources`);
|
|
4964
|
-
}
|
|
4965
|
-
|
|
4966
|
-
// Get base queries (from manifest or scope)
|
|
4967
|
-
const scope = window.ManifestDataConfig.getScope(dataSource);
|
|
4968
|
-
const scopeColumns = window.ManifestDataConfig.getScopeColumns(dataSource);
|
|
4969
|
-
const queriesConfig = window.ManifestDataConfig.getQueries(dataSource);
|
|
4970
|
-
const baseQueries = queriesConfig
|
|
4971
|
-
? await window.ManifestDataQueries.buildAppwriteQueries(queriesConfig.default || queriesConfig, scope, scopeColumns)
|
|
4972
|
-
: await window.ManifestDataQueries.buildAppwriteQueries([], scope, scopeColumns);
|
|
4973
|
-
|
|
4974
|
-
if (baseQueries === null) {
|
|
4975
|
-
throw new Error(`[Manifest Data] "${dataSourceName}" pagination: auth not ready yet — retry after auth settles`);
|
|
4976
|
-
}
|
|
4977
|
-
|
|
4978
|
-
if (key === '$first') {
|
|
4979
|
-
const limit = args[0] || 10;
|
|
4980
|
-
return await window.ManifestDataPagination.getFirstPage(dataSourceName, limit, baseQueries);
|
|
4981
|
-
} else if (key === '$next') {
|
|
4982
|
-
const [cursor, limit = 10] = args;
|
|
4983
|
-
if (!cursor) {
|
|
4984
|
-
throw new Error('[Manifest Data] Cursor is required for $next');
|
|
4985
|
-
}
|
|
4986
|
-
return await window.ManifestDataPagination.getNextPage(dataSourceName, cursor, limit, baseQueries);
|
|
4987
|
-
} else if (key === '$prev') {
|
|
4988
|
-
const [cursor, limit = 10] = args;
|
|
4989
|
-
if (!cursor) {
|
|
4990
|
-
throw new Error('[Manifest Data] Cursor is required for $prev');
|
|
4991
|
-
}
|
|
4992
|
-
return await window.ManifestDataPagination.getPrevPage(dataSourceName, cursor, limit, baseQueries);
|
|
4993
|
-
} else if (key === '$page') {
|
|
4994
|
-
const [pageNumber, limit = 10] = args;
|
|
4995
|
-
if (!pageNumber || pageNumber < 1) {
|
|
4996
|
-
throw new Error('[Manifest Data] Page number must be >= 1');
|
|
4997
|
-
}
|
|
4998
|
-
return await window.ManifestDataPagination.getPage(dataSourceName, pageNumber, limit, baseQueries);
|
|
4999
|
-
}
|
|
5000
|
-
};
|
|
4995
|
+
return (...args) => window.ManifestDataProxiesMagic.createPaginationMethod(key, dataSourceName)(...args);
|
|
5001
4996
|
}
|
|
5002
4997
|
|
|
5003
4998
|
// $files handler for tables
|
|
@@ -7701,6 +7696,8 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
7701
7696
|
const handleMethod = async function (method, ...args) {
|
|
7702
7697
|
const sourceUnloaded = args[3]?.sourceUnloaded === true;
|
|
7703
7698
|
if (!sourceUnloaded) clearErrorState();
|
|
7699
|
+
// Reads are ordered by call, not by network start: the last-issued one lands
|
|
7700
|
+
const readToken = method === '$query' ? window.ManifestDataStore?.beginRead?.(dataSourceName) : undefined;
|
|
7704
7701
|
|
|
7705
7702
|
try {
|
|
7706
7703
|
const manifest = await window.ManifestDataConfig?.ensureManifest?.();
|
|
@@ -7793,13 +7790,19 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
7793
7790
|
|
|
7794
7791
|
// Support batch updates
|
|
7795
7792
|
if (Array.isArray(idOrArray)) {
|
|
7796
|
-
|
|
7793
|
+
// Batch: ids (or rows) sharing `data`, or [{ id, data }] entries
|
|
7794
|
+
const updates = idOrArray.map(update => (update !== null && typeof update === 'object')
|
|
7795
|
+
? { id: update.$id || update.id || update.rowId, data: update.data || data || update }
|
|
7796
|
+
: { id: update, data });
|
|
7797
|
+
if (updates.some(u => u.id === undefined || u.id === null || u.id === '' || u.data === undefined)) {
|
|
7798
|
+
throw new Error(`[Manifest Data] "${dataSourceName}" $update: batch entries need an id and data`);
|
|
7799
|
+
}
|
|
7797
7800
|
if (executeMutation) {
|
|
7798
7801
|
// Use optimistic updates for batch
|
|
7799
7802
|
const results = await Promise.all(
|
|
7800
7803
|
updates.map(update => {
|
|
7801
|
-
const entryId = update.id
|
|
7802
|
-
const updateData = update.data
|
|
7804
|
+
const entryId = update.id;
|
|
7805
|
+
const updateData = update.data;
|
|
7803
7806
|
return executeMutation({
|
|
7804
7807
|
type: 'update',
|
|
7805
7808
|
dataSourceName,
|
|
@@ -7829,8 +7832,8 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
7829
7832
|
window.ManifestDataAppwrite.updateRow(
|
|
7830
7833
|
appwriteConfig.databaseId,
|
|
7831
7834
|
tableId,
|
|
7832
|
-
update.id
|
|
7833
|
-
update.data
|
|
7835
|
+
update.id,
|
|
7836
|
+
update.data
|
|
7834
7837
|
)
|
|
7835
7838
|
)
|
|
7836
7839
|
);
|
|
@@ -8077,23 +8080,24 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
8077
8080
|
}
|
|
8078
8081
|
// Dedupe key: source + serialized queries (never across different queries)
|
|
8079
8082
|
const key = `${dataSourceName}:$query:${JSON.stringify(appwriteQueries.map(q => String(q)))}`;
|
|
8080
|
-
const { runDeduped, landRows, sourceGeneration } = window.ManifestDataStore || {};
|
|
8083
|
+
const { runDeduped, landRows, sourceGeneration, isLatestRead } = window.ManifestDataStore || {};
|
|
8081
8084
|
const generation = sourceGeneration?.(dataSourceName);
|
|
8082
8085
|
const requireAuth = window.ManifestDataMain?.requiresIdentity?.({ ...dataSource, queries: [dataSource.queries, queries] }) ?? true;
|
|
8083
|
-
const run =
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8086
|
+
const run = () => window.ManifestDataAppwrite.loadTableRows(
|
|
8087
|
+
appwriteConfig.databaseId,
|
|
8088
|
+
tableId,
|
|
8089
|
+
appwriteQueries,
|
|
8090
|
+
{ requireAuth }
|
|
8091
|
+
);
|
|
8092
|
+
const result = runDeduped ? await runDeduped(key, run) : await run();
|
|
8093
|
+
// Network landing: query result replaces the source (coalesced, identity-preserving);
|
|
8094
|
+
// only the last-issued read of this source lands
|
|
8095
|
+
const latest = !isLatestRead || isLatestRead(dataSourceName, readToken);
|
|
8096
|
+
if (result !== undefined && landRows && latest && sourceGeneration?.(dataSourceName) === generation) {
|
|
8097
|
+
window.ManifestDataMain?.setActiveQuery?.(dataSourceName, queries || [], Array.isArray(result) ? result.length : 0);
|
|
8098
|
+
await landRows(dataSourceName, result, { mode: 'replace', fresh: true, generation });
|
|
8099
|
+
}
|
|
8100
|
+
return result;
|
|
8097
8101
|
}
|
|
8098
8102
|
}
|
|
8099
8103
|
|
|
@@ -9198,6 +9202,8 @@ window.ManifestDataProxiesMagic.createUploadMethod = createUploadMethod;
|
|
|
9198
9202
|
/* Manifest Data Sources - Magic Method Pagination Handlers */
|
|
9199
9203
|
// $first, $next, $prev, $page
|
|
9200
9204
|
|
|
9205
|
+
const PAGE_WINDOW_METHODS = new Set(['limit', 'offset', 'cursorAfter', 'cursorBefore']);
|
|
9206
|
+
|
|
9201
9207
|
function createPaginationMethod(methodName, dataSourceName) {
|
|
9202
9208
|
return async function (...args) {
|
|
9203
9209
|
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
@@ -9213,10 +9219,13 @@ function createPaginationMethod(methodName, dataSourceName) {
|
|
|
9213
9219
|
// Base queries from manifest or scope
|
|
9214
9220
|
const scope = window.ManifestDataConfig.getScope(dataSource);
|
|
9215
9221
|
const scopeColumns = window.ManifestDataConfig.getScopeColumns(dataSource);
|
|
9222
|
+
// Pages follow the active $query, else the default queries; paging supplies its own window
|
|
9216
9223
|
const queriesConfig = window.ManifestDataConfig.getQueries(dataSource);
|
|
9217
|
-
const
|
|
9218
|
-
|
|
9219
|
-
|
|
9224
|
+
const defaults = queriesConfig ? (queriesConfig.default || queriesConfig) : [];
|
|
9225
|
+
const active = window.ManifestDataMain?.getActiveQuery?.(dataSourceName);
|
|
9226
|
+
const filters = (Array.isArray(active) ? active : (Array.isArray(defaults) ? defaults : []))
|
|
9227
|
+
.filter(q => !(Array.isArray(q) && PAGE_WINDOW_METHODS.has(q[0])));
|
|
9228
|
+
const baseQueries = await window.ManifestDataQueries.buildAppwriteQueries(filters, scope, scopeColumns);
|
|
9220
9229
|
|
|
9221
9230
|
if (baseQueries === null) {
|
|
9222
9231
|
throw new Error(`[Manifest Data] "${dataSourceName}" pagination: auth not ready yet — retry after auth settles`);
|
|
@@ -11905,6 +11914,56 @@ function configureRealtimeMeta(dataSourceName, config, initialCount, limitQuery)
|
|
|
11905
11914
|
window.ManifestDataStore.setSourceState(dataSourceName, { realtimeOverflow: 0 });
|
|
11906
11915
|
}
|
|
11907
11916
|
|
|
11917
|
+
// Active $query per source (manifest-format): realtime matches, orders and
|
|
11918
|
+
// server-filters by it until the next default load replaces the rows
|
|
11919
|
+
const activeQueries = new Map();
|
|
11920
|
+
const realtimeBinds = new Map(); // Map<name, { config, mode, rebind }>
|
|
11921
|
+
|
|
11922
|
+
function realtimeQueriesFor(dataSourceName, defaults) {
|
|
11923
|
+
return activeQueries.has(dataSourceName) ? activeQueries.get(dataSourceName) : defaults;
|
|
11924
|
+
}
|
|
11925
|
+
|
|
11926
|
+
// [['orderDesc', 'n'], ...] → [['n', -1], ...]; orderRandom has no stable position
|
|
11927
|
+
function sortSpec(queries) {
|
|
11928
|
+
if (!Array.isArray(queries)) return null;
|
|
11929
|
+
if (queries.some(q => Array.isArray(q) && q[0] === 'orderRandom')) return null;
|
|
11930
|
+
const order = queries
|
|
11931
|
+
.filter(q => Array.isArray(q) && (q[0] === 'orderAsc' || q[0] === 'orderDesc') && typeof q[1] === 'string')
|
|
11932
|
+
.map(q => [q[1], q[0] === 'orderAsc' ? 1 : -1]);
|
|
11933
|
+
return order.length ? order : null;
|
|
11934
|
+
}
|
|
11935
|
+
|
|
11936
|
+
function rebindLive(dataSourceName) {
|
|
11937
|
+
const bind = realtimeBinds.get(dataSourceName);
|
|
11938
|
+
if (bind?.mode !== 'all') return;
|
|
11939
|
+
Promise.resolve().then(bind.rebind).catch(error => console.error(`[Manifest Data] Realtime rebind failed for "${dataSourceName}":`, error));
|
|
11940
|
+
}
|
|
11941
|
+
|
|
11942
|
+
// $query landing: realtime follows the new filter set (caps reset to its result)
|
|
11943
|
+
function setActiveQuery(dataSourceName, queries, rowCount) {
|
|
11944
|
+
const list = Array.isArray(queries) ? queries : [];
|
|
11945
|
+
activeQueries.set(dataSourceName, list);
|
|
11946
|
+
const bind = realtimeBinds.get(dataSourceName);
|
|
11947
|
+
if (!bind) return;
|
|
11948
|
+
const limitQ = list.find(q => Array.isArray(q) && q[0] === 'limit');
|
|
11949
|
+
configureRealtimeMeta(dataSourceName, bind.config, rowCount || 0, limitQ ? limitQ[1] : null);
|
|
11950
|
+
rebindLive(dataSourceName);
|
|
11951
|
+
}
|
|
11952
|
+
|
|
11953
|
+
// Default rows landed: back to the manifest queries (caps sized to those rows)
|
|
11954
|
+
function clearActiveQuery(dataSourceName, rowCount) {
|
|
11955
|
+
if (!activeQueries.delete(dataSourceName)) return;
|
|
11956
|
+
const bind = realtimeBinds.get(dataSourceName);
|
|
11957
|
+
if (bind) configureRealtimeMeta(dataSourceName, bind.config, rowCount || 0, bind.defaultLimit);
|
|
11958
|
+
rebindLive(dataSourceName);
|
|
11959
|
+
}
|
|
11960
|
+
|
|
11961
|
+
// Source reset (identity/scope) or torn down: nothing of the old binding carries over
|
|
11962
|
+
function forgetLiveSource(dataSourceName) {
|
|
11963
|
+
activeQueries.delete(dataSourceName);
|
|
11964
|
+
realtimeBinds.delete(dataSourceName);
|
|
11965
|
+
}
|
|
11966
|
+
|
|
11908
11967
|
// Events not applied since the last load — $x.<source>.$realtimeOverflow
|
|
11909
11968
|
function bumpRealtimeOverflow(dataSourceName) {
|
|
11910
11969
|
const state = Alpine.store('data')?.[`_${dataSourceName}_state`];
|
|
@@ -11913,12 +11972,12 @@ function bumpRealtimeOverflow(dataSourceName) {
|
|
|
11913
11972
|
|
|
11914
11973
|
// Append under the cap. 'window' evicts the oldest realtime-appended row first
|
|
11915
11974
|
// (never an initially-loaded row); otherwise the event counts in $realtimeOverflow.
|
|
11916
|
-
function realtimeAppend(dataSourceName, row, currentRows, generation) {
|
|
11975
|
+
function realtimeAppend(dataSourceName, row, currentRows, generation, order) {
|
|
11917
11976
|
const { landRows, landRemove } = window.ManifestDataStore;
|
|
11918
11977
|
const meta = realtimeMeta.get(dataSourceName);
|
|
11919
11978
|
if (!meta || meta.maxRows === 0) {
|
|
11920
11979
|
if (meta) meta.appended.push(row.$id);
|
|
11921
|
-
landRows(dataSourceName, [row], { mode: 'append', generation });
|
|
11980
|
+
landRows(dataSourceName, [row], { mode: 'append', generation, order });
|
|
11922
11981
|
return;
|
|
11923
11982
|
}
|
|
11924
11983
|
const len = currentRows.length + meta.pending;
|
|
@@ -11943,7 +12002,7 @@ function realtimeAppend(dataSourceName, row, currentRows, generation) {
|
|
|
11943
12002
|
}
|
|
11944
12003
|
meta.pending++;
|
|
11945
12004
|
meta.appended.push(row.$id);
|
|
11946
|
-
landRows(dataSourceName, [row], { mode: 'append', generation })
|
|
12005
|
+
landRows(dataSourceName, [row], { mode: 'append', generation, order })
|
|
11947
12006
|
.then(() => { meta.pending = Math.max(0, meta.pending - 1); });
|
|
11948
12007
|
}
|
|
11949
12008
|
|
|
@@ -11992,6 +12051,7 @@ async function handleTableRealtimeEvent(dataSourceName, databaseId, tableId, sco
|
|
|
11992
12051
|
|
|
11993
12052
|
// Network landings: coalesced per frame (landRows upserts by $id), never the sync mutation path
|
|
11994
12053
|
const { landRows, landRemove } = window.ManifestDataStore;
|
|
12054
|
+
const order = sortSpec(queriesConfig);
|
|
11995
12055
|
|
|
11996
12056
|
if (eventType === 'create') {
|
|
11997
12057
|
const row = payload?.$id ? payload : (payload?.row || payload);
|
|
@@ -12001,9 +12061,9 @@ async function handleTableRealtimeEvent(dataSourceName, databaseId, tableId, sco
|
|
|
12001
12061
|
if (rowMatchesScope && eventMatchesQueries(row, queriesConfig)) {
|
|
12002
12062
|
if (currentRows.find(r => r.$id === row.$id)) {
|
|
12003
12063
|
// Echo of a row already held (optimistic create): merge, never counts as growth
|
|
12004
|
-
landRows(dataSourceName, [row], { mode: 'append', generation });
|
|
12064
|
+
landRows(dataSourceName, [row], { mode: 'append', generation, order });
|
|
12005
12065
|
} else {
|
|
12006
|
-
realtimeAppend(dataSourceName, row, currentRows, generation);
|
|
12066
|
+
realtimeAppend(dataSourceName, row, currentRows, generation, order);
|
|
12007
12067
|
}
|
|
12008
12068
|
}
|
|
12009
12069
|
} else {
|
|
@@ -12024,7 +12084,7 @@ async function handleTableRealtimeEvent(dataSourceName, databaseId, tableId, sco
|
|
|
12024
12084
|
}
|
|
12025
12085
|
if (!existingRow) {
|
|
12026
12086
|
// Row not in list, but matches now - add it (capped like a create)
|
|
12027
|
-
realtimeAppend(dataSourceName, row, currentRows, generation);
|
|
12087
|
+
realtimeAppend(dataSourceName, row, currentRows, generation, order);
|
|
12028
12088
|
return;
|
|
12029
12089
|
}
|
|
12030
12090
|
|
|
@@ -12084,7 +12144,7 @@ async function handleTableRealtimeEvent(dataSourceName, databaseId, tableId, sco
|
|
|
12084
12144
|
const fileIdsChanged = isProjectWithFiles &&
|
|
12085
12145
|
JSON.stringify(existingFileIds) !== JSON.stringify(incomingFileIds);
|
|
12086
12146
|
|
|
12087
|
-
landRows(dataSourceName, [row], { mode: 'append', generation });
|
|
12147
|
+
landRows(dataSourceName, [row], { mode: 'append', generation, order });
|
|
12088
12148
|
|
|
12089
12149
|
// Emit custom event for project file updates so UI can refresh
|
|
12090
12150
|
if (fileIdsChanged && dataSourceName === 'projects') {
|
|
@@ -12264,11 +12324,17 @@ async function loadDataSource(dataSourceName, locale = 'en', options = {}) {
|
|
|
12264
12324
|
return cachedData;
|
|
12265
12325
|
}
|
|
12266
12326
|
|
|
12267
|
-
// In flight for this source+locale: share it (every entry path lands here)
|
|
12327
|
+
// In flight for this source+locale: share it (every entry path lands here);
|
|
12328
|
+
// joining makes it the latest read again
|
|
12268
12329
|
if (loadingPromises.has(cacheKey)) {
|
|
12330
|
+
window.ManifestDataStore.adoptRead?.(dataSourceName, window.ManifestDataStore.loadReadTokens?.get(cacheKey));
|
|
12269
12331
|
return loadingPromises.get(cacheKey);
|
|
12270
12332
|
}
|
|
12271
12333
|
|
|
12334
|
+
// Reads are ordered by call: a $query issued after this load wins over it
|
|
12335
|
+
const readToken = window.ManifestDataStore.beginRead?.(dataSourceName);
|
|
12336
|
+
window.ManifestDataStore.loadReadTokens?.set(cacheKey, readToken);
|
|
12337
|
+
|
|
12272
12338
|
// Loading state: rows already landed stay live; first-ever load clears
|
|
12273
12339
|
const keepRows = hasLiveRows(dataSourceName);
|
|
12274
12340
|
if (!isInitializing) {
|
|
@@ -12403,22 +12469,29 @@ async function loadDataSource(dataSourceName, locale = 'en', options = {}) {
|
|
|
12403
12469
|
if (dataSource.realtime !== false && window.ManifestDataRealtime && window.ManifestDataRealtime.subscribeToTable) {
|
|
12404
12470
|
const rtQueries = Array.isArray(queriesConfig?.default || queriesConfig) ? (queriesConfig.default || queriesConfig) : [];
|
|
12405
12471
|
const limitQ = rtQueries.find(q => Array.isArray(q) && q[0] === 'limit');
|
|
12406
|
-
|
|
12472
|
+
if (!activeQueries.has(dataSourceName) || !realtimeMeta.has(dataSourceName)) {
|
|
12473
|
+
configureRealtimeMeta(dataSourceName, dataSource.realtime, Array.isArray(data) ? data.length : 0, limitQ ? limitQ[1] : null);
|
|
12474
|
+
}
|
|
12407
12475
|
// Events server-filtered where the SDK supports realtime queries; the client
|
|
12408
12476
|
// matcher below still runs. serverFilter: 'scope' (default) | 'all' (alias true) | false
|
|
12409
12477
|
const rtMode = serverFilterMode(dataSource.realtime);
|
|
12410
|
-
const rtFilterSpec = rtMode ? {
|
|
12411
|
-
|
|
12478
|
+
const rtFilterSpec = rtMode ? {
|
|
12479
|
+
get queriesConfig() { return realtimeQueriesFor(dataSourceName, rtQueries); },
|
|
12480
|
+
scope, scopeColumns, mode: rtMode
|
|
12481
|
+
} : null;
|
|
12482
|
+
const subscribe = () => window.ManifestDataRealtime.subscribeToTable(
|
|
12412
12483
|
dataSourceName,
|
|
12413
12484
|
appwriteConfig.databaseId,
|
|
12414
12485
|
tableId,
|
|
12415
12486
|
scope,
|
|
12416
12487
|
async (eventType, payload) => {
|
|
12417
|
-
await handleTableRealtimeEvent(dataSourceName, appwriteConfig.databaseId, tableId, scope, scopeColumns, eventType, payload, generation, rtQueries);
|
|
12488
|
+
await handleTableRealtimeEvent(dataSourceName, appwriteConfig.databaseId, tableId, scope, scopeColumns, eventType, payload, generation, realtimeQueriesFor(dataSourceName, rtQueries));
|
|
12418
12489
|
},
|
|
12419
12490
|
() => !superseded(),
|
|
12420
12491
|
rtFilterSpec
|
|
12421
12492
|
);
|
|
12493
|
+
realtimeBinds.set(dataSourceName, { config: dataSource.realtime, mode: rtMode, rebind: subscribe, defaultLimit: limitQ ? limitQ[1] : null });
|
|
12494
|
+
const unsubscribe = await subscribe();
|
|
12422
12495
|
if (superseded()) { dropSubscription(dataSourceName, unsubscribe); landed = true; return null; }
|
|
12423
12496
|
}
|
|
12424
12497
|
} else if (bucketId) {
|
|
@@ -12594,6 +12667,13 @@ async function loadDataSource(dataSourceName, locale = 'en', options = {}) {
|
|
|
12594
12667
|
|
|
12595
12668
|
if (superseded()) { landed = true; return null; }
|
|
12596
12669
|
|
|
12670
|
+
// A $query issued since this load began: its rows stand, this result never lands
|
|
12671
|
+
if (window.ManifestDataStore.isLatestRead && !window.ManifestDataStore.isLatestRead(dataSourceName, readToken)) {
|
|
12672
|
+
landed = true;
|
|
12673
|
+
if (!isInitializing) setSourceState(dataSourceName, { loading: false });
|
|
12674
|
+
return enhancedData;
|
|
12675
|
+
}
|
|
12676
|
+
|
|
12597
12677
|
// Cache is always safe — the key carries this load's locale.
|
|
12598
12678
|
dataSourceCache.set(cacheKey, enhancedData);
|
|
12599
12679
|
|
|
@@ -12610,6 +12690,7 @@ async function loadDataSource(dataSourceName, locale = 'en', options = {}) {
|
|
|
12610
12690
|
// Network landing (coalesced per frame, merges by $id); resolves once visible
|
|
12611
12691
|
if (!isInitializing && !staleLocale) {
|
|
12612
12692
|
landed = true;
|
|
12693
|
+
clearActiveQuery(dataSourceName, Array.isArray(enhancedData) ? enhancedData.length : 0);
|
|
12613
12694
|
await landRows(dataSourceName, enhancedData, { mode: 'replace', loading: false, error: null, ready: true, fresh: true, generation });
|
|
12614
12695
|
}
|
|
12615
12696
|
|
|
@@ -12780,12 +12861,38 @@ async function initializeDataSourcesPlugin() {
|
|
|
12780
12861
|
}
|
|
12781
12862
|
|
|
12782
12863
|
// Export loadDataSource for use by team change listener
|
|
12864
|
+
// Catch-up: events missed while offline or asleep never arrive, so live sources
|
|
12865
|
+
// refetch (their active $query, else the default load) on reconnect or wake
|
|
12866
|
+
const CATCH_UP_HIDDEN_MS = 60000;
|
|
12867
|
+
let hiddenSince = document.hidden ? Date.now() : null;
|
|
12868
|
+
let catchUpTimer = null;
|
|
12869
|
+
const catchUpLiveSources = () => {
|
|
12870
|
+
clearTimeout(catchUpTimer);
|
|
12871
|
+
catchUpTimer = setTimeout(() => {
|
|
12872
|
+
for (const name of realtimeBinds.keys()) {
|
|
12873
|
+
const active = activeQueries.get(name);
|
|
12874
|
+
const handler = active && window.ManifestDataProxiesAppwrite?.createAppwriteMethodsHandler?.(name, reloadDataSource);
|
|
12875
|
+
Promise.resolve(handler ? handler('$query', active) : reloadDataSource(name)).catch(() => { /* $error carries it */ });
|
|
12876
|
+
}
|
|
12877
|
+
}, 250);
|
|
12878
|
+
};
|
|
12879
|
+
window.addEventListener('online', catchUpLiveSources);
|
|
12880
|
+
document.addEventListener('visibilitychange', () => {
|
|
12881
|
+
if (document.hidden) { hiddenSince = Date.now(); return; }
|
|
12882
|
+
const away = hiddenSince !== null ? Date.now() - hiddenSince : 0;
|
|
12883
|
+
hiddenSince = null;
|
|
12884
|
+
if (away >= CATCH_UP_HIDDEN_MS) catchUpLiveSources();
|
|
12885
|
+
});
|
|
12886
|
+
|
|
12783
12887
|
window.ManifestDataMain = {
|
|
12784
12888
|
loadDataSource,
|
|
12785
12889
|
reloadDataSource,
|
|
12786
12890
|
_loadDataSource: reloadDataSource, // Internal: every user is a reload-after-mutation
|
|
12787
12891
|
filterFilesByScope, // Export for use by getFilesForEntry
|
|
12788
|
-
requiresIdentity
|
|
12892
|
+
requiresIdentity,
|
|
12893
|
+
setActiveQuery,
|
|
12894
|
+
forgetLiveSource,
|
|
12895
|
+
getActiveQuery: (dataSourceName) => activeQueries.get(dataSourceName) || null
|
|
12789
12896
|
};
|
|
12790
12897
|
|
|
12791
12898
|
// Listen for manifest:dev-reload (fired by mnfst-run when a data file changes).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-gWLSeVPqCLMiUZB8MU7GqMg3x2yULFUsp8nTTZrPp/9Dlkix42rBn9yIimvwrHqZ",
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-7gDP0QYT/sjPnPxKB0DahCW7wGTjVeKzqRHJSkqv4R4J8CtcmB7b6qTEsyK4iGoh",
|
|
4
4
|
"manifest.appwrite.presences.js": "sha384-LINPhIPTCK+rA8zd+HPUzMSEgH6Sl2vQMEyItT97bnEE2FYGYKqjXX+CWdt6nl9z",
|
|
5
5
|
"manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
|
|
6
6
|
"manifest.charts.js": "sha384-AFbP7mQnigy7DU1s+YE30yKTeQAKfgNazhbfSNbfd9ZpLgeulZKaPi/fAq3gJHDO",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"manifest.color.js": "sha384-6Rv3LxyTcZNjrhtayQfqRdCx0uSZ4BiEbgEI98I62eTvp8Aw7LBIoNJ0Je1oktwL",
|
|
10
10
|
"manifest.colorpicker.js": "sha384-P+Zx0QzhMGfku8s3yEskTte4/iXCGVX3zdhu42IGNfFcSmhOW+nqVK7w+uczWRGY",
|
|
11
11
|
"manifest.combobox.js": "sha384-/lJo6vaxKjgnBSRs/dzkhK1dzGk3GBw8FISoNJZB70mwAVwu1k5veZyBXjOb4keS",
|
|
12
|
-
"manifest.components.js": "sha384-
|
|
12
|
+
"manifest.components.js": "sha384-1el5WMdgmzu/2ocaYN21OjLi/lfjllvA8aju1J3knYuOizw+XFfJU1+rvGqYW7qk",
|
|
13
13
|
"manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
|
|
14
|
-
"manifest.data.js": "sha384-
|
|
14
|
+
"manifest.data.js": "sha384-mV2B+tijlZgcD/MFDLzw6w+6fGd0rZpGTTOJEyv6LJYwRydD3XtekFaMvZCWzudH",
|
|
15
15
|
"manifest.datepicker.js": "sha384-EzlMwvIxlla/0BuyhAEqxN0M8TGcWIWgEIg840V0akKQQK1uY648wPWMkobvtq/o",
|
|
16
16
|
"manifest.defer.js": "sha384-PRp7+dCZHnnl55rX2xrHutLrQnszHo7o5o9Tq28M/yjLZPuXDzcwQNxCdvbtCYSz",
|
|
17
17
|
"manifest.device.js": "sha384-YeQaS56L8IILqrQNBSeAOLwIh5DuAOrE60cYLK1+46qJtUrXlAvqGe2j5mbV4Vq7",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"manifest.status.js": "sha384-ofu7nBnVIGZ1U1o2R9d2H3V8aEMPUCVbl5FO3gIToXqi0oa36fTviEdh5UU7Kitw",
|
|
30
30
|
"manifest.submissions.js": "sha384-v9eS47ytAfTGIKAyVnbd0QWegucVS7yduvigqfsxxoqXmbaEoy0M2y+BiI4xeZBd",
|
|
31
31
|
"manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
|
|
32
|
-
"manifest.sw.js": "sha384-
|
|
32
|
+
"manifest.sw.js": "sha384-tJoDnCGd8KNuPQSC2U45K3sFnVP+FKP/Qddzg4BoFsBjwhwQCk/FDo2i54aS/l+s",
|
|
33
33
|
"manifest.tabs.js": "sha384-otU09H7jnawVKQdLAYpMCd3jx00tgyPVr42D2hLIBzN5dG4se505YesavdnMqEi1",
|
|
34
34
|
"manifest.tailwind.js": "sha384-yuP3LEvWU+QVjxjkZ0YhErtC9RrGmhOmHjjFjhS9obqZbp5/KTIEnSR0CXDvHE0B",
|
|
35
35
|
"manifest.toasts.js": "sha384-UpOz9fAdGeGUhL0NamBg5iPepEfIy73p9HYdcxfOQC5b7CVsl7Our0skdZzaLNcC",
|
package/lib/manifest.sw.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
// Build stamps the published version here; unstamped (dev) falls back to the
|
|
18
18
|
// registration URL's `v`, then 'dev'.
|
|
19
|
-
const BUILD_VERSION = '0.5.
|
|
19
|
+
const BUILD_VERSION = '0.5.274';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
// Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnfst",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.274",
|
|
4
4
|
"private": false,
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"templates/starter",
|
|
@@ -50,7 +50,9 @@
|
|
|
50
50
|
"test:e2e:magic": "node tests/e2e/magic-one-arg.e2e.mjs",
|
|
51
51
|
"test:e2e:markdown-safe": "node tests/e2e/markdown-safe.e2e.mjs",
|
|
52
52
|
"test:e2e:upload": "node tests/e2e/upload-first-load.e2e.mjs",
|
|
53
|
+
"test:e2e:test-kit": "node tests/e2e/test-kit-journeys.e2e.mjs",
|
|
53
54
|
"test:e2e:submissions": "node tests/e2e/submissions.e2e.mjs",
|
|
55
|
+
"test:e2e:modules": "node tests/e2e/modules.e2e.mjs",
|
|
54
56
|
"lint": "echo 'No linting configured'",
|
|
55
57
|
"release:docs": "node scripts/release-bump.mjs packages/docs && cd packages/docs && npm publish --auth-type=web",
|
|
56
58
|
"release:check": "node scripts/release-check.mjs"
|