onelaraveljs 1.0.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/README.md +87 -0
- package/docs/integration_analysis.md +116 -0
- package/docs/onejs_analysis.md +108 -0
- package/docs/optimization_implementation_group2.md +458 -0
- package/docs/optimization_plan.md +130 -0
- package/index.js +16 -0
- package/package.json +13 -0
- package/src/app.js +61 -0
- package/src/core/API.js +72 -0
- package/src/core/ChildrenRegistry.js +410 -0
- package/src/core/DOMBatcher.js +207 -0
- package/src/core/ErrorBoundary.js +226 -0
- package/src/core/EventDelegator.js +416 -0
- package/src/core/Helper.js +817 -0
- package/src/core/LoopContext.js +97 -0
- package/src/core/OneDOM.js +246 -0
- package/src/core/OneMarkup.js +444 -0
- package/src/core/Router.js +996 -0
- package/src/core/SEOConfig.js +321 -0
- package/src/core/SectionEngine.js +75 -0
- package/src/core/TemplateEngine.js +83 -0
- package/src/core/View.js +273 -0
- package/src/core/ViewConfig.js +229 -0
- package/src/core/ViewController.js +1410 -0
- package/src/core/ViewControllerOptimized.js +164 -0
- package/src/core/ViewIdentifier.js +361 -0
- package/src/core/ViewLoader.js +272 -0
- package/src/core/ViewManager.js +1962 -0
- package/src/core/ViewState.js +761 -0
- package/src/core/ViewSystem.js +301 -0
- package/src/core/ViewTemplate.js +4 -0
- package/src/core/helpers/BindingHelper.js +239 -0
- package/src/core/helpers/ConfigHelper.js +37 -0
- package/src/core/helpers/EventHelper.js +172 -0
- package/src/core/helpers/LifecycleHelper.js +17 -0
- package/src/core/helpers/ReactiveHelper.js +169 -0
- package/src/core/helpers/RenderHelper.js +15 -0
- package/src/core/helpers/ResourceHelper.js +89 -0
- package/src/core/helpers/TemplateHelper.js +11 -0
- package/src/core/managers/BindingManager.js +671 -0
- package/src/core/managers/ConfigurationManager.js +136 -0
- package/src/core/managers/EventManager.js +309 -0
- package/src/core/managers/LifecycleManager.js +356 -0
- package/src/core/managers/ReactiveManager.js +334 -0
- package/src/core/managers/RenderEngine.js +292 -0
- package/src/core/managers/ResourceManager.js +441 -0
- package/src/core/managers/ViewHierarchyManager.js +258 -0
- package/src/core/managers/ViewTemplateManager.js +127 -0
- package/src/core/reactive/ReactiveComponent.js +592 -0
- package/src/core/services/EventService.js +418 -0
- package/src/core/services/HttpService.js +106 -0
- package/src/core/services/LoggerService.js +57 -0
- package/src/core/services/StateService.js +512 -0
- package/src/core/services/StorageService.js +856 -0
- package/src/core/services/StoreService.js +258 -0
- package/src/core/services/TemplateDetectorService.js +361 -0
- package/src/core/services/Test.js +18 -0
- package/src/helpers/devWarnings.js +205 -0
- package/src/helpers/performance.js +226 -0
- package/src/helpers/utils.js +287 -0
- package/src/init.js +343 -0
- package/src/plugins/auto-plugin.js +34 -0
- package/src/services/Test.js +18 -0
- package/src/types/index.js +193 -0
- package/src/utils/date-helper.js +51 -0
- package/src/utils/helpers.js +39 -0
- package/src/utils/validation.js +32 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic View Loader
|
|
3
|
+
* Provides lazy loading and code splitting for views
|
|
4
|
+
*
|
|
5
|
+
* @module core/ViewLoader
|
|
6
|
+
* @author OneLaravel Team
|
|
7
|
+
* @since 2025-12-29
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import logger from './services/LoggerService.js';
|
|
11
|
+
import { warn, invariant } from '../helpers/devWarnings.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* View Loader - Handles dynamic view loading with caching
|
|
15
|
+
*
|
|
16
|
+
* @class ViewLoader
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const loader = new ViewLoader();
|
|
20
|
+
* const ViewClass = await loader.load('web.pages.home');
|
|
21
|
+
*/
|
|
22
|
+
export class ViewLoader {
|
|
23
|
+
constructor() {
|
|
24
|
+
/**
|
|
25
|
+
* @type {Map<string, Function>}
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
this.viewCache = new Map();
|
|
29
|
+
/**
|
|
30
|
+
* @type {Object}
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
this.registry = {};
|
|
34
|
+
/**
|
|
35
|
+
* @type {Map<string, Promise<Function>>}
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
this.loadingPromises = new Map();
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @type {Map<string, string>}
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
this.viewPathMap = new Map();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Set view registry
|
|
49
|
+
* @param {Object} registry
|
|
50
|
+
*/
|
|
51
|
+
setRegistry(registry) {
|
|
52
|
+
this.registry = registry;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Register a view path mapping
|
|
57
|
+
*
|
|
58
|
+
* @param {string} viewPath - View path (e.g., 'web.pages.home')
|
|
59
|
+
* @param {string} filePath - File path (e.g., './views/WebPagesHome.js')
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* loader.register('web.pages.home', './views/WebPagesHome.js');
|
|
63
|
+
*/
|
|
64
|
+
register(viewPath, filePath) {
|
|
65
|
+
this.viewPathMap.set(viewPath, filePath);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Register multiple view mappings
|
|
70
|
+
*
|
|
71
|
+
* @param {Object<string, string>} mappings - View path to file path mappings
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* loader.registerBulk({
|
|
75
|
+
* 'web.pages.home': './views/WebPagesHome.js',
|
|
76
|
+
* 'web.pages.about': './views/WebPagesAbout.js',
|
|
77
|
+
* });
|
|
78
|
+
*/
|
|
79
|
+
registerBulk(mappings) {
|
|
80
|
+
Object.entries(mappings).forEach(([viewPath, filePath]) => {
|
|
81
|
+
this.register(viewPath, filePath);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Load a view dynamically
|
|
87
|
+
*
|
|
88
|
+
* @param {string} viewPath - View path
|
|
89
|
+
* @returns {Promise<Function>} View class/function
|
|
90
|
+
* @throws {Error} If view cannot be loaded
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* const ViewClass = await loader.load('web.pages.home');
|
|
94
|
+
* const view = ViewClass(data, systemData);
|
|
95
|
+
*/
|
|
96
|
+
async load(viewPath) {
|
|
97
|
+
invariant(viewPath, 'View path is required');
|
|
98
|
+
|
|
99
|
+
// Check cache first
|
|
100
|
+
if (this.viewCache.has(viewPath)) {
|
|
101
|
+
logger.debug(`[ViewLoader] Loading from cache: ${viewPath}`);
|
|
102
|
+
return this.viewCache.get(viewPath);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Check if already loading
|
|
106
|
+
if (this.loadingPromises.has(viewPath)) {
|
|
107
|
+
logger.debug(`[ViewLoader] Waiting for in-progress load: ${viewPath}`);
|
|
108
|
+
return this.loadingPromises.get(viewPath);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Get file path
|
|
112
|
+
const filePath = this.viewPathMap.get(viewPath);
|
|
113
|
+
|
|
114
|
+
if (!filePath) {
|
|
115
|
+
warn(false, `View path not registered: ${viewPath}`);
|
|
116
|
+
throw new Error(`[ViewLoader] View not found: ${viewPath}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Create loading promise
|
|
120
|
+
const loadingPromise = this._loadViewModule(viewPath, filePath);
|
|
121
|
+
this.loadingPromises.set(viewPath, loadingPromise);
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const ViewClass = await loadingPromise;
|
|
125
|
+
|
|
126
|
+
// Cache the loaded view
|
|
127
|
+
this.viewCache.set(viewPath, ViewClass);
|
|
128
|
+
logger.debug(`[ViewLoader] Successfully loaded: ${viewPath}`);
|
|
129
|
+
|
|
130
|
+
return ViewClass;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
logger.error(`[ViewLoader] Failed to load view: ${viewPath}`, error);
|
|
133
|
+
throw error;
|
|
134
|
+
} finally {
|
|
135
|
+
// Remove from loading promises
|
|
136
|
+
this.loadingPromises.delete(viewPath);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Load view module using dynamic import from registry
|
|
142
|
+
*
|
|
143
|
+
* @param {string} viewPath - View path
|
|
144
|
+
* @param {string} filePath - File path (kept for backward compatibility)
|
|
145
|
+
* @returns {Promise<Function>} View class/function
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
async _loadViewModule(viewPath, filePath) {
|
|
149
|
+
logger.debug(`[ViewLoader] Loading module: ${viewPath}`);
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
// Use this.registry for static analysis by webpack
|
|
153
|
+
const importFn = this.registry[viewPath];
|
|
154
|
+
|
|
155
|
+
if (!importFn) {
|
|
156
|
+
const errorMsg = `View "${viewPath}" not found in registry. Make sure view is registered via setRegistry()`;
|
|
157
|
+
logger.error(`[ViewLoader] ${errorMsg}`);
|
|
158
|
+
throw new Error(errorMsg);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Load from registry (webpack can analyze this statically)
|
|
162
|
+
const module = await importFn();
|
|
163
|
+
|
|
164
|
+
// Get the view function from module
|
|
165
|
+
const ViewClass = module.default || module[this._getFunctionName(viewPath)];
|
|
166
|
+
|
|
167
|
+
if (!ViewClass) {
|
|
168
|
+
throw new Error(`View function not found in module: ${viewPath}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return ViewClass;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
logger.error(`[ViewLoader] Import failed: ${viewPath}`, error);
|
|
174
|
+
throw new Error(`Failed to load view module: ${error.message}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Convert view path to function name
|
|
180
|
+
*
|
|
181
|
+
* @param {string} viewPath - View path (e.g., 'web.pages.home')
|
|
182
|
+
* @returns {string} Function name (e.g., 'WebPagesHome')
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
_getFunctionName(viewPath) {
|
|
186
|
+
return viewPath
|
|
187
|
+
.split('.')
|
|
188
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
189
|
+
.join('');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Preload views for better performance
|
|
194
|
+
*
|
|
195
|
+
* @param {Array<string>} viewPaths - View paths to preload
|
|
196
|
+
* @returns {Promise<void>}
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* await loader.preload(['web.pages.home', 'web.pages.about']);
|
|
200
|
+
*/
|
|
201
|
+
async preload(viewPaths) {
|
|
202
|
+
logger.debug('[ViewLoader] Preloading views:', viewPaths);
|
|
203
|
+
|
|
204
|
+
const promises = viewPaths.map(viewPath => {
|
|
205
|
+
return this.load(viewPath).catch(error => {
|
|
206
|
+
logger.warn(`[ViewLoader] Failed to preload: ${viewPath}`, error);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
await Promise.all(promises);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Clear cache for a specific view or all views
|
|
215
|
+
*
|
|
216
|
+
* @param {string} [viewPath] - View path (if omitted, clears all)
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* loader.clearCache('web.pages.home'); // Clear specific view
|
|
220
|
+
* loader.clearCache(); // Clear all
|
|
221
|
+
*/
|
|
222
|
+
clearCache(viewPath = null) {
|
|
223
|
+
if (viewPath) {
|
|
224
|
+
this.viewCache.delete(viewPath);
|
|
225
|
+
logger.debug(`[ViewLoader] Cleared cache: ${viewPath}`);
|
|
226
|
+
} else {
|
|
227
|
+
this.viewCache.clear();
|
|
228
|
+
logger.debug('[ViewLoader] Cleared all cache');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Get cache statistics
|
|
234
|
+
*
|
|
235
|
+
* @returns {Object} Cache stats
|
|
236
|
+
*/
|
|
237
|
+
getCacheStats() {
|
|
238
|
+
return {
|
|
239
|
+
cached: this.viewCache.size,
|
|
240
|
+
loading: this.loadingPromises.size,
|
|
241
|
+
registered: this.viewPathMap.size,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Check if view is cached
|
|
247
|
+
*
|
|
248
|
+
* @param {string} viewPath - View path
|
|
249
|
+
* @returns {boolean}
|
|
250
|
+
*/
|
|
251
|
+
isCached(viewPath) {
|
|
252
|
+
return this.viewCache.has(viewPath);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Check if view is currently loading
|
|
257
|
+
*
|
|
258
|
+
* @param {string} viewPath - View path
|
|
259
|
+
* @returns {boolean}
|
|
260
|
+
*/
|
|
261
|
+
isLoading(viewPath) {
|
|
262
|
+
return this.loadingPromises.has(viewPath);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Global view loader instance
|
|
268
|
+
* @type {ViewLoader}
|
|
269
|
+
*/
|
|
270
|
+
export const viewLoader = new ViewLoader();
|
|
271
|
+
|
|
272
|
+
export default viewLoader;
|