@buenojs/bueno 0.8.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/.env.example +109 -0
- package/.github/workflows/ci.yml +31 -0
- package/LICENSE +21 -0
- package/README.md +892 -0
- package/architecture.md +652 -0
- package/bun.lock +70 -0
- package/dist/cli/index.js +3233 -0
- package/dist/index.js +9014 -0
- package/package.json +77 -0
- package/src/cache/index.ts +795 -0
- package/src/cli/ARCHITECTURE.md +837 -0
- package/src/cli/bin.ts +10 -0
- package/src/cli/commands/build.ts +425 -0
- package/src/cli/commands/dev.ts +248 -0
- package/src/cli/commands/generate.ts +541 -0
- package/src/cli/commands/help.ts +55 -0
- package/src/cli/commands/index.ts +112 -0
- package/src/cli/commands/migration.ts +355 -0
- package/src/cli/commands/new.ts +804 -0
- package/src/cli/commands/start.ts +208 -0
- package/src/cli/core/args.ts +283 -0
- package/src/cli/core/console.ts +349 -0
- package/src/cli/core/index.ts +60 -0
- package/src/cli/core/prompt.ts +424 -0
- package/src/cli/core/spinner.ts +265 -0
- package/src/cli/index.ts +135 -0
- package/src/cli/templates/deploy.ts +295 -0
- package/src/cli/templates/docker.ts +307 -0
- package/src/cli/templates/index.ts +24 -0
- package/src/cli/utils/fs.ts +428 -0
- package/src/cli/utils/index.ts +8 -0
- package/src/cli/utils/strings.ts +197 -0
- package/src/config/env.ts +408 -0
- package/src/config/index.ts +506 -0
- package/src/config/loader.ts +329 -0
- package/src/config/merge.ts +285 -0
- package/src/config/types.ts +320 -0
- package/src/config/validation.ts +441 -0
- package/src/container/forward-ref.ts +143 -0
- package/src/container/index.ts +386 -0
- package/src/context/index.ts +360 -0
- package/src/database/index.ts +1142 -0
- package/src/database/migrations/index.ts +371 -0
- package/src/database/schema/index.ts +619 -0
- package/src/frontend/api-routes.ts +640 -0
- package/src/frontend/bundler.ts +643 -0
- package/src/frontend/console-client.ts +419 -0
- package/src/frontend/console-stream.ts +587 -0
- package/src/frontend/dev-server.ts +846 -0
- package/src/frontend/file-router.ts +611 -0
- package/src/frontend/frameworks/index.ts +106 -0
- package/src/frontend/frameworks/react.ts +85 -0
- package/src/frontend/frameworks/solid.ts +104 -0
- package/src/frontend/frameworks/svelte.ts +110 -0
- package/src/frontend/frameworks/vue.ts +92 -0
- package/src/frontend/hmr-client.ts +663 -0
- package/src/frontend/hmr.ts +728 -0
- package/src/frontend/index.ts +342 -0
- package/src/frontend/islands.ts +552 -0
- package/src/frontend/isr.ts +555 -0
- package/src/frontend/layout.ts +475 -0
- package/src/frontend/ssr/react.ts +446 -0
- package/src/frontend/ssr/solid.ts +523 -0
- package/src/frontend/ssr/svelte.ts +546 -0
- package/src/frontend/ssr/vue.ts +504 -0
- package/src/frontend/ssr.ts +699 -0
- package/src/frontend/types.ts +2274 -0
- package/src/health/index.ts +604 -0
- package/src/index.ts +410 -0
- package/src/lock/index.ts +587 -0
- package/src/logger/index.ts +444 -0
- package/src/logger/transports/index.ts +969 -0
- package/src/metrics/index.ts +494 -0
- package/src/middleware/built-in.ts +360 -0
- package/src/middleware/index.ts +94 -0
- package/src/modules/filters.ts +458 -0
- package/src/modules/guards.ts +405 -0
- package/src/modules/index.ts +1256 -0
- package/src/modules/interceptors.ts +574 -0
- package/src/modules/lazy.ts +418 -0
- package/src/modules/lifecycle.ts +478 -0
- package/src/modules/metadata.ts +90 -0
- package/src/modules/pipes.ts +626 -0
- package/src/router/index.ts +339 -0
- package/src/router/linear.ts +371 -0
- package/src/router/regex.ts +292 -0
- package/src/router/tree.ts +562 -0
- package/src/rpc/index.ts +1263 -0
- package/src/security/index.ts +436 -0
- package/src/ssg/index.ts +631 -0
- package/src/storage/index.ts +456 -0
- package/src/telemetry/index.ts +1097 -0
- package/src/testing/index.ts +1586 -0
- package/src/types/index.ts +236 -0
- package/src/types/optional-deps.d.ts +219 -0
- package/src/validation/index.ts +276 -0
- package/src/websocket/index.ts +1004 -0
- package/tests/integration/cli.test.ts +1016 -0
- package/tests/integration/fullstack.test.ts +234 -0
- package/tests/unit/cache.test.ts +174 -0
- package/tests/unit/cli-commands.test.ts +892 -0
- package/tests/unit/cli.test.ts +1258 -0
- package/tests/unit/container.test.ts +279 -0
- package/tests/unit/context.test.ts +221 -0
- package/tests/unit/database.test.ts +183 -0
- package/tests/unit/linear-router.test.ts +280 -0
- package/tests/unit/lock.test.ts +336 -0
- package/tests/unit/middleware.test.ts +184 -0
- package/tests/unit/modules.test.ts +142 -0
- package/tests/unit/pubsub.test.ts +257 -0
- package/tests/unit/regex-router.test.ts +265 -0
- package/tests/unit/router.test.ts +373 -0
- package/tests/unit/rpc.test.ts +1248 -0
- package/tests/unit/security.test.ts +174 -0
- package/tests/unit/telemetry.test.ts +371 -0
- package/tests/unit/test-cache.test.ts +110 -0
- package/tests/unit/test-database.test.ts +282 -0
- package/tests/unit/tree-router.test.ts +325 -0
- package/tests/unit/validation.test.ts +794 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy Loading System
|
|
3
|
+
*
|
|
4
|
+
* Provides on-demand module loading for improved startup time
|
|
5
|
+
* and reduced memory usage for large applications.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Container, Token, Provider } from "../container";
|
|
9
|
+
import { Injectable } from "./metadata";
|
|
10
|
+
import { Inject } from "./index";
|
|
11
|
+
|
|
12
|
+
// ============= Types =============
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Constructor type for module classes
|
|
16
|
+
*/
|
|
17
|
+
export type Constructor = new (...args: unknown[]) => unknown;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Lazy module loader interface
|
|
21
|
+
*/
|
|
22
|
+
export interface LazyModuleLoader {
|
|
23
|
+
/**
|
|
24
|
+
* Load the lazy module
|
|
25
|
+
*/
|
|
26
|
+
load(): Promise<void>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check if the module is already loaded
|
|
30
|
+
*/
|
|
31
|
+
isLoaded(): boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Module loader function type for dynamic imports
|
|
36
|
+
*/
|
|
37
|
+
export type ModuleLoaderFn = () => Promise<Constructor>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Metadata for lazy modules
|
|
41
|
+
*/
|
|
42
|
+
export interface LazyModuleMetadata {
|
|
43
|
+
loader: ModuleLoaderFn;
|
|
44
|
+
loaded: boolean;
|
|
45
|
+
loadedModule?: Constructor;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ============= Metadata Storage =============
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* WeakMap storage for lazy module metadata
|
|
52
|
+
*/
|
|
53
|
+
const lazyModuleMetadata = new WeakMap<Constructor, LazyModuleMetadata>();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Set lazy module metadata
|
|
57
|
+
*/
|
|
58
|
+
function setLazyMetadata(
|
|
59
|
+
target: Constructor,
|
|
60
|
+
metadata: LazyModuleMetadata,
|
|
61
|
+
): void {
|
|
62
|
+
lazyModuleMetadata.set(target, metadata);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get lazy module metadata
|
|
67
|
+
*/
|
|
68
|
+
export function getLazyMetadata(
|
|
69
|
+
target: Constructor,
|
|
70
|
+
): LazyModuleMetadata | undefined {
|
|
71
|
+
return lazyModuleMetadata.get(target);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Check if a module is a lazy module
|
|
76
|
+
*/
|
|
77
|
+
export function isLazyModule(target: Constructor): boolean {
|
|
78
|
+
return lazyModuleMetadata.has(target);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============= Lazy Module Loader Implementation =============
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Implementation of LazyModuleLoader
|
|
85
|
+
*/
|
|
86
|
+
export class LazyModuleLoaderImpl implements LazyModuleLoader {
|
|
87
|
+
private loaded = false;
|
|
88
|
+
private loadingPromise: Promise<void> | null = null;
|
|
89
|
+
private loader: ModuleLoaderFn;
|
|
90
|
+
private onModuleLoaded?: (moduleClass: Constructor) => Promise<void>;
|
|
91
|
+
|
|
92
|
+
constructor(
|
|
93
|
+
loader: ModuleLoaderFn,
|
|
94
|
+
onModuleLoaded?: (moduleClass: Constructor) => Promise<void>,
|
|
95
|
+
) {
|
|
96
|
+
this.loader = loader;
|
|
97
|
+
this.onModuleLoaded = onModuleLoaded;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async load(): Promise<void> {
|
|
101
|
+
// Return existing promise if already loading
|
|
102
|
+
if (this.loadingPromise) {
|
|
103
|
+
return this.loadingPromise;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Already loaded
|
|
107
|
+
if (this.loaded) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Start loading
|
|
112
|
+
this.loadingPromise = this.doLoad();
|
|
113
|
+
await this.loadingPromise;
|
|
114
|
+
this.loadingPromise = null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private async doLoad(): Promise<void> {
|
|
118
|
+
try {
|
|
119
|
+
const moduleClass = await this.loader();
|
|
120
|
+
this.loaded = true;
|
|
121
|
+
|
|
122
|
+
// Notify callback if provided
|
|
123
|
+
if (this.onModuleLoaded) {
|
|
124
|
+
await this.onModuleLoaded(moduleClass);
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
this.loadingPromise = null;
|
|
128
|
+
throw new Error(
|
|
129
|
+
`Failed to load lazy module: ${error instanceof Error ? error.message : String(error)}`,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
isLoaded(): boolean {
|
|
135
|
+
return this.loaded;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============= Lazy Module Decorator =============
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Decorator to mark a module as lazy-loaded
|
|
143
|
+
*
|
|
144
|
+
* @param loader - Function that returns a Promise resolving to the module class
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* @LazyModule(() => import('./users.module').then(m => m.UsersModule))
|
|
149
|
+
* export class LazyUsersModule {}
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export function LazyModule(loader: ModuleLoaderFn): ClassDecorator {
|
|
153
|
+
return <TFunction extends Function>(target: TFunction): TFunction => {
|
|
154
|
+
// Store metadata about the lazy module
|
|
155
|
+
setLazyMetadata(target as unknown as Constructor, {
|
|
156
|
+
loader,
|
|
157
|
+
loaded: false,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return target;
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ============= Module Loader Service =============
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Token for the ModuleLoader service
|
|
168
|
+
*/
|
|
169
|
+
export const MODULE_LOADER_TOKEN = Symbol.for("ModuleLoader") as Token<ModuleLoader>;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Options for loading lazy modules
|
|
173
|
+
*/
|
|
174
|
+
export interface LoadModuleOptions {
|
|
175
|
+
/**
|
|
176
|
+
* Skip lifecycle hooks when loading
|
|
177
|
+
*/
|
|
178
|
+
skipLifecycle?: boolean;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Module loader service for programmatically loading lazy modules
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* @Controller('admin')
|
|
187
|
+
* class AdminController {
|
|
188
|
+
* constructor(private moduleLoader: ModuleLoader) {}
|
|
189
|
+
*
|
|
190
|
+
* @Post('load-users-module')
|
|
191
|
+
* async loadUsersModule() {
|
|
192
|
+
* await this.moduleLoader.load(LazyUsersModule);
|
|
193
|
+
* return { message: 'Users module loaded' };
|
|
194
|
+
* }
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
@Injectable()
|
|
199
|
+
export class ModuleLoader {
|
|
200
|
+
private container: Container;
|
|
201
|
+
private loadedModules = new Set<Constructor>();
|
|
202
|
+
private moduleLoaders = new Map<Constructor, LazyModuleLoaderImpl>();
|
|
203
|
+
private onModuleLoadCallback?: (
|
|
204
|
+
moduleClass: Constructor,
|
|
205
|
+
) => Promise<void>;
|
|
206
|
+
|
|
207
|
+
constructor(container: Container) {
|
|
208
|
+
this.container = container;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Set callback to be called when a module is loaded
|
|
213
|
+
* Used by Application to register controllers and providers
|
|
214
|
+
*/
|
|
215
|
+
setOnModuleLoadCallback(
|
|
216
|
+
callback: (moduleClass: Constructor) => Promise<void>,
|
|
217
|
+
): void {
|
|
218
|
+
this.onModuleLoadCallback = callback;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Load a lazy module by its token/class
|
|
223
|
+
*
|
|
224
|
+
* @param moduleToken - The module class or token to load
|
|
225
|
+
* @param options - Options for loading
|
|
226
|
+
*/
|
|
227
|
+
async load(
|
|
228
|
+
moduleToken: Token | Constructor,
|
|
229
|
+
options: LoadModuleOptions = {},
|
|
230
|
+
): Promise<void> {
|
|
231
|
+
// Normalize to Constructor if it's a token
|
|
232
|
+
const moduleClass =
|
|
233
|
+
typeof moduleToken === "function"
|
|
234
|
+
? (moduleToken as Constructor)
|
|
235
|
+
: null;
|
|
236
|
+
|
|
237
|
+
if (!moduleClass) {
|
|
238
|
+
throw new Error("Module token must be a class constructor");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Check if already loaded
|
|
242
|
+
if (this.isLoaded(moduleClass)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check if it's a lazy module
|
|
247
|
+
const metadata = getLazyMetadata(moduleClass);
|
|
248
|
+
if (!metadata) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`Module ${moduleClass.name} is not a lazy module. Use @LazyModule decorator.`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Get or create loader
|
|
255
|
+
let loader = this.moduleLoaders.get(moduleClass);
|
|
256
|
+
if (!loader) {
|
|
257
|
+
loader = new LazyModuleLoaderImpl(
|
|
258
|
+
metadata.loader,
|
|
259
|
+
async (loadedModule) => {
|
|
260
|
+
// Update metadata
|
|
261
|
+
metadata.loaded = true;
|
|
262
|
+
metadata.loadedModule = loadedModule;
|
|
263
|
+
|
|
264
|
+
// Call the callback if set
|
|
265
|
+
if (this.onModuleLoadCallback && !options.skipLifecycle) {
|
|
266
|
+
await this.onModuleLoadCallback(loadedModule);
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
);
|
|
270
|
+
this.moduleLoaders.set(moduleClass, loader);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
await loader.load();
|
|
274
|
+
this.loadedModules.add(moduleClass);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Check if a module is loaded
|
|
279
|
+
*
|
|
280
|
+
* @param moduleToken - The module class or token to check
|
|
281
|
+
*/
|
|
282
|
+
isLoaded(moduleToken: Token | Constructor): boolean {
|
|
283
|
+
if (typeof moduleToken === "function") {
|
|
284
|
+
const metadata = getLazyMetadata(moduleToken as Constructor);
|
|
285
|
+
if (metadata) {
|
|
286
|
+
return metadata.loaded;
|
|
287
|
+
}
|
|
288
|
+
return this.loadedModules.has(moduleToken as unknown as Constructor);
|
|
289
|
+
}
|
|
290
|
+
return this.loadedModules.has(moduleToken as unknown as Constructor);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get all loaded module classes
|
|
295
|
+
*/
|
|
296
|
+
getLoadedModules(): Constructor[] {
|
|
297
|
+
return Array.from(this.loadedModules);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Preload multiple lazy modules
|
|
302
|
+
*
|
|
303
|
+
* @param moduleTokens - Array of module tokens to preload
|
|
304
|
+
*/
|
|
305
|
+
async preload(moduleTokens: Array<Token | Constructor>): Promise<void> {
|
|
306
|
+
await Promise.all(moduleTokens.map((token) => this.load(token)));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// ============= Lazy Module Registry =============
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Registry for tracking lazy modules across the application
|
|
314
|
+
*/
|
|
315
|
+
export class LazyModuleRegistry {
|
|
316
|
+
private static instance: LazyModuleRegistry;
|
|
317
|
+
private lazyModules = new Map<Token, LazyModuleMetadata>();
|
|
318
|
+
|
|
319
|
+
private constructor() {}
|
|
320
|
+
|
|
321
|
+
static getInstance(): LazyModuleRegistry {
|
|
322
|
+
if (!LazyModuleRegistry.instance) {
|
|
323
|
+
LazyModuleRegistry.instance = new LazyModuleRegistry();
|
|
324
|
+
}
|
|
325
|
+
return LazyModuleRegistry.instance;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Register a lazy module
|
|
330
|
+
*/
|
|
331
|
+
register(token: Token, metadata: LazyModuleMetadata): void {
|
|
332
|
+
this.lazyModules.set(token, metadata);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Get lazy module metadata
|
|
337
|
+
*/
|
|
338
|
+
get(token: Token): LazyModuleMetadata | undefined {
|
|
339
|
+
return this.lazyModules.get(token);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Check if a token is a registered lazy module
|
|
344
|
+
*/
|
|
345
|
+
has(token: Token): boolean {
|
|
346
|
+
return this.lazyModules.has(token);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Get all registered lazy module tokens
|
|
351
|
+
*/
|
|
352
|
+
getAllTokens(): Token[] {
|
|
353
|
+
return Array.from(this.lazyModules.keys());
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Clear the registry
|
|
358
|
+
*/
|
|
359
|
+
clear(): void {
|
|
360
|
+
this.lazyModules.clear();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ============= Helper Functions =============
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Create a lazy module loader for dynamic imports
|
|
368
|
+
*
|
|
369
|
+
* @param importFn - Dynamic import function
|
|
370
|
+
* @param exportName - Name of the exported module class (default: 'default')
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```typescript
|
|
374
|
+
* const loadUsersModule = createLazyLoader(
|
|
375
|
+
* () => import('./users.module'),
|
|
376
|
+
* 'UsersModule'
|
|
377
|
+
* );
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
export function createLazyLoader(
|
|
381
|
+
importFn: () => Promise<Record<string, unknown>>,
|
|
382
|
+
exportName = "default",
|
|
383
|
+
): ModuleLoaderFn {
|
|
384
|
+
return async () => {
|
|
385
|
+
const module = await importFn();
|
|
386
|
+
const moduleClass = module[exportName] as Constructor;
|
|
387
|
+
if (!moduleClass) {
|
|
388
|
+
throw new Error(
|
|
389
|
+
`Export "${exportName}" not found in lazy loaded module`,
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
return moduleClass;
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Check if all lazy modules in a list are loaded
|
|
398
|
+
*/
|
|
399
|
+
export function areAllLazyModulesLoaded(
|
|
400
|
+
modules: Constructor[],
|
|
401
|
+
): boolean {
|
|
402
|
+
return modules.every((module) => {
|
|
403
|
+
const metadata = getLazyMetadata(module);
|
|
404
|
+
return !metadata || metadata.loaded;
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Get list of unloaded lazy modules
|
|
410
|
+
*/
|
|
411
|
+
export function getUnloadedLazyModules(
|
|
412
|
+
modules: Constructor[],
|
|
413
|
+
): Constructor[] {
|
|
414
|
+
return modules.filter((module) => {
|
|
415
|
+
const metadata = getLazyMetadata(module);
|
|
416
|
+
return metadata && !metadata.loaded;
|
|
417
|
+
});
|
|
418
|
+
}
|