vite-plugin-cross-origin-storage 1.3.19 → 1.3.20
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/dist/index.js +3 -1
- package/dist/loader.js +31 -91
- package/loader.js +31 -91
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1722,8 +1722,10 @@ function cosPlugin(options = {}) {
|
|
|
1722
1722
|
hasDefault
|
|
1723
1723
|
};
|
|
1724
1724
|
}
|
|
1725
|
+
const entryFileName = mainChunk.fileName;
|
|
1725
1726
|
manifest["index"] = {
|
|
1726
|
-
|
|
1727
|
+
fileName: entryFileName,
|
|
1728
|
+
file: `${base}${entryFileName}`
|
|
1727
1729
|
};
|
|
1728
1730
|
if (htmlAsset) {
|
|
1729
1731
|
try {
|
package/dist/loader.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
(async function () {
|
|
2
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
3
|
-
|
|
4
2
|
const isCOSAvailable = 'crossOriginStorage' in navigator;
|
|
5
3
|
console.log('COS Loader: isCOSAvailable =', isCOSAvailable);
|
|
6
4
|
|
|
@@ -16,8 +14,6 @@
|
|
|
16
14
|
|
|
17
15
|
// Identify managed chunks (anything with a hash)
|
|
18
16
|
const chunksToLoad = Object.values(manifest).filter((item) => item.hash);
|
|
19
|
-
const chunksByFileName = {};
|
|
20
|
-
chunksToLoad.forEach(c => chunksByFileName[c.fileName] = c);
|
|
21
17
|
|
|
22
18
|
async function getBlobFromCOS(hash) {
|
|
23
19
|
if (!isCOSAvailable) return null;
|
|
@@ -46,23 +42,14 @@
|
|
|
46
42
|
const writable = await handles[0].createWritable();
|
|
47
43
|
await writable.write(blob);
|
|
48
44
|
await writable.close();
|
|
49
|
-
console.log('COS Loader: Stored
|
|
45
|
+
console.log('COS Loader: Stored chunk in COS', hash);
|
|
50
46
|
}
|
|
51
47
|
} catch (err) {
|
|
52
48
|
console.error('COS Loader: Failed to store in COS', err);
|
|
53
49
|
}
|
|
54
50
|
}
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
const resolvedUrls = {}; // fileName -> { blobUrl, shimUrl }
|
|
58
|
-
const processing = new Set();
|
|
59
|
-
|
|
60
|
-
// Cache for raw text content
|
|
61
|
-
const rawContent = {}; // fileName -> string
|
|
62
|
-
|
|
63
|
-
async function loadRawContent(chunk) {
|
|
64
|
-
if (rawContent[chunk.fileName]) return rawContent[chunk.fileName];
|
|
65
|
-
|
|
52
|
+
async function getChunkDataUrl(chunk) {
|
|
66
53
|
let blob = await getBlobFromCOS(chunk.hash);
|
|
67
54
|
if (!blob) {
|
|
68
55
|
console.log(`COS Loader: ${chunk.file} not in COS, fetching...`);
|
|
@@ -70,97 +57,50 @@
|
|
|
70
57
|
const resp = await fetch(chunk.file);
|
|
71
58
|
if (!resp.ok) throw new Error(`Status ${resp.status}`);
|
|
72
59
|
blob = await resp.blob();
|
|
73
|
-
storeBlobInCOS(blob, chunk.hash);
|
|
60
|
+
await storeBlobInCOS(blob, chunk.hash);
|
|
74
61
|
} catch (e) {
|
|
75
62
|
console.error(`COS Loader: Failed to fetch ${chunk.file}`, e);
|
|
76
63
|
return null;
|
|
77
64
|
}
|
|
78
65
|
}
|
|
79
|
-
const text = await blob.text();
|
|
80
|
-
rawContent[chunk.fileName] = text;
|
|
81
|
-
return text;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function resolveChunk(fileName) {
|
|
85
|
-
if (resolvedUrls[fileName]) return resolvedUrls[fileName];
|
|
86
|
-
if (processing.has(fileName)) {
|
|
87
|
-
console.warn(`COS Loader: Circular dependency detected for ${fileName}. Breaking cycle with placeholder (may fail).`);
|
|
88
|
-
// We cannot solve cycles with Direct Data Injection easily.
|
|
89
|
-
// Returning null might cause failure, but we hope merging chunks avoided this.
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
processing.add(fileName);
|
|
94
|
-
const chunk = chunksByFileName[fileName];
|
|
95
|
-
if (!chunk) {
|
|
96
|
-
// Unmanaged dependency? Should have been handled by absolute/base logic but we reverted to ./
|
|
97
|
-
// If it's ./unmanaged.js, we don't have it in manifest.
|
|
98
|
-
// We can't inject it.
|
|
99
|
-
console.warn(`COS Loader: Unknown dependency ${fileName}`);
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
66
|
|
|
103
|
-
|
|
104
|
-
|
|
67
|
+
// Convert blob to Data URL
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
const reader = new FileReader();
|
|
70
|
+
reader.onloadend = () => resolve(reader.result);
|
|
71
|
+
reader.readAsDataURL(blob);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
105
74
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
let match;
|
|
110
|
-
const deps = new Set();
|
|
111
|
-
while ((match = depRegex.exec(code)) !== null) {
|
|
112
|
-
deps.add(match[1]); // The filename relative to current
|
|
113
|
-
}
|
|
75
|
+
// Initialize
|
|
76
|
+
try {
|
|
77
|
+
console.log('COS Loader: Starting app...');
|
|
114
78
|
|
|
115
|
-
// Resolve
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
|
|
79
|
+
// Resolve all chunks to Data URLs
|
|
80
|
+
const importMap = { imports: {} };
|
|
81
|
+
const loadPromises = chunksToLoad.map(async (chunk) => {
|
|
82
|
+
const dataUrl = await getChunkDataUrl(chunk);
|
|
83
|
+
if (dataUrl) {
|
|
84
|
+
// Map the relative path (as used in the plugin's bare specifier rewrite) to the data URL
|
|
85
|
+
importMap.imports[`./${chunk.fileName}`] = dataUrl;
|
|
121
86
|
}
|
|
122
|
-
}
|
|
87
|
+
});
|
|
123
88
|
|
|
124
|
-
|
|
125
|
-
for (const { depName, url } of replacements) {
|
|
126
|
-
// Replace ALL occurrences
|
|
127
|
-
// We need to be careful with regex replacement safer:
|
|
128
|
-
// Replace `from "./depName"` with `from "url"`
|
|
129
|
-
code = code.split(`from "./${depName}"`).join(`from "${url}"`);
|
|
130
|
-
code = code.split(`from './${depName}'`).join(`from "${url}"`);
|
|
89
|
+
await Promise.all(loadPromises);
|
|
131
90
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const blob = new Blob([code], { type: 'text/javascript' });
|
|
138
|
-
const blobUrl = URL.createObjectURL(blob);
|
|
91
|
+
// Inject Import Map
|
|
92
|
+
const script = document.createElement('script');
|
|
93
|
+
script.type = 'importmap';
|
|
94
|
+
script.textContent = JSON.stringify(importMap);
|
|
95
|
+
document.head.appendChild(script);
|
|
139
96
|
|
|
140
|
-
|
|
141
|
-
const shim = `export * from "${blobUrl}";${chunk.hasDefault ? `export { default } from "${blobUrl}";` : ''}`;
|
|
142
|
-
const shimUrl = `data:text/javascript;base64,${btoa(shim)}`;
|
|
97
|
+
console.log('COS Loader: Import Map injected');
|
|
143
98
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return resolvedUrls[fileName];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Initialize
|
|
150
|
-
try {
|
|
151
|
-
console.log('COS Loader: Starting app...');
|
|
152
|
-
// Resolve main entry
|
|
99
|
+
// Import the main entry.
|
|
100
|
+
// The main entry itself is also managed and rewritten to use bare specifiers.
|
|
153
101
|
const entryFileName = mainEntry.fileName;
|
|
154
|
-
|
|
155
|
-
// Actually resolveChunk returns the shimUrl.
|
|
156
|
-
const res = await resolveChunk(entryFileName);
|
|
102
|
+
await import(`./${entryFileName}`);
|
|
157
103
|
|
|
158
|
-
if (res) {
|
|
159
|
-
// Import the SHIM of the main entry
|
|
160
|
-
await import(res.shimUrl);
|
|
161
|
-
} else {
|
|
162
|
-
console.error('COS Loader: Failed to resolve main entry');
|
|
163
|
-
}
|
|
164
104
|
} catch (err) {
|
|
165
105
|
console.error('COS Loader: Failed to start app', err);
|
|
166
106
|
}
|
package/loader.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
(async function () {
|
|
2
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
3
|
-
|
|
4
2
|
const isCOSAvailable = 'crossOriginStorage' in navigator;
|
|
5
3
|
console.log('COS Loader: isCOSAvailable =', isCOSAvailable);
|
|
6
4
|
|
|
@@ -16,8 +14,6 @@
|
|
|
16
14
|
|
|
17
15
|
// Identify managed chunks (anything with a hash)
|
|
18
16
|
const chunksToLoad = Object.values(manifest).filter((item) => item.hash);
|
|
19
|
-
const chunksByFileName = {};
|
|
20
|
-
chunksToLoad.forEach(c => chunksByFileName[c.fileName] = c);
|
|
21
17
|
|
|
22
18
|
async function getBlobFromCOS(hash) {
|
|
23
19
|
if (!isCOSAvailable) return null;
|
|
@@ -46,23 +42,14 @@
|
|
|
46
42
|
const writable = await handles[0].createWritable();
|
|
47
43
|
await writable.write(blob);
|
|
48
44
|
await writable.close();
|
|
49
|
-
console.log('COS Loader: Stored
|
|
45
|
+
console.log('COS Loader: Stored chunk in COS', hash);
|
|
50
46
|
}
|
|
51
47
|
} catch (err) {
|
|
52
48
|
console.error('COS Loader: Failed to store in COS', err);
|
|
53
49
|
}
|
|
54
50
|
}
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
const resolvedUrls = {}; // fileName -> { blobUrl, shimUrl }
|
|
58
|
-
const processing = new Set();
|
|
59
|
-
|
|
60
|
-
// Cache for raw text content
|
|
61
|
-
const rawContent = {}; // fileName -> string
|
|
62
|
-
|
|
63
|
-
async function loadRawContent(chunk) {
|
|
64
|
-
if (rawContent[chunk.fileName]) return rawContent[chunk.fileName];
|
|
65
|
-
|
|
52
|
+
async function getChunkDataUrl(chunk) {
|
|
66
53
|
let blob = await getBlobFromCOS(chunk.hash);
|
|
67
54
|
if (!blob) {
|
|
68
55
|
console.log(`COS Loader: ${chunk.file} not in COS, fetching...`);
|
|
@@ -70,97 +57,50 @@
|
|
|
70
57
|
const resp = await fetch(chunk.file);
|
|
71
58
|
if (!resp.ok) throw new Error(`Status ${resp.status}`);
|
|
72
59
|
blob = await resp.blob();
|
|
73
|
-
storeBlobInCOS(blob, chunk.hash);
|
|
60
|
+
await storeBlobInCOS(blob, chunk.hash);
|
|
74
61
|
} catch (e) {
|
|
75
62
|
console.error(`COS Loader: Failed to fetch ${chunk.file}`, e);
|
|
76
63
|
return null;
|
|
77
64
|
}
|
|
78
65
|
}
|
|
79
|
-
const text = await blob.text();
|
|
80
|
-
rawContent[chunk.fileName] = text;
|
|
81
|
-
return text;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function resolveChunk(fileName) {
|
|
85
|
-
if (resolvedUrls[fileName]) return resolvedUrls[fileName];
|
|
86
|
-
if (processing.has(fileName)) {
|
|
87
|
-
console.warn(`COS Loader: Circular dependency detected for ${fileName}. Breaking cycle with placeholder (may fail).`);
|
|
88
|
-
// We cannot solve cycles with Direct Data Injection easily.
|
|
89
|
-
// Returning null might cause failure, but we hope merging chunks avoided this.
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
processing.add(fileName);
|
|
94
|
-
const chunk = chunksByFileName[fileName];
|
|
95
|
-
if (!chunk) {
|
|
96
|
-
// Unmanaged dependency? Should have been handled by absolute/base logic but we reverted to ./
|
|
97
|
-
// If it's ./unmanaged.js, we don't have it in manifest.
|
|
98
|
-
// We can't inject it.
|
|
99
|
-
console.warn(`COS Loader: Unknown dependency ${fileName}`);
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
66
|
|
|
103
|
-
|
|
104
|
-
|
|
67
|
+
// Convert blob to Data URL
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
const reader = new FileReader();
|
|
70
|
+
reader.onloadend = () => resolve(reader.result);
|
|
71
|
+
reader.readAsDataURL(blob);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
105
74
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
let match;
|
|
110
|
-
const deps = new Set();
|
|
111
|
-
while ((match = depRegex.exec(code)) !== null) {
|
|
112
|
-
deps.add(match[1]); // The filename relative to current
|
|
113
|
-
}
|
|
75
|
+
// Initialize
|
|
76
|
+
try {
|
|
77
|
+
console.log('COS Loader: Starting app...');
|
|
114
78
|
|
|
115
|
-
// Resolve
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
|
|
79
|
+
// Resolve all chunks to Data URLs
|
|
80
|
+
const importMap = { imports: {} };
|
|
81
|
+
const loadPromises = chunksToLoad.map(async (chunk) => {
|
|
82
|
+
const dataUrl = await getChunkDataUrl(chunk);
|
|
83
|
+
if (dataUrl) {
|
|
84
|
+
// Map the relative path (as used in the plugin's bare specifier rewrite) to the data URL
|
|
85
|
+
importMap.imports[`./${chunk.fileName}`] = dataUrl;
|
|
121
86
|
}
|
|
122
|
-
}
|
|
87
|
+
});
|
|
123
88
|
|
|
124
|
-
|
|
125
|
-
for (const { depName, url } of replacements) {
|
|
126
|
-
// Replace ALL occurrences
|
|
127
|
-
// We need to be careful with regex replacement safer:
|
|
128
|
-
// Replace `from "./depName"` with `from "url"`
|
|
129
|
-
code = code.split(`from "./${depName}"`).join(`from "${url}"`);
|
|
130
|
-
code = code.split(`from './${depName}'`).join(`from "${url}"`);
|
|
89
|
+
await Promise.all(loadPromises);
|
|
131
90
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const blob = new Blob([code], { type: 'text/javascript' });
|
|
138
|
-
const blobUrl = URL.createObjectURL(blob);
|
|
91
|
+
// Inject Import Map
|
|
92
|
+
const script = document.createElement('script');
|
|
93
|
+
script.type = 'importmap';
|
|
94
|
+
script.textContent = JSON.stringify(importMap);
|
|
95
|
+
document.head.appendChild(script);
|
|
139
96
|
|
|
140
|
-
|
|
141
|
-
const shim = `export * from "${blobUrl}";${chunk.hasDefault ? `export { default } from "${blobUrl}";` : ''}`;
|
|
142
|
-
const shimUrl = `data:text/javascript;base64,${btoa(shim)}`;
|
|
97
|
+
console.log('COS Loader: Import Map injected');
|
|
143
98
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return resolvedUrls[fileName];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Initialize
|
|
150
|
-
try {
|
|
151
|
-
console.log('COS Loader: Starting app...');
|
|
152
|
-
// Resolve main entry
|
|
99
|
+
// Import the main entry.
|
|
100
|
+
// The main entry itself is also managed and rewritten to use bare specifiers.
|
|
153
101
|
const entryFileName = mainEntry.fileName;
|
|
154
|
-
|
|
155
|
-
// Actually resolveChunk returns the shimUrl.
|
|
156
|
-
const res = await resolveChunk(entryFileName);
|
|
102
|
+
await import(`./${entryFileName}`);
|
|
157
103
|
|
|
158
|
-
if (res) {
|
|
159
|
-
// Import the SHIM of the main entry
|
|
160
|
-
await import(res.shimUrl);
|
|
161
|
-
} else {
|
|
162
|
-
console.error('COS Loader: Failed to resolve main entry');
|
|
163
|
-
}
|
|
164
104
|
} catch (err) {
|
|
165
105
|
console.error('COS Loader: Failed to start app', err);
|
|
166
106
|
}
|