@astroscope/boot 0.4.0 → 0.6.0
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 -0
- package/README.md +46 -28
- package/dist/events.d.cts +1 -1
- package/dist/events.d.ts +1 -1
- package/dist/index.cjs +75 -39
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +72 -39
- package/dist/lifecycle.d.cts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/setup.d.cts +1 -1
- package/dist/setup.d.ts +1 -1
- package/dist/types-Ccbd5qoU.d.cts +10 -0
- package/dist/types-Ccbd5qoU.d.ts +10 -0
- package/package.json +9 -13
- package/dist/types-CxpusND2.d.cts +0 -18
- package/dist/types-CxpusND2.d.ts +0 -18
- package/dist/warmup.cjs +0 -82
- package/dist/warmup.d.cts +0 -22
- package/dist/warmup.d.ts +0 -22
- package/dist/warmup.js +0 -56
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Simon Bobrov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -89,45 +89,47 @@ Called when the server is shutting down (SIGTERM in production, server close in
|
|
|
89
89
|
- Cleaning up resources
|
|
90
90
|
- Graceful shutdown of external services
|
|
91
91
|
|
|
92
|
-
##
|
|
92
|
+
## Warmup
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
Pre-imports server modules at startup to eliminate cold-start latency on the first request. At build time, a virtual module is generated that statically imports all matched files. At runtime, this module is loaded in parallel with `onStartup`, so warmup doesn't delay server readiness.
|
|
95
|
+
|
|
96
|
+
### Enable warmup
|
|
95
97
|
|
|
96
98
|
```ts
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
import { warmup } from "@astroscope/boot/warmup";
|
|
99
|
+
boot({ warmup: true });
|
|
100
|
+
```
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
const result = await warmup();
|
|
102
|
+
This uses the default glob patterns (`WARMUP_MODULES`) which cover:
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
104
|
+
- `src/pages/**/*.{astro,ts,tsx,js,jsx,md,mdx}`
|
|
105
|
+
- `src/middleware.{ts,js}` / `src/middleware/index.{ts,js}`
|
|
107
106
|
|
|
108
|
-
|
|
109
|
-
console.warn(`Failed to warm up: ${result.failed.join(", ")}`);
|
|
110
|
-
}
|
|
107
|
+
### Custom patterns
|
|
111
108
|
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
Pass an array of glob patterns to control exactly which files are warmed up:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { WARMUP_MODULES } from "@astroscope/boot";
|
|
113
|
+
|
|
114
|
+
// defaults + custom patterns
|
|
115
|
+
boot({ warmup: [...WARMUP_MODULES, "src/components/**/*.tsx"] });
|
|
116
|
+
|
|
117
|
+
// only custom patterns (no defaults)
|
|
118
|
+
boot({ warmup: ["src/lib/heavy-module.ts"] });
|
|
114
119
|
```
|
|
115
120
|
|
|
116
|
-
###
|
|
121
|
+
### Exported constants
|
|
122
|
+
|
|
123
|
+
The default glob patterns are exported for composition:
|
|
117
124
|
|
|
118
125
|
```ts
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/** Time taken in milliseconds */
|
|
125
|
-
duration: number;
|
|
126
|
-
}
|
|
126
|
+
import {
|
|
127
|
+
WARMUP_PAGE_MODULES,
|
|
128
|
+
WARMUP_MIDDLEWARE_MODULES,
|
|
129
|
+
WARMUP_MODULES,
|
|
130
|
+
} from "@astroscope/boot";
|
|
127
131
|
```
|
|
128
132
|
|
|
129
|
-
In development mode, `warmup()` is a no-op that returns empty results. In production, it reads a manifest generated during the build and imports all discovered page modules and middleware in parallel.
|
|
130
|
-
|
|
131
133
|
## Options
|
|
132
134
|
|
|
133
135
|
### `entry`
|
|
@@ -152,14 +154,30 @@ Re-run `onStartup` when the boot file changes during development. This is disabl
|
|
|
152
154
|
boot({ hmr: true });
|
|
153
155
|
```
|
|
154
156
|
|
|
157
|
+
### `warmup`
|
|
158
|
+
|
|
159
|
+
Pre-import server modules on startup to eliminate cold-start latency.
|
|
160
|
+
|
|
161
|
+
- **Type**: `boolean | string[]`
|
|
162
|
+
- **Default**: `false`
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// use default patterns
|
|
166
|
+
boot({ warmup: true });
|
|
167
|
+
|
|
168
|
+
// custom patterns
|
|
169
|
+
boot({ warmup: [...WARMUP_MODULES, "src/components/**/*.tsx"] });
|
|
170
|
+
```
|
|
171
|
+
|
|
155
172
|
## How it works
|
|
156
173
|
|
|
157
174
|
- **Development**: The boot file runs _after_ the dev server starts listening (Vite limitation). `onShutdown` is called when the dev server closes.
|
|
158
|
-
- **Production**: `onStartup` runs _before_ the server starts handling requests. `onShutdown` is called on SIGTERM.
|
|
175
|
+
- **Production**: `onStartup` runs _before_ the server starts handling requests. `onShutdown` is called on SIGTERM. When warmup is enabled, module pre-loading runs in parallel with `onStartup`.
|
|
159
176
|
|
|
160
177
|
## Requirements
|
|
161
178
|
|
|
162
|
-
-
|
|
179
|
+
- Node.js runtime
|
|
180
|
+
- SSR output mode (`output: "server"`)
|
|
163
181
|
|
|
164
182
|
## License
|
|
165
183
|
|
package/dist/events.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BootContext } from './types-
|
|
1
|
+
import { B as BootContext } from './types-Ccbd5qoU.cjs';
|
|
2
2
|
|
|
3
3
|
type BootEventName = 'beforeOnStartup' | 'afterOnStartup' | 'beforeOnShutdown' | 'afterOnShutdown';
|
|
4
4
|
type BootEventHandler = (context: BootContext) => Promise<void> | void;
|
package/dist/events.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BootContext } from './types-
|
|
1
|
+
import { B as BootContext } from './types-Ccbd5qoU.js';
|
|
2
2
|
|
|
3
3
|
type BootEventName = 'beforeOnStartup' | 'afterOnStartup' | 'beforeOnShutdown' | 'afterOnShutdown';
|
|
4
4
|
type BootEventHandler = (context: BootContext) => Promise<void> | void;
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
WARMUP_MIDDLEWARE_MODULES: () => WARMUP_MIDDLEWARE_MODULES,
|
|
34
|
+
WARMUP_MODULES: () => WARMUP_MODULES,
|
|
35
|
+
WARMUP_PAGE_MODULES: () => WARMUP_PAGE_MODULES,
|
|
33
36
|
boot: () => boot,
|
|
34
37
|
default: () => boot,
|
|
35
38
|
prepend: () => prepend
|
|
@@ -38,6 +41,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
38
41
|
|
|
39
42
|
// src/integration.ts
|
|
40
43
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
44
|
+
var import_node_url = require("url");
|
|
41
45
|
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
42
46
|
var import_vite2 = require("vite");
|
|
43
47
|
|
|
@@ -194,35 +198,30 @@ function getPrependCode() {
|
|
|
194
198
|
return code;
|
|
195
199
|
}
|
|
196
200
|
|
|
197
|
-
// src/warmup
|
|
201
|
+
// src/warmup.ts
|
|
198
202
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
199
203
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
200
|
-
var
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
var WARMUP_PAGE_MODULES = ["src/pages/**/*.{astro,ts,tsx,js,jsx,md,mdx}"];
|
|
205
|
+
var WARMUP_MIDDLEWARE_MODULES = ["src/middleware.{ts,js}", "src/middleware/index.{ts,js}"];
|
|
206
|
+
var WARMUP_MODULES = [...WARMUP_PAGE_MODULES, ...WARMUP_MIDDLEWARE_MODULES];
|
|
207
|
+
var VIRTUAL_MODULE_ID = "virtual:@astroscope/boot/warmup";
|
|
208
|
+
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
209
|
+
async function resolveWarmupFiles(patterns, projectRoot) {
|
|
210
|
+
const files = [];
|
|
211
|
+
for (const pattern of patterns) {
|
|
212
|
+
for await (const entry of import_node_fs.default.promises.glob(pattern, {
|
|
213
|
+
cwd: projectRoot,
|
|
214
|
+
exclude: (name) => name === "node_modules"
|
|
215
|
+
})) {
|
|
216
|
+
files.push(import_node_path2.default.resolve(projectRoot, entry));
|
|
211
217
|
}
|
|
212
218
|
}
|
|
213
|
-
return
|
|
219
|
+
return [...new Set(files)];
|
|
214
220
|
}
|
|
215
|
-
function
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
for (const page of pageModules) {
|
|
221
|
-
modules.push(`./${page}`);
|
|
222
|
-
}
|
|
223
|
-
const manifestPath = import_node_path2.default.join(outDir, "chunks", WARMUP_MANIFEST_FILE);
|
|
224
|
-
import_node_fs.default.writeFileSync(manifestPath, JSON.stringify({ modules }));
|
|
225
|
-
logger.info(`generated warmup for ${pageModules.length} pages`);
|
|
221
|
+
function generateWarmupCode(files) {
|
|
222
|
+
if (files.length === 0) return "";
|
|
223
|
+
return `${files.map((f) => `import ${JSON.stringify(f)};`).join("\n")}
|
|
224
|
+
`;
|
|
226
225
|
}
|
|
227
226
|
|
|
228
227
|
// src/integration.ts
|
|
@@ -246,11 +245,20 @@ function getBootContext(server, config) {
|
|
|
246
245
|
const { host, port } = getServerDefaults(config);
|
|
247
246
|
return { dev: true, host, port };
|
|
248
247
|
}
|
|
249
|
-
|
|
248
|
+
function resolveWarmupPatterns(warmup) {
|
|
249
|
+
if (!warmup) return null;
|
|
250
|
+
if (Array.isArray(warmup)) {
|
|
251
|
+
return warmup;
|
|
252
|
+
}
|
|
253
|
+
return WARMUP_MODULES;
|
|
254
|
+
}
|
|
255
|
+
var getState = (0, import_vite2.perEnvironmentState)(() => ({ bootChunkRef: null, warmupChunkRef: null }));
|
|
250
256
|
function boot(options = {}) {
|
|
251
257
|
const entry = resolveEntry(options.entry);
|
|
252
258
|
const hmr = options.hmr ?? false;
|
|
259
|
+
const warmupPatterns = resolveWarmupPatterns(options.warmup);
|
|
253
260
|
let astroConfig = null;
|
|
261
|
+
let warmupCode = null;
|
|
254
262
|
return {
|
|
255
263
|
name: "@astroscope/boot",
|
|
256
264
|
hooks: {
|
|
@@ -259,16 +267,38 @@ function boot(options = {}) {
|
|
|
259
267
|
updateConfig({
|
|
260
268
|
vite: {
|
|
261
269
|
plugins: [
|
|
262
|
-
// build plugin: handles entry.mjs injection
|
|
270
|
+
// build plugin: handles entry.mjs injection and warmup virtual module
|
|
263
271
|
{
|
|
264
272
|
name: "@astroscope/boot",
|
|
265
|
-
|
|
273
|
+
resolveId(id) {
|
|
274
|
+
if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
|
|
275
|
+
},
|
|
276
|
+
load(id) {
|
|
277
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) return warmupCode ?? "";
|
|
278
|
+
},
|
|
279
|
+
async buildStart() {
|
|
266
280
|
if (this.environment.name !== "ssr") return;
|
|
267
281
|
const state = getState(this);
|
|
268
282
|
try {
|
|
269
283
|
state.bootChunkRef = this.emitFile({ type: "chunk", id: entry, name: "boot" });
|
|
270
284
|
} catch {
|
|
271
285
|
}
|
|
286
|
+
if (warmupPatterns) {
|
|
287
|
+
const projectRoot = astroConfig?.root ? (0, import_node_url.fileURLToPath)(astroConfig.root) : process.cwd();
|
|
288
|
+
const files = await resolveWarmupFiles(warmupPatterns, projectRoot);
|
|
289
|
+
warmupCode = generateWarmupCode(files);
|
|
290
|
+
if (files.length > 0) {
|
|
291
|
+
try {
|
|
292
|
+
state.warmupChunkRef = this.emitFile({
|
|
293
|
+
type: "chunk",
|
|
294
|
+
id: VIRTUAL_MODULE_ID,
|
|
295
|
+
name: "warmup"
|
|
296
|
+
});
|
|
297
|
+
} catch {
|
|
298
|
+
}
|
|
299
|
+
logger.info(`warmup: ${files.length} files`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
272
302
|
},
|
|
273
303
|
generateBundle(_, bundle) {
|
|
274
304
|
const state = getState(this);
|
|
@@ -283,16 +313,26 @@ function boot(options = {}) {
|
|
|
283
313
|
logger.warn("entry.mjs not found - boot injection skipped");
|
|
284
314
|
return;
|
|
285
315
|
}
|
|
286
|
-
state.warmupModules = collectWarmupModules(bundle);
|
|
287
316
|
const { host, port } = getServerDefaults(astroConfig);
|
|
288
317
|
const prependCode = getPrependCode();
|
|
289
318
|
const prefix = prependCode.length ? `${prependCode.join("\n")}
|
|
290
319
|
` : "";
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
320
|
+
let warmupStart = "";
|
|
321
|
+
let warmupEnd = "";
|
|
322
|
+
if (state.warmupChunkRef) {
|
|
323
|
+
const warmupChunkName = this.getFileName(state.warmupChunkRef);
|
|
324
|
+
if (warmupChunkName) {
|
|
325
|
+
warmupStart = `const __astroscope_warmup = import('./${warmupChunkName}');
|
|
295
326
|
`;
|
|
327
|
+
warmupEnd = `await __astroscope_warmup;
|
|
328
|
+
`;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const setupConfig = JSON.stringify({ host, port });
|
|
332
|
+
const injection = `${prefix}${warmupStart}import * as __astroscope_boot from './${bootChunkName}';
|
|
333
|
+
import { setup as __astroscope_bootSetup } from '@astroscope/boot/setup';
|
|
334
|
+
await __astroscope_bootSetup(__astroscope_boot, ${setupConfig});
|
|
335
|
+
${warmupEnd}`;
|
|
296
336
|
const s = new import_magic_string.default(entryChunk.code);
|
|
297
337
|
s.prepend(injection);
|
|
298
338
|
entryChunk.code = s.toString();
|
|
@@ -300,13 +340,6 @@ await __astroscope_bootSetup(__astroscope_boot, ${JSON.stringify({ host, port })
|
|
|
300
340
|
entryChunk.map = s.generateMap({ hires: true });
|
|
301
341
|
}
|
|
302
342
|
logger.info(`injected ${bootChunkName} into entry.mjs`);
|
|
303
|
-
},
|
|
304
|
-
writeBundle(outputOptions) {
|
|
305
|
-
const state = getState(this);
|
|
306
|
-
if (!state.warmupModules) return;
|
|
307
|
-
const outDir = outputOptions.dir;
|
|
308
|
-
if (!outDir) return;
|
|
309
|
-
writeWarmupManifest(outDir, state.warmupModules, logger);
|
|
310
343
|
}
|
|
311
344
|
},
|
|
312
345
|
// startup plugin: runs after all other configureServer hooks
|
|
@@ -345,6 +378,9 @@ await __astroscope_bootSetup(__astroscope_boot, ${JSON.stringify({ host, port })
|
|
|
345
378
|
}
|
|
346
379
|
// Annotate the CommonJS export names for ESM import in node:
|
|
347
380
|
0 && (module.exports = {
|
|
381
|
+
WARMUP_MIDDLEWARE_MODULES,
|
|
382
|
+
WARMUP_MODULES,
|
|
383
|
+
WARMUP_PAGE_MODULES,
|
|
348
384
|
boot,
|
|
349
385
|
prepend
|
|
350
386
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
|
-
export { B as BootContext
|
|
2
|
+
export { B as BootContext } from './types-Ccbd5qoU.cjs';
|
|
3
3
|
export { BootEventHandler, BootEventName } from './events.cjs';
|
|
4
4
|
export { prepend } from './prepend.cjs';
|
|
5
5
|
|
|
@@ -14,6 +14,15 @@ interface BootOptions {
|
|
|
14
14
|
* @default false
|
|
15
15
|
*/
|
|
16
16
|
hmr?: boolean | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Pre-import all page modules and middleware on startup to eliminate cold-start latency.
|
|
19
|
+
*
|
|
20
|
+
* - `true` — warmup using default glob patterns ({@link WARMUP_MODULES})
|
|
21
|
+
* - `string[]` — custom glob patterns (use `{@link WARMUP_MODULES}` to include defaults)
|
|
22
|
+
*
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
warmup?: boolean | string[] | undefined;
|
|
17
26
|
}
|
|
18
27
|
/**
|
|
19
28
|
* Astro integration for application lifecycle hooks.
|
|
@@ -23,4 +32,14 @@ interface BootOptions {
|
|
|
23
32
|
*/
|
|
24
33
|
declare function boot(options?: BootOptions): AstroIntegration;
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Default warmup glob patterns covering Astro pages and middleware.
|
|
37
|
+
*/
|
|
38
|
+
declare const WARMUP_PAGE_MODULES: string[];
|
|
39
|
+
declare const WARMUP_MIDDLEWARE_MODULES: string[];
|
|
40
|
+
/**
|
|
41
|
+
* All default warmup glob patterns.
|
|
42
|
+
*/
|
|
43
|
+
declare const WARMUP_MODULES: string[];
|
|
44
|
+
|
|
45
|
+
export { type BootOptions, WARMUP_MIDDLEWARE_MODULES, WARMUP_MODULES, WARMUP_PAGE_MODULES, boot, boot as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
|
-
export { B as BootContext
|
|
2
|
+
export { B as BootContext } from './types-Ccbd5qoU.js';
|
|
3
3
|
export { BootEventHandler, BootEventName } from './events.js';
|
|
4
4
|
export { prepend } from './prepend.js';
|
|
5
5
|
|
|
@@ -14,6 +14,15 @@ interface BootOptions {
|
|
|
14
14
|
* @default false
|
|
15
15
|
*/
|
|
16
16
|
hmr?: boolean | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Pre-import all page modules and middleware on startup to eliminate cold-start latency.
|
|
19
|
+
*
|
|
20
|
+
* - `true` — warmup using default glob patterns ({@link WARMUP_MODULES})
|
|
21
|
+
* - `string[]` — custom glob patterns (use `{@link WARMUP_MODULES}` to include defaults)
|
|
22
|
+
*
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
warmup?: boolean | string[] | undefined;
|
|
17
26
|
}
|
|
18
27
|
/**
|
|
19
28
|
* Astro integration for application lifecycle hooks.
|
|
@@ -23,4 +32,14 @@ interface BootOptions {
|
|
|
23
32
|
*/
|
|
24
33
|
declare function boot(options?: BootOptions): AstroIntegration;
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Default warmup glob patterns covering Astro pages and middleware.
|
|
37
|
+
*/
|
|
38
|
+
declare const WARMUP_PAGE_MODULES: string[];
|
|
39
|
+
declare const WARMUP_MIDDLEWARE_MODULES: string[];
|
|
40
|
+
/**
|
|
41
|
+
* All default warmup glob patterns.
|
|
42
|
+
*/
|
|
43
|
+
declare const WARMUP_MODULES: string[];
|
|
44
|
+
|
|
45
|
+
export { type BootOptions, WARMUP_MIDDLEWARE_MODULES, WARMUP_MODULES, WARMUP_PAGE_MODULES, boot, boot as default };
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import "./chunk-I62ZQYTP.js";
|
|
|
10
10
|
|
|
11
11
|
// src/integration.ts
|
|
12
12
|
import fs2 from "fs";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
13
14
|
import MagicString from "magic-string";
|
|
14
15
|
import { perEnvironmentState } from "vite";
|
|
15
16
|
|
|
@@ -124,35 +125,30 @@ function setupBootHmr(server, entry, logger, getBootContext2) {
|
|
|
124
125
|
});
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
// src/warmup
|
|
128
|
+
// src/warmup.ts
|
|
128
129
|
import fs from "fs";
|
|
129
130
|
import path2 from "path";
|
|
130
|
-
var
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
131
|
+
var WARMUP_PAGE_MODULES = ["src/pages/**/*.{astro,ts,tsx,js,jsx,md,mdx}"];
|
|
132
|
+
var WARMUP_MIDDLEWARE_MODULES = ["src/middleware.{ts,js}", "src/middleware/index.{ts,js}"];
|
|
133
|
+
var WARMUP_MODULES = [...WARMUP_PAGE_MODULES, ...WARMUP_MIDDLEWARE_MODULES];
|
|
134
|
+
var VIRTUAL_MODULE_ID = "virtual:@astroscope/boot/warmup";
|
|
135
|
+
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
136
|
+
async function resolveWarmupFiles(patterns, projectRoot) {
|
|
137
|
+
const files = [];
|
|
138
|
+
for (const pattern of patterns) {
|
|
139
|
+
for await (const entry of fs.promises.glob(pattern, {
|
|
140
|
+
cwd: projectRoot,
|
|
141
|
+
exclude: (name) => name === "node_modules"
|
|
142
|
+
})) {
|
|
143
|
+
files.push(path2.resolve(projectRoot, entry));
|
|
141
144
|
}
|
|
142
145
|
}
|
|
143
|
-
return
|
|
146
|
+
return [...new Set(files)];
|
|
144
147
|
}
|
|
145
|
-
function
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
for (const page of pageModules) {
|
|
151
|
-
modules.push(`./${page}`);
|
|
152
|
-
}
|
|
153
|
-
const manifestPath = path2.join(outDir, "chunks", WARMUP_MANIFEST_FILE);
|
|
154
|
-
fs.writeFileSync(manifestPath, JSON.stringify({ modules }));
|
|
155
|
-
logger.info(`generated warmup for ${pageModules.length} pages`);
|
|
148
|
+
function generateWarmupCode(files) {
|
|
149
|
+
if (files.length === 0) return "";
|
|
150
|
+
return `${files.map((f) => `import ${JSON.stringify(f)};`).join("\n")}
|
|
151
|
+
`;
|
|
156
152
|
}
|
|
157
153
|
|
|
158
154
|
// src/integration.ts
|
|
@@ -176,11 +172,20 @@ function getBootContext(server, config) {
|
|
|
176
172
|
const { host, port } = getServerDefaults(config);
|
|
177
173
|
return { dev: true, host, port };
|
|
178
174
|
}
|
|
179
|
-
|
|
175
|
+
function resolveWarmupPatterns(warmup) {
|
|
176
|
+
if (!warmup) return null;
|
|
177
|
+
if (Array.isArray(warmup)) {
|
|
178
|
+
return warmup;
|
|
179
|
+
}
|
|
180
|
+
return WARMUP_MODULES;
|
|
181
|
+
}
|
|
182
|
+
var getState = perEnvironmentState(() => ({ bootChunkRef: null, warmupChunkRef: null }));
|
|
180
183
|
function boot(options = {}) {
|
|
181
184
|
const entry = resolveEntry(options.entry);
|
|
182
185
|
const hmr = options.hmr ?? false;
|
|
186
|
+
const warmupPatterns = resolveWarmupPatterns(options.warmup);
|
|
183
187
|
let astroConfig = null;
|
|
188
|
+
let warmupCode = null;
|
|
184
189
|
return {
|
|
185
190
|
name: "@astroscope/boot",
|
|
186
191
|
hooks: {
|
|
@@ -189,16 +194,38 @@ function boot(options = {}) {
|
|
|
189
194
|
updateConfig({
|
|
190
195
|
vite: {
|
|
191
196
|
plugins: [
|
|
192
|
-
// build plugin: handles entry.mjs injection
|
|
197
|
+
// build plugin: handles entry.mjs injection and warmup virtual module
|
|
193
198
|
{
|
|
194
199
|
name: "@astroscope/boot",
|
|
195
|
-
|
|
200
|
+
resolveId(id) {
|
|
201
|
+
if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
|
|
202
|
+
},
|
|
203
|
+
load(id) {
|
|
204
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) return warmupCode ?? "";
|
|
205
|
+
},
|
|
206
|
+
async buildStart() {
|
|
196
207
|
if (this.environment.name !== "ssr") return;
|
|
197
208
|
const state = getState(this);
|
|
198
209
|
try {
|
|
199
210
|
state.bootChunkRef = this.emitFile({ type: "chunk", id: entry, name: "boot" });
|
|
200
211
|
} catch {
|
|
201
212
|
}
|
|
213
|
+
if (warmupPatterns) {
|
|
214
|
+
const projectRoot = astroConfig?.root ? fileURLToPath(astroConfig.root) : process.cwd();
|
|
215
|
+
const files = await resolveWarmupFiles(warmupPatterns, projectRoot);
|
|
216
|
+
warmupCode = generateWarmupCode(files);
|
|
217
|
+
if (files.length > 0) {
|
|
218
|
+
try {
|
|
219
|
+
state.warmupChunkRef = this.emitFile({
|
|
220
|
+
type: "chunk",
|
|
221
|
+
id: VIRTUAL_MODULE_ID,
|
|
222
|
+
name: "warmup"
|
|
223
|
+
});
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
logger.info(`warmup: ${files.length} files`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
202
229
|
},
|
|
203
230
|
generateBundle(_, bundle) {
|
|
204
231
|
const state = getState(this);
|
|
@@ -213,16 +240,26 @@ function boot(options = {}) {
|
|
|
213
240
|
logger.warn("entry.mjs not found - boot injection skipped");
|
|
214
241
|
return;
|
|
215
242
|
}
|
|
216
|
-
state.warmupModules = collectWarmupModules(bundle);
|
|
217
243
|
const { host, port } = getServerDefaults(astroConfig);
|
|
218
244
|
const prependCode = getPrependCode();
|
|
219
245
|
const prefix = prependCode.length ? `${prependCode.join("\n")}
|
|
220
246
|
` : "";
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
247
|
+
let warmupStart = "";
|
|
248
|
+
let warmupEnd = "";
|
|
249
|
+
if (state.warmupChunkRef) {
|
|
250
|
+
const warmupChunkName = this.getFileName(state.warmupChunkRef);
|
|
251
|
+
if (warmupChunkName) {
|
|
252
|
+
warmupStart = `const __astroscope_warmup = import('./${warmupChunkName}');
|
|
225
253
|
`;
|
|
254
|
+
warmupEnd = `await __astroscope_warmup;
|
|
255
|
+
`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const setupConfig = JSON.stringify({ host, port });
|
|
259
|
+
const injection = `${prefix}${warmupStart}import * as __astroscope_boot from './${bootChunkName}';
|
|
260
|
+
import { setup as __astroscope_bootSetup } from '@astroscope/boot/setup';
|
|
261
|
+
await __astroscope_bootSetup(__astroscope_boot, ${setupConfig});
|
|
262
|
+
${warmupEnd}`;
|
|
226
263
|
const s = new MagicString(entryChunk.code);
|
|
227
264
|
s.prepend(injection);
|
|
228
265
|
entryChunk.code = s.toString();
|
|
@@ -230,13 +267,6 @@ await __astroscope_bootSetup(__astroscope_boot, ${JSON.stringify({ host, port })
|
|
|
230
267
|
entryChunk.map = s.generateMap({ hires: true });
|
|
231
268
|
}
|
|
232
269
|
logger.info(`injected ${bootChunkName} into entry.mjs`);
|
|
233
|
-
},
|
|
234
|
-
writeBundle(outputOptions) {
|
|
235
|
-
const state = getState(this);
|
|
236
|
-
if (!state.warmupModules) return;
|
|
237
|
-
const outDir = outputOptions.dir;
|
|
238
|
-
if (!outDir) return;
|
|
239
|
-
writeWarmupManifest(outDir, state.warmupModules, logger);
|
|
240
270
|
}
|
|
241
271
|
},
|
|
242
272
|
// startup plugin: runs after all other configureServer hooks
|
|
@@ -274,6 +304,9 @@ await __astroscope_bootSetup(__astroscope_boot, ${JSON.stringify({ host, port })
|
|
|
274
304
|
};
|
|
275
305
|
}
|
|
276
306
|
export {
|
|
307
|
+
WARMUP_MIDDLEWARE_MODULES,
|
|
308
|
+
WARMUP_MODULES,
|
|
309
|
+
WARMUP_PAGE_MODULES,
|
|
277
310
|
boot,
|
|
278
311
|
boot as default,
|
|
279
312
|
prepend
|
package/dist/lifecycle.d.cts
CHANGED
package/dist/lifecycle.d.ts
CHANGED
package/dist/setup.d.cts
CHANGED
package/dist/setup.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astroscope/boot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Startup and graceful shutdown hooks for Astro SSR",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,10 +11,6 @@
|
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"require": "./dist/index.cjs"
|
|
13
13
|
},
|
|
14
|
-
"./warmup": {
|
|
15
|
-
"types": "./dist/warmup.d.ts",
|
|
16
|
-
"import": "./dist/warmup.js"
|
|
17
|
-
},
|
|
18
14
|
"./events": {
|
|
19
15
|
"types": "./dist/events.d.ts",
|
|
20
16
|
"import": "./dist/events.js"
|
|
@@ -52,14 +48,8 @@
|
|
|
52
48
|
"url": "https://github.com/smnbbrv/astroscope/issues"
|
|
53
49
|
},
|
|
54
50
|
"homepage": "https://github.com/smnbbrv/astroscope/tree/main/packages/boot#readme",
|
|
55
|
-
"scripts": {
|
|
56
|
-
"build": "tsup src/index.ts src/warmup.ts src/events.ts src/lifecycle.ts src/setup.ts src/prepend.ts --format esm,cjs --dts",
|
|
57
|
-
"typecheck": "tsc --noEmit",
|
|
58
|
-
"lint": "eslint src",
|
|
59
|
-
"lint:fix": "eslint src --fix"
|
|
60
|
-
},
|
|
61
51
|
"devDependencies": {
|
|
62
|
-
"astro": "^6.0.
|
|
52
|
+
"astro": "^6.0.7",
|
|
63
53
|
"tsup": "^8.5.1",
|
|
64
54
|
"typescript": "^5.9.3"
|
|
65
55
|
},
|
|
@@ -69,5 +59,11 @@
|
|
|
69
59
|
},
|
|
70
60
|
"dependencies": {
|
|
71
61
|
"magic-string": "^0.30.21"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup src/index.ts src/events.ts src/lifecycle.ts src/setup.ts src/prepend.ts --format esm,cjs --dts",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"lint": "eslint src",
|
|
67
|
+
"lint:fix": "eslint src --fix"
|
|
72
68
|
}
|
|
73
|
-
}
|
|
69
|
+
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
interface BootContext {
|
|
2
|
-
/** Whether running in development mode (vite dev server) */
|
|
3
|
-
dev: boolean;
|
|
4
|
-
/** Server host from Astro config */
|
|
5
|
-
host: string;
|
|
6
|
-
/** Server port from Astro config */
|
|
7
|
-
port: number;
|
|
8
|
-
}
|
|
9
|
-
interface WarmupResult {
|
|
10
|
-
/** Modules that were successfully loaded */
|
|
11
|
-
success: string[];
|
|
12
|
-
/** Modules that failed to load */
|
|
13
|
-
failed: string[];
|
|
14
|
-
/** Time taken in milliseconds */
|
|
15
|
-
duration: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type { BootContext as B, WarmupResult as W };
|
package/dist/types-CxpusND2.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
interface BootContext {
|
|
2
|
-
/** Whether running in development mode (vite dev server) */
|
|
3
|
-
dev: boolean;
|
|
4
|
-
/** Server host from Astro config */
|
|
5
|
-
host: string;
|
|
6
|
-
/** Server port from Astro config */
|
|
7
|
-
port: number;
|
|
8
|
-
}
|
|
9
|
-
interface WarmupResult {
|
|
10
|
-
/** Modules that were successfully loaded */
|
|
11
|
-
success: string[];
|
|
12
|
-
/** Modules that failed to load */
|
|
13
|
-
failed: string[];
|
|
14
|
-
/** Time taken in milliseconds */
|
|
15
|
-
duration: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type { BootContext as B, WarmupResult as W };
|
package/dist/warmup.cjs
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/warmup.ts
|
|
21
|
-
var warmup_exports = {};
|
|
22
|
-
__export(warmup_exports, {
|
|
23
|
-
warmup: () => warmup
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(warmup_exports);
|
|
26
|
-
var import_node_fs = require("fs");
|
|
27
|
-
var import_node_path = require("path");
|
|
28
|
-
var import_node_url = require("url");
|
|
29
|
-
var import_meta = {};
|
|
30
|
-
var WARMUP_MANIFEST_FILE = "warmup-manifest.json";
|
|
31
|
-
function isDevMode() {
|
|
32
|
-
return Boolean(import_meta.env?.["DEV"]);
|
|
33
|
-
}
|
|
34
|
-
function loadManifest() {
|
|
35
|
-
if (isDevMode()) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
const serverUrl = globalThis.__astroscope_server_url;
|
|
39
|
-
if (!serverUrl) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
const serverDir = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(serverUrl));
|
|
43
|
-
const manifestPath = (0, import_node_path.join)(serverDir, "chunks", WARMUP_MANIFEST_FILE);
|
|
44
|
-
if (!(0, import_node_fs.existsSync)(manifestPath)) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
const manifest = JSON.parse((0, import_node_fs.readFileSync)(manifestPath, "utf-8"));
|
|
48
|
-
return {
|
|
49
|
-
modules: manifest.modules ?? [],
|
|
50
|
-
serverDir
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
async function warmup() {
|
|
54
|
-
const manifest = loadManifest();
|
|
55
|
-
if (!manifest || manifest.modules.length === 0) {
|
|
56
|
-
return { success: [], failed: [], duration: 0 };
|
|
57
|
-
}
|
|
58
|
-
const { modules, serverDir } = manifest;
|
|
59
|
-
const start = Date.now();
|
|
60
|
-
const resolvedModules = modules.map((mod) => {
|
|
61
|
-
const absolutePath = (0, import_node_path.resolve)(serverDir, mod);
|
|
62
|
-
return (0, import_node_url.pathToFileURL)(absolutePath).href;
|
|
63
|
-
});
|
|
64
|
-
const results = await Promise.allSettled(resolvedModules.map((mod) => import(
|
|
65
|
-
/* @vite-ignore */
|
|
66
|
-
mod
|
|
67
|
-
)));
|
|
68
|
-
const success = [];
|
|
69
|
-
const failed = [];
|
|
70
|
-
for (let i = 0; i < results.length; i++) {
|
|
71
|
-
if (results[i].status === "fulfilled") {
|
|
72
|
-
success.push(modules[i]);
|
|
73
|
-
} else {
|
|
74
|
-
failed.push(modules[i]);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return { success, failed, duration: Date.now() - start };
|
|
78
|
-
}
|
|
79
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
80
|
-
0 && (module.exports = {
|
|
81
|
-
warmup
|
|
82
|
-
});
|
package/dist/warmup.d.cts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { W as WarmupResult } from './types-CxpusND2.cjs';
|
|
2
|
-
|
|
3
|
-
declare global {
|
|
4
|
-
var __astroscope_server_url: string | undefined;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Warms up V8 by importing all page modules and middleware.
|
|
8
|
-
*
|
|
9
|
-
* In development mode, this is a no-op that returns empty results.
|
|
10
|
-
* In production, reads the warmup manifest and imports all discovered modules.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* import { warmup } from '@astroscope/boot/warmup';
|
|
15
|
-
*
|
|
16
|
-
* const result = await warmup();
|
|
17
|
-
* console.log(`warmed up ${result.success.length} modules`);
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
declare function warmup(): Promise<WarmupResult>;
|
|
21
|
-
|
|
22
|
-
export { WarmupResult, warmup };
|
package/dist/warmup.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { W as WarmupResult } from './types-CxpusND2.js';
|
|
2
|
-
|
|
3
|
-
declare global {
|
|
4
|
-
var __astroscope_server_url: string | undefined;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Warms up V8 by importing all page modules and middleware.
|
|
8
|
-
*
|
|
9
|
-
* In development mode, this is a no-op that returns empty results.
|
|
10
|
-
* In production, reads the warmup manifest and imports all discovered modules.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* import { warmup } from '@astroscope/boot/warmup';
|
|
15
|
-
*
|
|
16
|
-
* const result = await warmup();
|
|
17
|
-
* console.log(`warmed up ${result.success.length} modules`);
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
declare function warmup(): Promise<WarmupResult>;
|
|
21
|
-
|
|
22
|
-
export { WarmupResult, warmup };
|
package/dist/warmup.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// src/warmup.ts
|
|
2
|
-
import { existsSync, readFileSync } from "fs";
|
|
3
|
-
import { dirname, join, resolve } from "path";
|
|
4
|
-
import { fileURLToPath, pathToFileURL } from "url";
|
|
5
|
-
var WARMUP_MANIFEST_FILE = "warmup-manifest.json";
|
|
6
|
-
function isDevMode() {
|
|
7
|
-
return Boolean(import.meta.env?.["DEV"]);
|
|
8
|
-
}
|
|
9
|
-
function loadManifest() {
|
|
10
|
-
if (isDevMode()) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
const serverUrl = globalThis.__astroscope_server_url;
|
|
14
|
-
if (!serverUrl) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
const serverDir = dirname(fileURLToPath(serverUrl));
|
|
18
|
-
const manifestPath = join(serverDir, "chunks", WARMUP_MANIFEST_FILE);
|
|
19
|
-
if (!existsSync(manifestPath)) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
23
|
-
return {
|
|
24
|
-
modules: manifest.modules ?? [],
|
|
25
|
-
serverDir
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
async function warmup() {
|
|
29
|
-
const manifest = loadManifest();
|
|
30
|
-
if (!manifest || manifest.modules.length === 0) {
|
|
31
|
-
return { success: [], failed: [], duration: 0 };
|
|
32
|
-
}
|
|
33
|
-
const { modules, serverDir } = manifest;
|
|
34
|
-
const start = Date.now();
|
|
35
|
-
const resolvedModules = modules.map((mod) => {
|
|
36
|
-
const absolutePath = resolve(serverDir, mod);
|
|
37
|
-
return pathToFileURL(absolutePath).href;
|
|
38
|
-
});
|
|
39
|
-
const results = await Promise.allSettled(resolvedModules.map((mod) => import(
|
|
40
|
-
/* @vite-ignore */
|
|
41
|
-
mod
|
|
42
|
-
)));
|
|
43
|
-
const success = [];
|
|
44
|
-
const failed = [];
|
|
45
|
-
for (let i = 0; i < results.length; i++) {
|
|
46
|
-
if (results[i].status === "fulfilled") {
|
|
47
|
-
success.push(modules[i]);
|
|
48
|
-
} else {
|
|
49
|
-
failed.push(modules[i]);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return { success, failed, duration: Date.now() - start };
|
|
53
|
-
}
|
|
54
|
-
export {
|
|
55
|
-
warmup
|
|
56
|
-
};
|