mnfst 0.5.263 → 0.5.265
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.auth.js +4 -25
- package/lib/manifest.appwrite.data.js +1 -1
- package/lib/manifest.data.js +102 -72
- package/lib/manifest.export.js +8 -1
- package/lib/manifest.integrity.json +7 -7
- package/lib/manifest.markdown.js +1 -2
- package/lib/manifest.sw.js +1 -1
- package/lib/manifest.virtual.js +30 -7
- package/package.json +3 -1
|
@@ -2707,40 +2707,19 @@ async function resolvePersonalTeamName(nameConfig) {
|
|
|
2707
2707
|
// Remove '$x.' prefix and resolve path
|
|
2708
2708
|
const path = nameConfig.substring(3);
|
|
2709
2709
|
|
|
2710
|
-
//
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
// Split path and navigate through $x proxy
|
|
2710
|
+
// Data store, not the $x proxy: unloaded paths must read as null, not a loading proxy
|
|
2711
|
+
const dataStore = Alpine.store('data');
|
|
2712
|
+
if (dataStore) {
|
|
2714
2713
|
const parts = path.split('.');
|
|
2715
|
-
let value =
|
|
2714
|
+
let value = dataStore;
|
|
2716
2715
|
for (const part of parts) {
|
|
2717
2716
|
if (value && typeof value === 'object' && part in value) {
|
|
2718
2717
|
value = value[part];
|
|
2719
|
-
// If value is a Promise, wait for it
|
|
2720
|
-
if (value && typeof value.then === 'function') {
|
|
2721
|
-
value = await value;
|
|
2722
|
-
}
|
|
2723
2718
|
} else {
|
|
2724
|
-
// Data source may not be loaded yet - silently return null
|
|
2725
2719
|
return null;
|
|
2726
2720
|
}
|
|
2727
2721
|
}
|
|
2728
2722
|
return value || null;
|
|
2729
|
-
} else {
|
|
2730
|
-
// Fallback: try data store directly
|
|
2731
|
-
const dataStore = Alpine.store('data');
|
|
2732
|
-
if (dataStore) {
|
|
2733
|
-
const parts = path.split('.');
|
|
2734
|
-
let value = dataStore;
|
|
2735
|
-
for (const part of parts) {
|
|
2736
|
-
if (value && typeof value === 'object' && part in value) {
|
|
2737
|
-
value = value[part];
|
|
2738
|
-
} else {
|
|
2739
|
-
return null;
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
|
-
return value || null;
|
|
2743
|
-
}
|
|
2744
2723
|
}
|
|
2745
2724
|
} catch (error) {
|
|
2746
2725
|
// Data source may not be loaded yet - silently return null
|
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.265';
|
|
6
6
|
|
|
7
7
|
/* Manifest Data Sources - Configuration */
|
|
8
8
|
|
|
@@ -6735,12 +6735,19 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6735
6735
|
: [];
|
|
6736
6736
|
|
|
6737
6737
|
let loading = false;
|
|
6738
|
+
let reloadQueued = false;
|
|
6738
6739
|
let error = null;
|
|
6739
6740
|
let unsubscribeCallbacks = [];
|
|
6740
6741
|
|
|
6742
|
+
const tableRows = () => window.Alpine?.store?.('data')?.[tableName];
|
|
6743
|
+
|
|
6741
6744
|
// Load files function
|
|
6742
6745
|
const loadFiles = async () => {
|
|
6743
|
-
|
|
6746
|
+
// A request during a load may carry newer data than that load read
|
|
6747
|
+
if (loading) {
|
|
6748
|
+
reloadQueued = true;
|
|
6749
|
+
return;
|
|
6750
|
+
}
|
|
6744
6751
|
|
|
6745
6752
|
loading = true;
|
|
6746
6753
|
error = null;
|
|
@@ -6802,9 +6809,9 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6802
6809
|
files.push(...loadedFiles);
|
|
6803
6810
|
|
|
6804
6811
|
// Sync lastSeenFileIds so the watch effect doesn't false-positive
|
|
6805
|
-
const
|
|
6806
|
-
if (
|
|
6807
|
-
const entry =
|
|
6812
|
+
const rows = tableRows();
|
|
6813
|
+
if (Array.isArray(rows)) {
|
|
6814
|
+
const entry = rows.find(item => item.$id === entryId);
|
|
6808
6815
|
if (entry) {
|
|
6809
6816
|
const currentFileIds = entry[columnName || 'fileIds'] || [];
|
|
6810
6817
|
lastSeenFileIds = JSON.stringify(currentFileIds);
|
|
@@ -6815,6 +6822,10 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6815
6822
|
error = err.message || String(err);
|
|
6816
6823
|
} finally {
|
|
6817
6824
|
loading = false;
|
|
6825
|
+
if (reloadQueued) {
|
|
6826
|
+
reloadQueued = false;
|
|
6827
|
+
loadFiles();
|
|
6828
|
+
}
|
|
6818
6829
|
}
|
|
6819
6830
|
};
|
|
6820
6831
|
|
|
@@ -6840,10 +6851,10 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6840
6851
|
// Use requestAnimationFrame for immediate execution
|
|
6841
6852
|
requestAnimationFrame(() => {
|
|
6842
6853
|
// Check if file is linked to this entry
|
|
6843
|
-
const
|
|
6844
|
-
if (
|
|
6845
|
-
const entry = Array.isArray(
|
|
6846
|
-
?
|
|
6854
|
+
const rows = tableRows();
|
|
6855
|
+
if (rows) {
|
|
6856
|
+
const entry = Array.isArray(rows)
|
|
6857
|
+
? rows.find(item => item.$id === entryId)
|
|
6847
6858
|
: null;
|
|
6848
6859
|
if (entry && entry[columnName || 'fileIds']?.includes(e.detail.fileId)) {
|
|
6849
6860
|
loadFiles();
|
|
@@ -6881,14 +6892,15 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6881
6892
|
|
|
6882
6893
|
// Watch table data for fileIds changes; tracked per entry to avoid false positives
|
|
6883
6894
|
let lastSeenFileIds = null;
|
|
6895
|
+
let lastReconciledFileIds = null;
|
|
6884
6896
|
|
|
6885
6897
|
const watchTableData = () => {
|
|
6886
6898
|
if (typeof Alpine === 'undefined') return;
|
|
6887
6899
|
|
|
6888
6900
|
const unwatch = Alpine.effect(() => {
|
|
6889
|
-
const
|
|
6890
|
-
if (
|
|
6891
|
-
const entry =
|
|
6901
|
+
const rows = tableRows();
|
|
6902
|
+
if (Array.isArray(rows)) {
|
|
6903
|
+
const entry = rows.find(item => item.$id === entryId);
|
|
6892
6904
|
if (entry) {
|
|
6893
6905
|
const currentFileIds = entry[columnName || 'fileIds'] || [];
|
|
6894
6906
|
const currentFileIdsStr = JSON.stringify(currentFileIds);
|
|
@@ -6900,9 +6912,9 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6900
6912
|
|
|
6901
6913
|
loadFiles().then(() => {
|
|
6902
6914
|
// Re-verify fileIds in case they changed during load
|
|
6903
|
-
const
|
|
6904
|
-
if (
|
|
6905
|
-
const entryAfter =
|
|
6915
|
+
const rowsAfter = tableRows();
|
|
6916
|
+
if (Array.isArray(rowsAfter)) {
|
|
6917
|
+
const entryAfter = rowsAfter.find(item => item.$id === entryId);
|
|
6906
6918
|
if (entryAfter) {
|
|
6907
6919
|
const fileIdsAfter = entryAfter[columnName || 'fileIds'] || [];
|
|
6908
6920
|
lastSeenFileIds = JSON.stringify(fileIdsAfter);
|
|
@@ -6920,7 +6932,9 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6920
6932
|
const fileIdsMatch = currentFileIds.length === filesFileIds.length &&
|
|
6921
6933
|
currentFileIds.every(id => filesFileIds.includes(id));
|
|
6922
6934
|
|
|
6923
|
-
|
|
6935
|
+
// Once per fileIds value: an id the bucket no longer lists never matches
|
|
6936
|
+
if (!fileIdsMatch && !loading && lastSeenFileIds !== null && lastReconciledFileIds !== currentFileIdsStr) {
|
|
6937
|
+
lastReconciledFileIds = currentFileIdsStr;
|
|
6924
6938
|
lastSeenFileIds = JSON.stringify(currentFileIds);
|
|
6925
6939
|
loadFiles().catch(err => {
|
|
6926
6940
|
console.error('[Manifest Data] Failed to reload files after sync check:', err);
|
|
@@ -6939,7 +6953,7 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6939
6953
|
subscribeToEvents();
|
|
6940
6954
|
watchTableData();
|
|
6941
6955
|
|
|
6942
|
-
loadFiles();
|
|
6956
|
+
if (!loading) loadFiles();
|
|
6943
6957
|
|
|
6944
6958
|
const manager = {
|
|
6945
6959
|
files,
|
|
@@ -6947,6 +6961,7 @@ function createReactiveFileManager(tableName, entryId, bucketName, columnName) {
|
|
|
6947
6961
|
error: () => error,
|
|
6948
6962
|
reload: loadFiles,
|
|
6949
6963
|
destroy: () => {
|
|
6964
|
+
reloadQueued = false;
|
|
6950
6965
|
unsubscribeCallbacks.forEach(cb => cb());
|
|
6951
6966
|
reactiveFileManagers.delete(key);
|
|
6952
6967
|
}
|
|
@@ -7171,9 +7186,26 @@ async function getFilesForEntry(tableName, entryId, bucketId, fileIdsColumn = 'f
|
|
|
7171
7186
|
return entryFiles;
|
|
7172
7187
|
}
|
|
7173
7188
|
|
|
7189
|
+
// Link/unlink rewrite the whole fileIds value, so one entry's writes run one at a time
|
|
7190
|
+
const entryFileWrites = new Map();
|
|
7191
|
+
function queueEntryFileWrite(tableName, entryId, fileIdsColumn, write) {
|
|
7192
|
+
const key = `${tableName}:${entryId}:${fileIdsColumn}`;
|
|
7193
|
+
const result = (entryFileWrites.get(key) || Promise.resolve()).then(write);
|
|
7194
|
+
const tail = result.catch(() => { });
|
|
7195
|
+
entryFileWrites.set(key, tail);
|
|
7196
|
+
tail.then(() => {
|
|
7197
|
+
if (entryFileWrites.get(key) === tail) entryFileWrites.delete(key);
|
|
7198
|
+
});
|
|
7199
|
+
return result;
|
|
7200
|
+
}
|
|
7201
|
+
|
|
7174
7202
|
// Link a file to a table entry by adding the file ID to the entry's fileIds array
|
|
7175
7203
|
// Generic function - works with any table and any scope
|
|
7176
|
-
|
|
7204
|
+
function linkFileToEntry(tableName, entryId, fileId, fileIdsColumn = 'fileIds') {
|
|
7205
|
+
return queueEntryFileWrite(tableName, entryId, fileIdsColumn, () => writeFileLink(tableName, entryId, fileId, fileIdsColumn));
|
|
7206
|
+
}
|
|
7207
|
+
|
|
7208
|
+
async function writeFileLink(tableName, entryId, fileId, fileIdsColumn) {
|
|
7177
7209
|
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
7178
7210
|
const tableDataSource = manifest?.data?.[tableName];
|
|
7179
7211
|
|
|
@@ -7188,36 +7220,23 @@ async function linkFileToEntry(tableName, entryId, fileId, fileIdsColumn = 'file
|
|
|
7188
7220
|
throw new Error(`[Manifest Data] Invalid Appwrite configuration for "${tableName}"`);
|
|
7189
7221
|
}
|
|
7190
7222
|
|
|
7191
|
-
//
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
fileIds = storeEntry[fileIdsColumn];
|
|
7198
|
-
}
|
|
7199
|
-
}
|
|
7200
|
-
|
|
7201
|
-
// If store doesn't have it, read from database
|
|
7202
|
-
if (fileIds === null) {
|
|
7203
|
-
const entry = await window.ManifestDataAppwrite.getTableRow(
|
|
7204
|
-
appwriteConfig.databaseId,
|
|
7205
|
-
tableId,
|
|
7206
|
-
entryId
|
|
7207
|
-
);
|
|
7208
|
-
|
|
7209
|
-
if (!entry) {
|
|
7210
|
-
throw new Error(`[Manifest Data] Entry "${entryId}" not found in table "${tableName}"`);
|
|
7211
|
-
}
|
|
7223
|
+
// Server row, not the store: a late realtime echo or reload can move the store behind committed writes
|
|
7224
|
+
const entry = await window.ManifestDataAppwrite.getTableRow(
|
|
7225
|
+
appwriteConfig.databaseId,
|
|
7226
|
+
tableId,
|
|
7227
|
+
entryId
|
|
7228
|
+
);
|
|
7212
7229
|
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
if (fileIds === undefined) {
|
|
7217
|
-
// Column doesn't exist - throw a helpful error
|
|
7218
|
-
throw new Error(`[Manifest Data] The "${fileIdsColumn}" column does not exist in the "${tableName}" table. Please add a "${fileIdsColumn}" column (type: string array) to the table in Appwrite.`);
|
|
7219
|
-
}
|
|
7230
|
+
if (!entry) {
|
|
7231
|
+
throw new Error(`[Manifest Data] Entry "${entryId}" not found in table "${tableName}"`);
|
|
7232
|
+
}
|
|
7220
7233
|
|
|
7234
|
+
// Get or initialize fileIds array (using configurable column name)
|
|
7235
|
+
// Check if the column exists (if it's undefined, the column might not exist in the table schema)
|
|
7236
|
+
let fileIds = entry[fileIdsColumn];
|
|
7237
|
+
if (fileIds === undefined) {
|
|
7238
|
+
// Column doesn't exist - throw a helpful error
|
|
7239
|
+
throw new Error(`[Manifest Data] The "${fileIdsColumn}" column does not exist in the "${tableName}" table. Please add a "${fileIdsColumn}" column (type: string array) to the table in Appwrite.`);
|
|
7221
7240
|
}
|
|
7222
7241
|
|
|
7223
7242
|
if (!Array.isArray(fileIds)) {
|
|
@@ -7383,7 +7402,11 @@ async function unlinkFileFromAllEntries(fileId) {
|
|
|
7383
7402
|
|
|
7384
7403
|
// Unlink a file from a table entry by removing the file ID from the entry's fileIds array
|
|
7385
7404
|
// Generic function - works with any table and any scope
|
|
7386
|
-
|
|
7405
|
+
function unlinkFileFromEntry(tableName, entryId, fileId, fileIdsColumn = 'fileIds') {
|
|
7406
|
+
return queueEntryFileWrite(tableName, entryId, fileIdsColumn, () => writeFileUnlink(tableName, entryId, fileId, fileIdsColumn));
|
|
7407
|
+
}
|
|
7408
|
+
|
|
7409
|
+
async function writeFileUnlink(tableName, entryId, fileId, fileIdsColumn) {
|
|
7387
7410
|
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
7388
7411
|
const tableDataSource = manifest?.data?.[tableName];
|
|
7389
7412
|
|
|
@@ -7677,7 +7700,8 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
7677
7700
|
|
|
7678
7701
|
// Core handler (named so $duplicate etc. can recurse)
|
|
7679
7702
|
const handleMethod = async function (method, ...args) {
|
|
7680
|
-
|
|
7703
|
+
const sourceUnloaded = args[3]?.sourceUnloaded === true;
|
|
7704
|
+
if (!sourceUnloaded) clearErrorState();
|
|
7681
7705
|
|
|
7682
7706
|
try {
|
|
7683
7707
|
const manifest = await window.ManifestDataConfig?.ensureManifest?.();
|
|
@@ -8222,12 +8246,12 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
8222
8246
|
finalPermissions = Array.isArray(permissions) ? permissions : [permissions];
|
|
8223
8247
|
}
|
|
8224
8248
|
|
|
8225
|
-
//
|
|
8226
|
-
const validOnProgress =
|
|
8249
|
+
// The 4th arg may be $upload's options object, not a callback
|
|
8250
|
+
const validOnProgress = typeof onProgress === 'function' ? onProgress : undefined;
|
|
8227
8251
|
|
|
8228
8252
|
// Use optimistic update via mutation system
|
|
8229
|
-
const addEntryToStore = window.ManifestDataMutations?.addEntryToStore;
|
|
8230
|
-
const removeEntryFromStore = window.ManifestDataMutations?.removeEntryFromStore;
|
|
8253
|
+
const addEntryToStore = sourceUnloaded ? null : window.ManifestDataMutations?.addEntryToStore;
|
|
8254
|
+
const removeEntryFromStore = sourceUnloaded ? null : window.ManifestDataMutations?.removeEntryFromStore;
|
|
8231
8255
|
const writeOptions = { generation: window.ManifestDataStore?.sourceGeneration?.(dataSourceName) };
|
|
8232
8256
|
const manifest = await window.ManifestDataConfig.ensureManifest();
|
|
8233
8257
|
const dataSource = manifest?.data?.[dataSourceName];
|
|
@@ -8368,9 +8392,17 @@ function createAppwriteMethodsHandler(dataSourceName, reloadDataSource) {
|
|
|
8368
8392
|
}
|
|
8369
8393
|
}
|
|
8370
8394
|
|
|
8395
|
+
// The source may have landed during the upload, from a list without this file
|
|
8396
|
+
if (sourceUnloaded && window.ManifestDataStore?.getRawData?.(dataSourceName) != null) {
|
|
8397
|
+
const landed = window.ManifestDataStore.getRawData(dataSourceName);
|
|
8398
|
+
if (!Array.isArray(landed) || !landed.some(row => row.$id === result.$id)) {
|
|
8399
|
+
window.ManifestDataMutations?.addEntryToStore?.(dataSourceName, result, writeOptions);
|
|
8400
|
+
}
|
|
8401
|
+
}
|
|
8402
|
+
|
|
8371
8403
|
// We already have the real file from the API response, so no
|
|
8372
8404
|
// background reload; scope filtering (if any) is handled by realtime.
|
|
8373
|
-
if (!addEntryToStore) {
|
|
8405
|
+
if (!addEntryToStore && !sourceUnloaded) {
|
|
8374
8406
|
// Fallback: reload lands through loadDataSource (coalesced landing)
|
|
8375
8407
|
if (window.ManifestDataStore?.dataSourceCache) {
|
|
8376
8408
|
const cacheKey = `${dataSourceName}:en`;
|
|
@@ -9083,14 +9115,15 @@ function createUploadMethod(dataSourceName, reloadDataSource) {
|
|
|
9083
9115
|
throw new Error(`[Manifest Data] Storage bucket "${resolvedBucketName}" not found in manifest`);
|
|
9084
9116
|
}
|
|
9085
9117
|
|
|
9086
|
-
//
|
|
9087
|
-
const
|
|
9088
|
-
if (
|
|
9118
|
+
// Direct handler: $x[bucket] has no $create until that source has been read
|
|
9119
|
+
const createHandler = window.ManifestDataProxiesAppwrite?.createAppwriteMethodsHandler;
|
|
9120
|
+
if (!createHandler) {
|
|
9089
9121
|
throw new Error(`[Manifest Data] Bucket "${resolvedBucketName}" is not available`);
|
|
9090
9122
|
}
|
|
9123
|
+
const bucketMethods = createHandler(resolvedBucketName, reloadDataSource);
|
|
9091
9124
|
|
|
9092
9125
|
// Get helper functions for uploading state
|
|
9093
|
-
const { setUploadingFile, clearUploadingFile } = window.ManifestDataStore || {};
|
|
9126
|
+
const { setUploadingFile, clearUploadingFile, getRawData } = window.ManifestDataStore || {};
|
|
9094
9127
|
|
|
9095
9128
|
// Generate temporary file IDs for tracking upload state
|
|
9096
9129
|
const fileIds = files.map(file => {
|
|
@@ -9108,13 +9141,21 @@ function createUploadMethod(dataSourceName, reloadDataSource) {
|
|
|
9108
9141
|
}
|
|
9109
9142
|
|
|
9110
9143
|
try {
|
|
9144
|
+
// First load before any write: a row pushed into an unread store would block it
|
|
9145
|
+
if (getRawData?.(resolvedBucketName) == null) {
|
|
9146
|
+
await reloadDataSource(resolvedBucketName);
|
|
9147
|
+
}
|
|
9148
|
+
// Still unread (load failed or was denied): upload without a store row, keeping its error and a later load
|
|
9149
|
+
const sourceUnloaded = getRawData?.(resolvedBucketName) == null;
|
|
9150
|
+
|
|
9111
9151
|
// Upload files (single or multiple)
|
|
9112
9152
|
const uploadPromises = files.map((file, index) => {
|
|
9113
9153
|
const tempFileId = fileIds[index];
|
|
9114
|
-
return $
|
|
9154
|
+
return bucketMethods('$create', file, tempFileId, null, {
|
|
9115
9155
|
entryId: entryId,
|
|
9116
9156
|
table: dataSourceName,
|
|
9117
|
-
fileIdsColumn: resolvedColumnName
|
|
9157
|
+
fileIdsColumn: resolvedColumnName,
|
|
9158
|
+
sourceUnloaded
|
|
9118
9159
|
}).then(result => {
|
|
9119
9160
|
// Clear uploading state for this file
|
|
9120
9161
|
if (clearUploadingFile) {
|
|
@@ -9236,25 +9277,14 @@ if (typeof window !== 'undefined') {
|
|
|
9236
9277
|
}
|
|
9237
9278
|
}
|
|
9238
9279
|
|
|
9239
|
-
// 2. Alpine
|
|
9240
|
-
try {
|
|
9241
|
-
const magicFn = window.Alpine?.magic?.('x');
|
|
9242
|
-
if (magicFn && typeof magicFn === 'function') {
|
|
9243
|
-
const proxy = magicFn();
|
|
9244
|
-
if (proxy) return proxy;
|
|
9245
|
-
}
|
|
9246
|
-
} catch (e) {
|
|
9247
|
-
// Not ready — continue to fallback
|
|
9248
|
-
}
|
|
9249
|
-
|
|
9250
|
-
// 3. Loading proxy (lets code run while Alpine initializes)
|
|
9280
|
+
// 2. Loading proxy (lets code run while Alpine initializes)
|
|
9251
9281
|
const createLoadingProxy = window.ManifestDataProxiesCore?.createLoadingProxy;
|
|
9252
9282
|
if (createLoadingProxy) {
|
|
9253
9283
|
const loadingProxy = createLoadingProxy();
|
|
9254
9284
|
if (loadingProxy) return loadingProxy;
|
|
9255
9285
|
}
|
|
9256
9286
|
|
|
9257
|
-
//
|
|
9287
|
+
// 3. Cached self-chaining proxy (same instance keeps chaining safe)
|
|
9258
9288
|
if (!cachedFallbackProxy) {
|
|
9259
9289
|
cachedFallbackProxy = new Proxy({}, {
|
|
9260
9290
|
get(target, prop) {
|
package/lib/manifest.export.js
CHANGED
|
@@ -368,11 +368,18 @@ function initializeExportPlugin() {
|
|
|
368
368
|
|
|
369
369
|
// ------- Tabular exports (CSV, JSON) --------------------------------
|
|
370
370
|
|
|
371
|
+
function readXMagic() {
|
|
372
|
+
const A = window.Alpine;
|
|
373
|
+
if (!A) return undefined;
|
|
374
|
+
const expr = 'typeof $x !== "undefined" ? $x : undefined';
|
|
375
|
+
return window.ManifestUI?._eval ? window.ManifestUI._eval(expr) : A.evaluate(document.body, expr);
|
|
376
|
+
}
|
|
377
|
+
|
|
371
378
|
function resolveDataset(opts) {
|
|
372
379
|
if (Array.isArray(opts.data)) return opts.data;
|
|
373
380
|
if (opts.data && typeof opts.data === 'object') return opts.data;
|
|
374
381
|
if (opts.source) {
|
|
375
|
-
const x = window.$x || (
|
|
382
|
+
const x = window.$x || readXMagic();
|
|
376
383
|
if (x && x[opts.source] != null) return x[opts.source];
|
|
377
384
|
}
|
|
378
385
|
throw new Error('csv/json export needs `source: "<name>"` or `data: <value>`');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"manifest.appwrite.auth.js": "sha384-
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
2
|
+
"manifest.appwrite.auth.js": "sha384-gWLSeVPqCLMiUZB8MU7GqMg3x2yULFUsp8nTTZrPp/9Dlkix42rBn9yIimvwrHqZ",
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-oVT9VZ8V80FW+0U0YH7DhoNUzzvpgzerUIo0Ns4mMlOVuMFnihi52+RcuvOErLZ5",
|
|
4
4
|
"manifest.appwrite.presences.js": "sha384-/CagPsgWhO1sWEevCNGJmZ/ezRK9YCjLjvF7hxNSM4gVlJmEVtfSLfF7wnsRq441",
|
|
5
5
|
"manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
|
|
6
6
|
"manifest.charts.js": "sha384-AFbP7mQnigy7DU1s+YE30yKTeQAKfgNazhbfSNbfd9ZpLgeulZKaPi/fAq3gJHDO",
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
"manifest.combobox.js": "sha384-/lJo6vaxKjgnBSRs/dzkhK1dzGk3GBw8FISoNJZB70mwAVwu1k5veZyBXjOb4keS",
|
|
12
12
|
"manifest.components.js": "sha384-BUFA8h+G5Plr82sV7bKzO42pPoiRZwRQcKj1lt2ROFiKjjlkayU/vmkAFqEsdBA+",
|
|
13
13
|
"manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
|
|
14
|
-
"manifest.data.js": "sha384-
|
|
14
|
+
"manifest.data.js": "sha384-IGqPG+nOy9bH2l+gNGLF7GL4iYGl+h6N+CWy2Z15ddE13qluCtm2g4DTTOXqoX3L",
|
|
15
15
|
"manifest.datepicker.js": "sha384-EzlMwvIxlla/0BuyhAEqxN0M8TGcWIWgEIg840V0akKQQK1uY648wPWMkobvtq/o",
|
|
16
16
|
"manifest.defer.js": "sha384-5cHzFTbx+cZmGpk9FuiUtW3ciC9NvvHwJeHP7xL5yiZVp9PhMWVdQ7L9y6ju2yoo",
|
|
17
17
|
"manifest.device.js": "sha384-YeQaS56L8IILqrQNBSeAOLwIh5DuAOrE60cYLK1+46qJtUrXlAvqGe2j5mbV4Vq7",
|
|
18
18
|
"manifest.dropdowns.js": "sha384-TlFrYVWTXvpUmGnYaAk2til4lu0p6w5YcmWWEzZAokzd2qlmoyRLLXXVuYAK/AlR",
|
|
19
19
|
"manifest.edit.js": "sha384-MOgQNdNLeHijhR0u2W6ntoOulKFglsATCFDqkinesOU15tHoILk/JNzHKkGi5dUG",
|
|
20
|
-
"manifest.export.js": "sha384-
|
|
20
|
+
"manifest.export.js": "sha384-C4W5LrGQFnSILRWoWOCliajUK6rAzNW+EliogRx72vD1cUOYScSdfzHNbjSWv5XU",
|
|
21
21
|
"manifest.icons.js": "sha384-kKOINpX70YzNO3FvkV6umrmO3f0KIu0DNbwB+ej55a7y/lhU7v/myQtXL0bwCTbt",
|
|
22
22
|
"manifest.localization.js": "sha384-EImsIw8Z3l13V5eH9ZJF/yfsOfIvR1oPRNSArANkPji7V8O3IRf6zMwsNiAGj3Hk",
|
|
23
|
-
"manifest.markdown.js": "sha384-
|
|
23
|
+
"manifest.markdown.js": "sha384-SQqvC175/Ai3yLNjWNK1EOwrxVpoCrZVFSfzA5wg2btrQPQmNNQk3ICGeBY6f502",
|
|
24
24
|
"manifest.native.js": "sha384-YeQaS56L8IILqrQNBSeAOLwIh5DuAOrE60cYLK1+46qJtUrXlAvqGe2j5mbV4Vq7",
|
|
25
25
|
"manifest.payments.js": "sha384-8pofk2zhxtapPMpwnFyTelPMrYhShNhDCE722uQh/EYFvZFuPLmSdgunqsarVQjv",
|
|
26
26
|
"manifest.rich.text.js": "sha384-ZBV9jXmu2nmprEHicddRE/m7nR4RPZtVc969Jte0+EJYBcVph7itkjcgN/61PyeC",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
29
29
|
"manifest.status.js": "sha384-ofu7nBnVIGZ1U1o2R9d2H3V8aEMPUCVbl5FO3gIToXqi0oa36fTviEdh5UU7Kitw",
|
|
30
30
|
"manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
|
|
31
|
-
"manifest.sw.js": "sha384-
|
|
31
|
+
"manifest.sw.js": "sha384-kIFn/uTJ/LaTK10m44lza6qt+jfnLRyWFdmo/A5aNUD7G7V3KUxZPXUFLwnuiw2N",
|
|
32
32
|
"manifest.tabs.js": "sha384-otU09H7jnawVKQdLAYpMCd3jx00tgyPVr42D2hLIBzN5dG4se505YesavdnMqEi1",
|
|
33
33
|
"manifest.tailwind.js": "sha384-yuP3LEvWU+QVjxjkZ0YhErtC9RrGmhOmHjjFjhS9obqZbp5/KTIEnSR0CXDvHE0B",
|
|
34
34
|
"manifest.toasts.js": "sha384-3zkWxzw693pxg3QDFsoYCA3CqYaLKmBaMArULXODD66Utolpewl0OAeTB92aWUVv",
|
|
35
35
|
"manifest.tooltips.js": "sha384-hXGp5j0s6p2kGZY/hqLPEbaUv68ca63kFCjYiZqK3DcC12mpHTBy1vz3kuApyf4p",
|
|
36
36
|
"manifest.url.parameters.js": "sha384-J2aSVBOPsoqsbafHndrWLHEDpKb4AKJAoQnVmKA4gZh5P/8HHjFWHO/lkusmG84l",
|
|
37
37
|
"manifest.utilities.js": "sha384-h17EquaRtNcEW0yfhk7R+a+2+CzTlBxPuFryO6i9NV/OiIRMihREoyzQ77QawoQ7",
|
|
38
|
-
"manifest.virtual.js": "sha384-
|
|
38
|
+
"manifest.virtual.js": "sha384-ru/eYigBWgJHcHCP0yGKRaF1FNsKisWN61LBWaH16+8ZIh5H8fWtP3aMe0s9/mrg",
|
|
39
39
|
"manifest.js": "sha384-qMp2SeZUWYE/Lth8sguzlCAzXxn72gBDBPYUZ1iDlQVvzYuCc8/NPgw1gUJR88u1"
|
|
40
40
|
}
|
package/lib/manifest.markdown.js
CHANGED
|
@@ -869,8 +869,7 @@ async function initializeMarkdownPlugin() {
|
|
|
869
869
|
}
|
|
870
870
|
|
|
871
871
|
// Check if $x magic method is available
|
|
872
|
-
const
|
|
873
|
-
const hasXMagic = typeof xMagic === 'function';
|
|
872
|
+
const hasXMagic = typeof window._$xProxyFactory === 'function';
|
|
874
873
|
|
|
875
874
|
// If magic method isn't ready, wait briefly but don't block forever
|
|
876
875
|
if (!hasXMagic && retryCount < 5) {
|
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.265';
|
|
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/lib/manifest.virtual.js
CHANGED
|
@@ -241,6 +241,7 @@ function initializeVirtualPlugin() {
|
|
|
241
241
|
|
|
242
242
|
const visible = new Set();
|
|
243
243
|
const keys = [];
|
|
244
|
+
const items = [];
|
|
244
245
|
for (let i = startItem; i < endItem; i++) {
|
|
245
246
|
const item = data[i];
|
|
246
247
|
if (item == null) continue;
|
|
@@ -248,15 +249,35 @@ function initializeVirtualPlugin() {
|
|
|
248
249
|
if (key == null) continue;
|
|
249
250
|
visible.add(key);
|
|
250
251
|
keys.push(key);
|
|
251
|
-
|
|
252
|
-
if (!entry) entry = mountRow(item, key);
|
|
253
|
-
else if (entry.scope[itemName] !== item) entry.scope[itemName] = item; // rebind by key
|
|
254
|
-
host.insertBefore(entry.node, botSpacer); // keep DOM order = data order
|
|
252
|
+
items.push(item);
|
|
255
253
|
}
|
|
256
254
|
for (const [key, entry] of rendered) {
|
|
257
255
|
if (!visible.has(key)) removeRow(key, entry);
|
|
258
256
|
}
|
|
259
257
|
|
|
258
|
+
// Keep DOM order = data order, moving only rows out of place
|
|
259
|
+
const rowNodes = new Set();
|
|
260
|
+
for (const entry of rendered.values()) rowNodes.add(entry.node);
|
|
261
|
+
// Next row in the host; skips what a row root rendered (x-if clones), survives a row's init detaching it
|
|
262
|
+
const nextRow = (n) => {
|
|
263
|
+
while (n && n !== botSpacer && n.parentNode === host && !rowNodes.has(n)) n = n.nextSibling;
|
|
264
|
+
return n && n.parentNode === host ? n : botSpacer;
|
|
265
|
+
};
|
|
266
|
+
let cursor = nextRow(topSpacer.nextSibling);
|
|
267
|
+
for (let i = 0; i < keys.length; i++) {
|
|
268
|
+
if (cursor.parentNode !== host) cursor = botSpacer;
|
|
269
|
+
let entry = rendered.get(keys[i]);
|
|
270
|
+
if (!entry) {
|
|
271
|
+
entry = mountRow(items[i], keys[i], cursor);
|
|
272
|
+
rowNodes.add(entry.node);
|
|
273
|
+
if (entry.node.parentNode !== host) host.insertBefore(entry.node, cursor); // root replaced itself in init
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
if (entry.scope[itemName] !== items[i]) entry.scope[itemName] = items[i]; // rebind by key
|
|
277
|
+
if (entry.node === cursor) cursor = nextRow(cursor.nextSibling);
|
|
278
|
+
else host.insertBefore(entry.node, cursor);
|
|
279
|
+
}
|
|
280
|
+
|
|
260
281
|
// Measure anything not yet measured, then reconcile offsets once.
|
|
261
282
|
scheduleMeasure(keys);
|
|
262
283
|
}
|
|
@@ -306,10 +327,10 @@ function initializeVirtualPlugin() {
|
|
|
306
327
|
scheduleMeasure(keys);
|
|
307
328
|
}
|
|
308
329
|
|
|
309
|
-
function mountRow(item, key) {
|
|
330
|
+
function mountRow(item, key, before = anchor) {
|
|
310
331
|
const tpl = template.content.firstElementChild;
|
|
311
332
|
const node = tpl.cloneNode(true);
|
|
312
|
-
host.insertBefore(node,
|
|
333
|
+
host.insertBefore(node, before); // connect before init
|
|
313
334
|
const scope = Alpine.reactive({ [itemName]: item });
|
|
314
335
|
const removeScope = Alpine.addScopeToNode(node, scope);
|
|
315
336
|
Alpine.initTree(node);
|
|
@@ -422,11 +443,12 @@ function initializeVirtualPlugin() {
|
|
|
422
443
|
|
|
423
444
|
// ---- Scroll / resize ----
|
|
424
445
|
|
|
446
|
+
let destroyed = false;
|
|
425
447
|
let scrollScheduled = false;
|
|
426
448
|
const onScroll = () => {
|
|
427
449
|
if (scrollScheduled) return;
|
|
428
450
|
scrollScheduled = true;
|
|
429
|
-
requestAnimationFrame(() => { scrollScheduled = false; render(); });
|
|
451
|
+
requestAnimationFrame(() => { scrollScheduled = false; if (!destroyed) render(); });
|
|
430
452
|
};
|
|
431
453
|
scrollEl.addEventListener('scroll', onScroll, { passive: true });
|
|
432
454
|
|
|
@@ -440,6 +462,7 @@ function initializeVirtualPlugin() {
|
|
|
440
462
|
if (!kind && !isMasonry && host !== scrollEl) ro.observe(host); // only until a hidden host is classified
|
|
441
463
|
|
|
442
464
|
cleanup(() => {
|
|
465
|
+
destroyed = true;
|
|
443
466
|
scrollEl.removeEventListener('scroll', onScroll);
|
|
444
467
|
ro.disconnect();
|
|
445
468
|
clearTimeout(resizeTimer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnfst",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.265",
|
|
4
4
|
"private": false,
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"templates/starter",
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
"test:e2e:sdk": "node tests/e2e/payments.sdk.e2e.mjs",
|
|
48
48
|
"test:e2e:sw": "node tests/e2e/sw.e2e.mjs",
|
|
49
49
|
"test:e2e:settle": "node tests/e2e/render-settle.e2e.mjs",
|
|
50
|
+
"test:e2e:magic": "node tests/e2e/magic-one-arg.e2e.mjs",
|
|
51
|
+
"test:e2e:upload": "node tests/e2e/upload-first-load.e2e.mjs",
|
|
50
52
|
"lint": "echo 'No linting configured'",
|
|
51
53
|
"release:docs": "node scripts/release-bump.mjs packages/docs && cd packages/docs && npm publish --auth-type=web",
|
|
52
54
|
"release:check": "node scripts/release-check.mjs"
|