vite-plugin-cross-origin-storage 1.8.0 → 2.0.1
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/LICENSE +21 -201
- package/README.md +61 -110
- package/dist/index.d.mts +32 -0
- package/dist/index.mjs +242 -0
- package/dist/loader.d.mts +38 -0
- package/dist/loader.entry.d.mts +1 -0
- package/dist/loader.entry.mjs +7 -0
- package/dist/loader.mjs +51 -0
- package/package.json +53 -51
- package/dist/index.d.ts +0 -17
- package/dist/index.js +0 -2115
- package/dist/loader.js +0 -134
- package/loader.js +0 -134
package/dist/loader.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
(async function () {
|
|
2
|
-
const isCOSAvailable = 'crossOriginStorage' in navigator;
|
|
3
|
-
console.log('COS Loader: isCOSAvailable =', isCOSAvailable);
|
|
4
|
-
|
|
5
|
-
// Manifest is injected by the Vite plugin
|
|
6
|
-
// @ts-ignore
|
|
7
|
-
const manifest = __COS_MANIFEST__;
|
|
8
|
-
|
|
9
|
-
const { base, entry, chunks } = manifest;
|
|
10
|
-
const mainEntry = entry;
|
|
11
|
-
|
|
12
|
-
if (!mainEntry) {
|
|
13
|
-
console.warn('COS Loader: Missing entry in manifest.');
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Identify managed chunks
|
|
18
|
-
const chunksToLoad = Object.entries(chunks || {}).map(([fileName, hash]) => ({
|
|
19
|
-
fileName,
|
|
20
|
-
hash,
|
|
21
|
-
file: `${base}${fileName}`,
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
async function getBlobFromCOS(hash) {
|
|
25
|
-
if (!isCOSAvailable) return null;
|
|
26
|
-
try {
|
|
27
|
-
const handles = await navigator.crossOriginStorage.requestFileHandles([
|
|
28
|
-
{ algorithm: 'SHA-256', value: hash },
|
|
29
|
-
]);
|
|
30
|
-
if (handles && handles.length > 0) {
|
|
31
|
-
return await handles[0].getFile();
|
|
32
|
-
}
|
|
33
|
-
} catch (err) {
|
|
34
|
-
if (err.name !== 'NotFoundError')
|
|
35
|
-
console.error('COS Loader: Error checking COS', err);
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function storeBlobInCOS(blob, hash) {
|
|
41
|
-
if (!isCOSAvailable) return;
|
|
42
|
-
try {
|
|
43
|
-
const handles = await navigator.crossOriginStorage.requestFileHandles(
|
|
44
|
-
[{ algorithm: 'SHA-256', value: hash }],
|
|
45
|
-
{ create: true }
|
|
46
|
-
);
|
|
47
|
-
if (handles && handles.length > 0) {
|
|
48
|
-
const writable = await handles[0].createWritable();
|
|
49
|
-
await writable.write(blob);
|
|
50
|
-
await writable.close();
|
|
51
|
-
console.log('COS Loader: Stored chunk in COS', hash);
|
|
52
|
-
}
|
|
53
|
-
} catch (err) {
|
|
54
|
-
console.error('COS Loader: Failed to store in COS', err);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function getChunkBlobUrl(chunk) {
|
|
59
|
-
let blob = await getBlobFromCOS(chunk.hash);
|
|
60
|
-
if (blob) {
|
|
61
|
-
console.log(`COS Loader: ${chunk.fileName} found in COS`);
|
|
62
|
-
blob = new Blob([blob], { type: 'text/javascript' });
|
|
63
|
-
}
|
|
64
|
-
if (!blob) {
|
|
65
|
-
console.log(`COS Loader: ${chunk.file} not in COS, fetching...`);
|
|
66
|
-
try {
|
|
67
|
-
const resp = await fetch(chunk.file);
|
|
68
|
-
if (!resp.ok) throw new Error(`Status ${resp.status}`);
|
|
69
|
-
const rawBlob = await resp.blob();
|
|
70
|
-
blob = new Blob([rawBlob], { type: 'text/javascript' });
|
|
71
|
-
await storeBlobInCOS(blob, chunk.hash);
|
|
72
|
-
} catch (e) {
|
|
73
|
-
console.error(`COS Loader: Failed to fetch ${chunk.file}`, e);
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Convert blob to Blob URL
|
|
79
|
-
// Blob URLs are synchronous and share the page origin,
|
|
80
|
-
// which helps with module resolution in complex graphs.
|
|
81
|
-
return URL.createObjectURL(blob);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Initialize
|
|
85
|
-
try {
|
|
86
|
-
console.log('COS Loader: Starting app...');
|
|
87
|
-
|
|
88
|
-
// Resolve all chunks to Blob URLs
|
|
89
|
-
const importMap = { imports: {} };
|
|
90
|
-
|
|
91
|
-
// Set up unmanaged dependencies correctly so Blob URLs can resolve them.
|
|
92
|
-
for (const fileName of manifest.unmanaged || []) {
|
|
93
|
-
const bareSpecifier = `coschunk-${fileName.replace(/\//g, '-')}`;
|
|
94
|
-
importMap.imports[bareSpecifier] =
|
|
95
|
-
window.location.origin + base + fileName;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
console.log(`COS Loader: Loading ${chunksToLoad.length} chunks...`);
|
|
99
|
-
const loadPromises = chunksToLoad.map(async (chunk) => {
|
|
100
|
-
const blobUrl = await getChunkBlobUrl(chunk);
|
|
101
|
-
if (blobUrl) {
|
|
102
|
-
// Use a hyphenated prefix and replace all slashes to ensure it's treated
|
|
103
|
-
// as a truly bare specifier, bypassing hierarchical/protocol checks.
|
|
104
|
-
const bareSpecifier = `coschunk-${chunk.fileName.replace(/\//g, '-')}`;
|
|
105
|
-
importMap.imports[bareSpecifier] = blobUrl;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
await Promise.all(loadPromises);
|
|
110
|
-
|
|
111
|
-
// Inject Import Map
|
|
112
|
-
const script = document.createElement('script');
|
|
113
|
-
script.type = 'importmap';
|
|
114
|
-
script.textContent = JSON.stringify(importMap, null, 2);
|
|
115
|
-
document.head.appendChild(script);
|
|
116
|
-
|
|
117
|
-
console.log('COS Loader: Import Map injected');
|
|
118
|
-
|
|
119
|
-
// Import the main entry via its bare specifier to ensure it resolves
|
|
120
|
-
// through the import map and can find other managed chunks.
|
|
121
|
-
const entrySpecifier = `coschunk-${mainEntry.replace(/\//g, '-')}`;
|
|
122
|
-
|
|
123
|
-
// Yield to the event loop once so the browser registers the dynamically
|
|
124
|
-
// injected import map before the first module import.
|
|
125
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
126
|
-
try {
|
|
127
|
-
await import(entrySpecifier);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
console.error('COS Loader: Failed to start app', err);
|
|
130
|
-
}
|
|
131
|
-
} catch (err) {
|
|
132
|
-
console.error('COS Loader: Initialization failed', err);
|
|
133
|
-
}
|
|
134
|
-
})();
|
package/loader.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
(async function () {
|
|
2
|
-
const isCOSAvailable = 'crossOriginStorage' in navigator;
|
|
3
|
-
console.log('COS Loader: isCOSAvailable =', isCOSAvailable);
|
|
4
|
-
|
|
5
|
-
// Manifest is injected by the Vite plugin
|
|
6
|
-
// @ts-ignore
|
|
7
|
-
const manifest = __COS_MANIFEST__;
|
|
8
|
-
|
|
9
|
-
const { base, entry, chunks } = manifest;
|
|
10
|
-
const mainEntry = entry;
|
|
11
|
-
|
|
12
|
-
if (!mainEntry) {
|
|
13
|
-
console.warn('COS Loader: Missing entry in manifest.');
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Identify managed chunks
|
|
18
|
-
const chunksToLoad = Object.entries(chunks || {}).map(([fileName, hash]) => ({
|
|
19
|
-
fileName,
|
|
20
|
-
hash,
|
|
21
|
-
file: `${base}${fileName}`,
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
async function getBlobFromCOS(hash) {
|
|
25
|
-
if (!isCOSAvailable) return null;
|
|
26
|
-
try {
|
|
27
|
-
const handles = await navigator.crossOriginStorage.requestFileHandles([
|
|
28
|
-
{ algorithm: 'SHA-256', value: hash },
|
|
29
|
-
]);
|
|
30
|
-
if (handles && handles.length > 0) {
|
|
31
|
-
return await handles[0].getFile();
|
|
32
|
-
}
|
|
33
|
-
} catch (err) {
|
|
34
|
-
if (err.name !== 'NotFoundError')
|
|
35
|
-
console.error('COS Loader: Error checking COS', err);
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function storeBlobInCOS(blob, hash) {
|
|
41
|
-
if (!isCOSAvailable) return;
|
|
42
|
-
try {
|
|
43
|
-
const handles = await navigator.crossOriginStorage.requestFileHandles(
|
|
44
|
-
[{ algorithm: 'SHA-256', value: hash }],
|
|
45
|
-
{ create: true }
|
|
46
|
-
);
|
|
47
|
-
if (handles && handles.length > 0) {
|
|
48
|
-
const writable = await handles[0].createWritable();
|
|
49
|
-
await writable.write(blob);
|
|
50
|
-
await writable.close();
|
|
51
|
-
console.log('COS Loader: Stored chunk in COS', hash);
|
|
52
|
-
}
|
|
53
|
-
} catch (err) {
|
|
54
|
-
console.error('COS Loader: Failed to store in COS', err);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function getChunkBlobUrl(chunk) {
|
|
59
|
-
let blob = await getBlobFromCOS(chunk.hash);
|
|
60
|
-
if (blob) {
|
|
61
|
-
console.log(`COS Loader: ${chunk.fileName} found in COS`);
|
|
62
|
-
blob = new Blob([blob], { type: 'text/javascript' });
|
|
63
|
-
}
|
|
64
|
-
if (!blob) {
|
|
65
|
-
console.log(`COS Loader: ${chunk.file} not in COS, fetching...`);
|
|
66
|
-
try {
|
|
67
|
-
const resp = await fetch(chunk.file);
|
|
68
|
-
if (!resp.ok) throw new Error(`Status ${resp.status}`);
|
|
69
|
-
const rawBlob = await resp.blob();
|
|
70
|
-
blob = new Blob([rawBlob], { type: 'text/javascript' });
|
|
71
|
-
await storeBlobInCOS(blob, chunk.hash);
|
|
72
|
-
} catch (e) {
|
|
73
|
-
console.error(`COS Loader: Failed to fetch ${chunk.file}`, e);
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Convert blob to Blob URL
|
|
79
|
-
// Blob URLs are synchronous and share the page origin,
|
|
80
|
-
// which helps with module resolution in complex graphs.
|
|
81
|
-
return URL.createObjectURL(blob);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Initialize
|
|
85
|
-
try {
|
|
86
|
-
console.log('COS Loader: Starting app...');
|
|
87
|
-
|
|
88
|
-
// Resolve all chunks to Blob URLs
|
|
89
|
-
const importMap = { imports: {} };
|
|
90
|
-
|
|
91
|
-
// Set up unmanaged dependencies correctly so Blob URLs can resolve them.
|
|
92
|
-
for (const fileName of manifest.unmanaged || []) {
|
|
93
|
-
const bareSpecifier = `coschunk-${fileName.replace(/\//g, '-')}`;
|
|
94
|
-
importMap.imports[bareSpecifier] =
|
|
95
|
-
window.location.origin + base + fileName;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
console.log(`COS Loader: Loading ${chunksToLoad.length} chunks...`);
|
|
99
|
-
const loadPromises = chunksToLoad.map(async (chunk) => {
|
|
100
|
-
const blobUrl = await getChunkBlobUrl(chunk);
|
|
101
|
-
if (blobUrl) {
|
|
102
|
-
// Use a hyphenated prefix and replace all slashes to ensure it's treated
|
|
103
|
-
// as a truly bare specifier, bypassing hierarchical/protocol checks.
|
|
104
|
-
const bareSpecifier = `coschunk-${chunk.fileName.replace(/\//g, '-')}`;
|
|
105
|
-
importMap.imports[bareSpecifier] = blobUrl;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
await Promise.all(loadPromises);
|
|
110
|
-
|
|
111
|
-
// Inject Import Map
|
|
112
|
-
const script = document.createElement('script');
|
|
113
|
-
script.type = 'importmap';
|
|
114
|
-
script.textContent = JSON.stringify(importMap, null, 2);
|
|
115
|
-
document.head.appendChild(script);
|
|
116
|
-
|
|
117
|
-
console.log('COS Loader: Import Map injected');
|
|
118
|
-
|
|
119
|
-
// Import the main entry via its bare specifier to ensure it resolves
|
|
120
|
-
// through the import map and can find other managed chunks.
|
|
121
|
-
const entrySpecifier = `coschunk-${mainEntry.replace(/\//g, '-')}`;
|
|
122
|
-
|
|
123
|
-
// Yield to the event loop once so the browser registers the dynamically
|
|
124
|
-
// injected import map before the first module import.
|
|
125
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
126
|
-
try {
|
|
127
|
-
await import(entrySpecifier);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
console.error('COS Loader: Failed to start app', err);
|
|
130
|
-
}
|
|
131
|
-
} catch (err) {
|
|
132
|
-
console.error('COS Loader: Initialization failed', err);
|
|
133
|
-
}
|
|
134
|
-
})();
|