@sdeverywhere/plugin-check 0.3.21 → 0.3.23
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.cjs +30 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +39 -22
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/template-bundle/src/bundle.ts +0 -12
- package/template-report/src/env.d.ts +0 -1
- package/template-report/src/index.ts +14 -59
- package/template-report/src/load-bundle.ts +95 -0
|
@@ -6,6 +6,8 @@ import type { BundleLocation, BundleSpec } from '@sdeverywhere/check-ui-shell'
|
|
|
6
6
|
import { initAppShell } from '@sdeverywhere/check-ui-shell'
|
|
7
7
|
import '@sdeverywhere/check-ui-shell/dist/style.css'
|
|
8
8
|
|
|
9
|
+
import type { BundleMetadata, BundleResult } from './load-bundle'
|
|
10
|
+
import { loadLocalBundle, loadRemoteBundle } from './load-bundle'
|
|
9
11
|
import { initOverlay } from './overlay'
|
|
10
12
|
|
|
11
13
|
import './global.css'
|
|
@@ -15,11 +17,6 @@ import { createBundle as createBaselineBundle } from '@_baseline_bundle_'
|
|
|
15
17
|
import { createBundle as createCurrentBundle } from '@_current_bundle_'
|
|
16
18
|
import { getConfigOptions } from '@_test_config_'
|
|
17
19
|
|
|
18
|
-
interface BundleMetadata {
|
|
19
|
-
name: string
|
|
20
|
-
url: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
20
|
function loadBundleMetadata(side: 'left' | 'right'): BundleMetadata | undefined {
|
|
24
21
|
if (import.meta.hot) {
|
|
25
22
|
const metadataJson = localStorage.getItem(`sde-check-selected-bundle-${side}`)
|
|
@@ -43,7 +40,7 @@ function saveBundleMetadata(side: 'left' | 'right', metadata: BundleMetadata): v
|
|
|
43
40
|
let savedBundleMetadataL: BundleMetadata | undefined
|
|
44
41
|
let savedBundleMetadataR: BundleMetadata | undefined
|
|
45
42
|
// The following value will be injected by `vite-config-for-report.ts`
|
|
46
|
-
const bundlesPath = './bundles
|
|
43
|
+
const bundlesPath = './bundles/**/*.txt'
|
|
47
44
|
if (import.meta.hot && bundlesPath) {
|
|
48
45
|
// Restore the previously selected bundles (from before the page was reloaded)
|
|
49
46
|
savedBundleMetadataL = loadBundleMetadata('left')
|
|
@@ -90,12 +87,6 @@ async function initForProduction(): Promise<void> {
|
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
async function initForLocal(): Promise<void> {
|
|
93
|
-
interface BundleResult {
|
|
94
|
-
bundle: Bundle
|
|
95
|
-
bundleName: string
|
|
96
|
-
bundleUrl: string
|
|
97
|
-
}
|
|
98
|
-
|
|
99
90
|
async function createBundle(bundleMetadata: BundleMetadata | undefined): Promise<BundleResult> {
|
|
100
91
|
if (bundleMetadata === undefined) {
|
|
101
92
|
bundleMetadata = {
|
|
@@ -107,16 +98,7 @@ async function initForLocal(): Promise<void> {
|
|
|
107
98
|
if (bundleMetadata.url.startsWith('http')) {
|
|
108
99
|
// Load remote bundles using dynamic import
|
|
109
100
|
try {
|
|
110
|
-
|
|
111
|
-
const cacheBuster = `?cb=${Date.now()}`
|
|
112
|
-
const fullUrl = `${bundleMetadata.url}${cacheBuster}`
|
|
113
|
-
const module = await import(/* @vite-ignore */ fullUrl)
|
|
114
|
-
const bundle = module.createBundle() as Bundle
|
|
115
|
-
return {
|
|
116
|
-
bundle,
|
|
117
|
-
bundleName: bundleMetadata.name,
|
|
118
|
-
bundleUrl: bundleMetadata.url
|
|
119
|
-
}
|
|
101
|
+
return loadRemoteBundle(bundleMetadata)
|
|
120
102
|
} catch (e) {
|
|
121
103
|
console.error(
|
|
122
104
|
`ERROR: Failed to load remote bundle from ${bundleMetadata.url}; will use "current" bundle instead. Cause:`,
|
|
@@ -124,35 +106,15 @@ async function initForLocal(): Promise<void> {
|
|
|
124
106
|
)
|
|
125
107
|
}
|
|
126
108
|
} else if (bundleMetadata.url.startsWith('file://')) {
|
|
127
|
-
// Load local bundles using `import.meta.glob`
|
|
128
|
-
// available for file URLs due to security restrictions). The glob pattern
|
|
129
|
-
// part will be replaced by Vite (see `vite-config-for-report.ts`). Note
|
|
130
|
-
// that we provide a placeholder here that looks like a valid glob pattern,
|
|
131
|
-
// since Vite's dependency resolver will report errors if it is invalid
|
|
132
|
-
// (not a literal).
|
|
109
|
+
// Load local bundles using `import.meta.glob`
|
|
133
110
|
try {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const bundleFileName = bundlePathParts[bundlePathParts.length - 1]
|
|
142
|
-
return bundleFileName === remoteBundleFileName
|
|
143
|
-
})
|
|
144
|
-
if (bundleKey) {
|
|
145
|
-
type BundleModule = {
|
|
146
|
-
createBundle(): Bundle
|
|
147
|
-
}
|
|
148
|
-
const loadBundle = bundlesGlob[bundleKey]
|
|
149
|
-
const module = (await loadBundle()) as BundleModule
|
|
150
|
-
const bundle = module.createBundle() as Bundle
|
|
151
|
-
return {
|
|
152
|
-
bundle,
|
|
153
|
-
bundleName: bundleMetadata.name,
|
|
154
|
-
bundleUrl: bundleMetadata.url
|
|
155
|
-
}
|
|
111
|
+
const result = await loadLocalBundle(bundleMetadata)
|
|
112
|
+
if (result) {
|
|
113
|
+
return result
|
|
114
|
+
} else {
|
|
115
|
+
console.error(
|
|
116
|
+
`ERROR: Bundle key not found in glob for ${bundleMetadata.name}; will use "current" bundle instead`
|
|
117
|
+
)
|
|
156
118
|
}
|
|
157
119
|
} catch (e) {
|
|
158
120
|
console.error(
|
|
@@ -269,21 +231,14 @@ async function getLocalBundles(): Promise<BundleLocation[]> {
|
|
|
269
231
|
const handleSuccess = (data: { bundles: Array<{ name: string; url: string; lastModified: string }> }) => {
|
|
270
232
|
cleanup()
|
|
271
233
|
|
|
272
|
-
// Add the bundles that were found in the Node process
|
|
234
|
+
// Add the bundles that were found in the Node process. The bundles returned from the Node process
|
|
235
|
+
// include both local bundles and the special "current" bundle with its up-to-date last modified time.
|
|
273
236
|
const bundles: BundleLocation[] = data.bundles.map(b => ({
|
|
274
237
|
name: b.name,
|
|
275
238
|
url: b.url,
|
|
276
239
|
lastModified: b.lastModified
|
|
277
240
|
}))
|
|
278
241
|
|
|
279
|
-
// Add the special "current" bundle that is generated by the builder
|
|
280
|
-
const currentBundleLastModified = __CURRENT_BUNDLE_LAST_MODIFIED__
|
|
281
|
-
bundles.push({
|
|
282
|
-
name: 'current',
|
|
283
|
-
url: 'current',
|
|
284
|
-
lastModified: currentBundleLastModified
|
|
285
|
-
})
|
|
286
|
-
|
|
287
242
|
resolve(bundles)
|
|
288
243
|
}
|
|
289
244
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Copyright (c) 2025 Climate Interactive / New Venture Fund
|
|
2
|
+
|
|
3
|
+
import type { Bundle } from '@sdeverywhere/check-core'
|
|
4
|
+
|
|
5
|
+
export interface BundleMetadata {
|
|
6
|
+
name: string
|
|
7
|
+
url: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface BundleResult {
|
|
11
|
+
bundle: Bundle
|
|
12
|
+
bundleName: string
|
|
13
|
+
bundleUrl: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Load a remote bundle from a given URL.
|
|
18
|
+
*/
|
|
19
|
+
export async function loadRemoteBundle(bundleMetadata: BundleMetadata): Promise<BundleResult> {
|
|
20
|
+
// Add cache busting parameter
|
|
21
|
+
const cacheBuster = `?cb=${Date.now()}`
|
|
22
|
+
const fullUrl = `${bundleMetadata.url}${cacheBuster}`
|
|
23
|
+
const module = await import(/* @vite-ignore */ fullUrl)
|
|
24
|
+
const bundle = module.createBundle() as Bundle
|
|
25
|
+
return {
|
|
26
|
+
bundle,
|
|
27
|
+
bundleName: bundleMetadata.name,
|
|
28
|
+
bundleUrl: bundleMetadata.url
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Load a local bundle from the file system using dynamic import (only available in development mode with HMR).
|
|
34
|
+
*/
|
|
35
|
+
export async function loadLocalBundle(bundleMetadata: BundleMetadata): Promise<BundleResult | undefined> {
|
|
36
|
+
// Only available in development mode with HMR
|
|
37
|
+
if (!import.meta.hot) {
|
|
38
|
+
return undefined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
// Set up listeners
|
|
43
|
+
const handleSuccess = async (data: { name: string; url: string; sourceCode: string }) => {
|
|
44
|
+
cleanup()
|
|
45
|
+
if (data.url === bundleMetadata.url) {
|
|
46
|
+
try {
|
|
47
|
+
// Create a blob URL from the source code
|
|
48
|
+
const blob = new Blob([data.sourceCode], { type: 'application/javascript' })
|
|
49
|
+
const blobUrl = URL.createObjectURL(blob)
|
|
50
|
+
|
|
51
|
+
// Import the bundle from the blob URL
|
|
52
|
+
const module = await import(/* @vite-ignore */ blobUrl)
|
|
53
|
+
const bundle = module.createBundle() as Bundle
|
|
54
|
+
|
|
55
|
+
// Clean up the blob URL
|
|
56
|
+
URL.revokeObjectURL(blobUrl)
|
|
57
|
+
|
|
58
|
+
resolve({
|
|
59
|
+
bundle,
|
|
60
|
+
bundleName: bundleMetadata.name,
|
|
61
|
+
bundleUrl: bundleMetadata.url
|
|
62
|
+
})
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error(`Failed to execute bundle ${bundleMetadata.name}:`, error)
|
|
65
|
+
resolve(undefined)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const handleError = (data: { name: string; url: string; error: string }) => {
|
|
71
|
+
cleanup()
|
|
72
|
+
if (data.url === bundleMetadata.url) {
|
|
73
|
+
console.error(`Failed to load bundle ${bundleMetadata.name}:`, data.error)
|
|
74
|
+
resolve(undefined)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const cleanup = () => {
|
|
79
|
+
import.meta.hot.off('load-bundle-success', handleSuccess)
|
|
80
|
+
import.meta.hot.off('load-bundle-error', handleError)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
import.meta.hot.on('load-bundle-success', handleSuccess)
|
|
84
|
+
import.meta.hot.on('load-bundle-error', handleError)
|
|
85
|
+
|
|
86
|
+
// Send request to load bundle
|
|
87
|
+
import.meta.hot.send('load-bundle', { url: bundleMetadata.url, name: bundleMetadata.name })
|
|
88
|
+
|
|
89
|
+
// Timeout after 10 seconds
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
cleanup()
|
|
92
|
+
reject(new Error(`Timeout waiting for bundle: ${bundleMetadata.name}`))
|
|
93
|
+
}, 10000)
|
|
94
|
+
})
|
|
95
|
+
}
|