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.
Files changed (67) hide show
  1. package/README.md +87 -0
  2. package/docs/integration_analysis.md +116 -0
  3. package/docs/onejs_analysis.md +108 -0
  4. package/docs/optimization_implementation_group2.md +458 -0
  5. package/docs/optimization_plan.md +130 -0
  6. package/index.js +16 -0
  7. package/package.json +13 -0
  8. package/src/app.js +61 -0
  9. package/src/core/API.js +72 -0
  10. package/src/core/ChildrenRegistry.js +410 -0
  11. package/src/core/DOMBatcher.js +207 -0
  12. package/src/core/ErrorBoundary.js +226 -0
  13. package/src/core/EventDelegator.js +416 -0
  14. package/src/core/Helper.js +817 -0
  15. package/src/core/LoopContext.js +97 -0
  16. package/src/core/OneDOM.js +246 -0
  17. package/src/core/OneMarkup.js +444 -0
  18. package/src/core/Router.js +996 -0
  19. package/src/core/SEOConfig.js +321 -0
  20. package/src/core/SectionEngine.js +75 -0
  21. package/src/core/TemplateEngine.js +83 -0
  22. package/src/core/View.js +273 -0
  23. package/src/core/ViewConfig.js +229 -0
  24. package/src/core/ViewController.js +1410 -0
  25. package/src/core/ViewControllerOptimized.js +164 -0
  26. package/src/core/ViewIdentifier.js +361 -0
  27. package/src/core/ViewLoader.js +272 -0
  28. package/src/core/ViewManager.js +1962 -0
  29. package/src/core/ViewState.js +761 -0
  30. package/src/core/ViewSystem.js +301 -0
  31. package/src/core/ViewTemplate.js +4 -0
  32. package/src/core/helpers/BindingHelper.js +239 -0
  33. package/src/core/helpers/ConfigHelper.js +37 -0
  34. package/src/core/helpers/EventHelper.js +172 -0
  35. package/src/core/helpers/LifecycleHelper.js +17 -0
  36. package/src/core/helpers/ReactiveHelper.js +169 -0
  37. package/src/core/helpers/RenderHelper.js +15 -0
  38. package/src/core/helpers/ResourceHelper.js +89 -0
  39. package/src/core/helpers/TemplateHelper.js +11 -0
  40. package/src/core/managers/BindingManager.js +671 -0
  41. package/src/core/managers/ConfigurationManager.js +136 -0
  42. package/src/core/managers/EventManager.js +309 -0
  43. package/src/core/managers/LifecycleManager.js +356 -0
  44. package/src/core/managers/ReactiveManager.js +334 -0
  45. package/src/core/managers/RenderEngine.js +292 -0
  46. package/src/core/managers/ResourceManager.js +441 -0
  47. package/src/core/managers/ViewHierarchyManager.js +258 -0
  48. package/src/core/managers/ViewTemplateManager.js +127 -0
  49. package/src/core/reactive/ReactiveComponent.js +592 -0
  50. package/src/core/services/EventService.js +418 -0
  51. package/src/core/services/HttpService.js +106 -0
  52. package/src/core/services/LoggerService.js +57 -0
  53. package/src/core/services/StateService.js +512 -0
  54. package/src/core/services/StorageService.js +856 -0
  55. package/src/core/services/StoreService.js +258 -0
  56. package/src/core/services/TemplateDetectorService.js +361 -0
  57. package/src/core/services/Test.js +18 -0
  58. package/src/helpers/devWarnings.js +205 -0
  59. package/src/helpers/performance.js +226 -0
  60. package/src/helpers/utils.js +287 -0
  61. package/src/init.js +343 -0
  62. package/src/plugins/auto-plugin.js +34 -0
  63. package/src/services/Test.js +18 -0
  64. package/src/types/index.js +193 -0
  65. package/src/utils/date-helper.js +51 -0
  66. package/src/utils/helpers.js +39 -0
  67. package/src/utils/validation.js +32 -0
package/src/init.js ADDED
@@ -0,0 +1,343 @@
1
+ /**
2
+ * init Module
3
+ * ES6 Module for Blade Compiler
4
+ */
5
+
6
+ // import { App } from './app.js';
7
+
8
+ function initApp(App) {
9
+ App = App || window.App;
10
+
11
+ // Check if APP_CONFIGS is available
12
+ if (typeof window.APP_CONFIGS === 'undefined') {
13
+ console.error('APP_CONFIGS not found! Please define window.APP_CONFIGS in your HTML.');
14
+ return;
15
+ }
16
+
17
+ console.log('✅ APP_CONFIGS found:', window.APP_CONFIGS);
18
+
19
+ const config = window.APP_CONFIGS;
20
+
21
+ // Validate required App modules
22
+ if (typeof App === 'undefined') {
23
+ console.error('App core module not found! Please ensure app.main.js is loaded.');
24
+ return;
25
+ }
26
+
27
+ // Validate config structure
28
+ if (!config || typeof config !== 'object') {
29
+ console.error('Invalid APP_CONFIGS! Config must be an object.');
30
+ return;
31
+ }
32
+
33
+ // Initialize view container first
34
+ const container = config.container ? (
35
+ typeof config.container === 'string' ? (
36
+ document.querySelector(config.container) || document.body
37
+ ) : (config.container instanceof HTMLElement ? config.container : document.body)
38
+ ) : document.body;
39
+ if (container) {
40
+ App.View.setContainer(container);
41
+ } else {
42
+ console.warn('⚠️ No container specified and no default container found');
43
+ }
44
+
45
+ const isServerRendered = container.getAttribute('data-server-rendered') === 'true';
46
+
47
+ App.env = {...App.env, ...config.env};
48
+
49
+ if (App.View) {
50
+ // If server-rendered, ensure view container is properly hydrated
51
+ if (isServerRendered) {
52
+ // Mark container as hydrated without re-rendering content
53
+ App.View._isHydrated = true;
54
+ }
55
+
56
+ // Initialize View configuration
57
+ if (App.View && config.view) {
58
+ App.View.init(config.view);
59
+ } else if (config.view) {
60
+ console.warn('⚠️ View configuration provided but App.View not found');
61
+ }
62
+
63
+ }
64
+
65
+ // Initialize API configuration
66
+ if (config.api && App.Http) {
67
+ if (config.api.baseUrl) {
68
+ App.Http.setBaseUrl(config.api.baseUrl);
69
+ }
70
+
71
+ // Set default headers including CSRF token
72
+ const defaultHeaders = {
73
+ 'Content-Type': 'application/json',
74
+ 'X-Requested-With': 'XMLHttpRequest'
75
+ };
76
+
77
+ if (config.api.csrfToken) {
78
+ defaultHeaders['X-CSRF-TOKEN'] = config.api.csrfToken;
79
+ }
80
+
81
+ App.Http.setDefaultHeaders(defaultHeaders);
82
+ App.Http.setTimeout(config.api.timeout || 10000);
83
+
84
+ } else if (config.api) {
85
+ console.warn('⚠️ API configuration provided but AppInstance.HttpService not found');
86
+ } else {
87
+ console.warn('⚠️ No API configuration provided');
88
+ }
89
+
90
+ // Initialize router configuration
91
+ if (App.Router) {
92
+ if (config.router.allRoutes) {
93
+ App.Router.setAllRoutes(config.router.allRoutes);
94
+ }
95
+ // Get routes from router config or fallback to top-level routes
96
+ let routes = config.router?.routes || config.routes;
97
+ if (!routes || !Array.isArray(routes) || routes.length === 0) {
98
+ const scope = config.appScope || 'web';
99
+ routes = [
100
+ { path: `/${scope}`, view: `${scope}.home` },
101
+ { path: `/${scope}/about`, view: `${scope}.about` },
102
+ { path: `/${scope}/users`, view: `${scope}.users` },
103
+ { path: `/${scope}/users/:id`, view: `${scope}.user-detail` },
104
+ { path: `/${scope}/contact`, view: `${scope}.contact` }
105
+ ];
106
+ } else {
107
+ console.log('🔧 Using provided routes:', routes.length);
108
+ }
109
+
110
+ // Register routes
111
+ routes.forEach(route => {
112
+ if (route.path && (route.view || route.component)) {
113
+ const viewName = route.view || route.component;
114
+ App.Router.addRoute(route.path, viewName, route.options || {});
115
+ }
116
+ });
117
+
118
+ // Configure router options
119
+ if (config.router) {
120
+ if (config.router.mode) {
121
+ App.Router.setMode(config.router.mode);
122
+ }
123
+ if (config.router.base) {
124
+ App.Router.setBase(config.router.base);
125
+ }
126
+
127
+ // Setup default router hooks if not provided
128
+ if (!config.router.beforeEach) {
129
+ App.Router.beforeEach(function(to, from) {
130
+ if (App.mode === 'development') {
131
+ console.log('Navigating to:', to.path);
132
+ }
133
+ return true;
134
+ });
135
+ } else {
136
+ App.Router.beforeEach(config.router.beforeEach);
137
+ }
138
+
139
+ if (!config.router.afterEach) {
140
+ App.Router.afterEach(function(to, from) {
141
+ if (App.mode === 'development') {
142
+ console.log('Navigation complete:', to.path || to);
143
+ }
144
+ // to.path should be set from Router, fallback to window.location.pathname
145
+ const path = to.path || window.location.pathname;
146
+ updateActiveNav(path);
147
+ });
148
+ } else {
149
+ App.Router.afterEach(function(to, from) {
150
+ // Call custom afterEach if provided
151
+ if (typeof config.router.afterEach === 'function') {
152
+ config.router.afterEach(to, from);
153
+ }
154
+ // Always update navigation
155
+ // to.path should be set from Router, fallback to window.location.pathname
156
+ const path = to.path || window.location.pathname;
157
+ updateActiveNav(path);
158
+ });
159
+ }
160
+ console.log('✅ Router configuration applied');
161
+ }
162
+
163
+ // Set default route
164
+ const defaultRoute = config.defaultRoute || `/${config.appScope || 'web'}`;
165
+ App.Router.setDefaultRoute(defaultRoute);
166
+
167
+ if (isServerRendered) {
168
+ // Start router but don't handle initial route
169
+ App.Router.start(true); // Pass true to skip initial route handling
170
+
171
+ // Mark as client-side ready after a short delay
172
+ setTimeout(() => {
173
+ if (container) {
174
+ container.setAttribute('data-server-rendered', 'false');
175
+ }
176
+ }, 100);
177
+ } else {
178
+ // Start the router normally
179
+ App.Router.start();
180
+ console.log('✅ Router started');
181
+ }
182
+ } else {
183
+ console.warn('⚠️ Router not available - AppInstance.Router not found');
184
+ }
185
+
186
+ if(config.view){
187
+ if(config.view.superView){
188
+ App.View.setSuperViewPath(config.view.superView);
189
+ }
190
+ }
191
+ // Initialize system data
192
+ // Initialize mode (development/production)
193
+ if (config.mode) {
194
+ App.mode = config.mode;
195
+
196
+ // Enable/disable debug logging based on mode
197
+ if (config.mode === 'development') {
198
+ console.log('🔧 Development mode enabled - debug logging active');
199
+ } else {
200
+ console.log('🏭 Production mode enabled');
201
+ }
202
+ } else {
203
+ // Set default mode
204
+ App.mode = 'development';
205
+ console.warn('⚠️ No mode specified in config, using default: development');
206
+ }
207
+
208
+ // Initialize global data
209
+ App.globalData = {
210
+ siteName: 'One App',
211
+ version: '1.0.0',
212
+ csrfToken: config.api?.csrfToken,
213
+ appScope: config.appScope,
214
+ currentUser: config.currentUser,
215
+ ...(config.data || {})
216
+ };
217
+
218
+ // Initialize language configuration
219
+ if (config.lang) {
220
+ App.lang = {
221
+ current: config.lang.locale || 'en',
222
+ fallback: config.lang.fallback || 'en',
223
+ ...config.lang
224
+ };
225
+ console.log('✅ Language configuration initialized:', App.lang);
226
+ } else {
227
+ // Set default language configuration
228
+ App.lang = {
229
+ current: 'en',
230
+ fallback: 'en'
231
+ };
232
+ console.warn('⚠️ No language configuration provided, using defaults');
233
+ }
234
+
235
+
236
+ // Setup navigation updates
237
+ if (App.View) {
238
+ App.View.on('view:rendered', function (viewName) {
239
+ console.log('View rendered:', viewName);
240
+ updateActiveNav();
241
+ });
242
+ } else {
243
+ console.warn('⚠️ Navigation updates not available - App.View not found');
244
+ }
245
+
246
+ // Custom initialization callback
247
+ if (config.onInit && typeof config.onInit === 'function') {
248
+ try {
249
+ config.onInit(App, config);
250
+ console.log('✅ Custom initialization callback executed');
251
+ } catch (error) {
252
+ console.error('❌ Error in custom initialization callback:', error);
253
+ }
254
+ }
255
+
256
+ // Dispatch App ready event
257
+ try {
258
+ const appReadyEvent = new CustomEvent('app:ready', {
259
+ detail: { App: App, config }
260
+ });
261
+ document.dispatchEvent(appReadyEvent);
262
+ console.log('✅ App ready event dispatched');
263
+ } catch (error) {
264
+ console.error('❌ Error dispatching App ready event:', error);
265
+ }
266
+
267
+ console.log('🎉 App initialization completed successfully!');
268
+ }
269
+
270
+ // Navigation helper function - updates active navigation link
271
+ export function updateActiveNav(currentPath) {
272
+ // Use provided path or current location
273
+ const path = currentPath || window.location.pathname;
274
+
275
+ // Find all navigation links (support multiple selectors)
276
+ const navLinks = document.querySelectorAll('.nav-menu a, .nav-link, nav a[data-navigate]');
277
+
278
+ navLinks.forEach(link => {
279
+ link.classList.remove('active');
280
+
281
+ // Check href attribute
282
+ const href = link.getAttribute('href');
283
+ // Check data-navigate attribute
284
+ const navigatePath = link.getAttribute('data-navigate');
285
+
286
+ // Match if href or data-navigate matches current path
287
+ let isActive = false;
288
+
289
+ // 1. Exact match
290
+ if (href === path || navigatePath === path) {
291
+ isActive = true;
292
+ }
293
+ // 2. Check full URL match
294
+ else {
295
+ const fullUrl = window.location.protocol + '//' + window.location.host + path;
296
+ if (href === fullUrl) {
297
+ isActive = true;
298
+ }
299
+ }
300
+
301
+ // 3. Partial/prefix match for paths with query parameters or dynamic segments
302
+ // e.g., /demo matches /demo/section-name
303
+ if (!isActive && (href || navigatePath)) {
304
+ const basePath = href || navigatePath;
305
+ // Extract base path without query string
306
+ const basePathWithoutQuery = basePath.split('?')[0];
307
+ const currentPathWithoutQuery = path.split('?')[0];
308
+
309
+ // Check if current path starts with nav link path (for routes with parameters)
310
+ if (basePathWithoutQuery && currentPathWithoutQuery.startsWith(basePathWithoutQuery + '/')) {
311
+ isActive = true;
312
+ }
313
+ // Also check exact match after removing query string
314
+ else if (basePathWithoutQuery === currentPathWithoutQuery) {
315
+ isActive = true;
316
+ }
317
+ }
318
+
319
+ if (isActive) {
320
+ link.classList.add('active');
321
+ }
322
+ });
323
+ }
324
+
325
+ // Make updateActiveNav globally available for router hooks
326
+ if (typeof window !== 'undefined') {
327
+ window.updateActiveNav = updateActiveNav;
328
+ }
329
+ // try {
330
+ // // Make updateActiveNav globally available for router config
331
+ // window.updateActiveNav = updateActiveNav;
332
+
333
+ // // Initialize when DOM is ready
334
+ // if (document.readyState === 'loading') {
335
+ // document.addEventListener('DOMContentLoaded', initApp);
336
+ // } else {
337
+ // initApp();
338
+ // }
339
+ // } catch (error) {
340
+ // console.error('❌ Error in init:', error);
341
+ // }
342
+
343
+ export default initApp;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Auto Plugin Module
3
+ * This file in a subdirectory will be automatically discovered
4
+ */
5
+
6
+ export class AutoPlugin {
7
+ constructor() {
8
+ this.name = 'AutoPlugin';
9
+ this.type = 'plugin';
10
+ this.version = '1.0.0';
11
+ }
12
+
13
+ initialize() {
14
+ console.log(`🚀 ${this.name} initialized!`);
15
+ return true;
16
+ }
17
+
18
+ getInfo() {
19
+ return {
20
+ name: this.name,
21
+ type: this.type,
22
+ version: this.version,
23
+ timestamp: new Date().toISOString()
24
+ };
25
+ }
26
+ }
27
+
28
+ // Register with global App object
29
+ if (typeof window !== 'undefined' && window.App) {
30
+ window.App.AutoPlugin = AutoPlugin;
31
+ }
32
+
33
+ // Export for ES6 modules
34
+ export default AutoPlugin;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Test service để demo alias @app
3
+ */
4
+ export class TestService {
5
+ constructor() {
6
+ this.name = 'TestService';
7
+ }
8
+
9
+ getMessage() {
10
+ return `Hello from ${this.name}!`;
11
+ }
12
+
13
+ static create() {
14
+ return new TestService();
15
+ }
16
+ }
17
+
18
+ export default TestService;
@@ -0,0 +1,193 @@
1
+ /**
2
+ * TypeScript-style type definitions using JSDoc
3
+ * This file provides type hints for better IDE support and documentation
4
+ *
5
+ * @module types/index
6
+ * @author OneLaravel Team
7
+ * @since 2025-12-29
8
+ */
9
+
10
+ /**
11
+ * @typedef {Object} Application
12
+ * @property {string} name - Application name
13
+ * @property {Helper} Helper - Helper instance
14
+ * @property {Router} Router - Router instance
15
+ * @property {ViewManager} View - ViewManager instance
16
+ * @property {typeof HttpService} HttpService - HttpService class
17
+ * @property {HttpService} Http - HttpService instance
18
+ * @property {OneMarkup} OneMarkup - OneMarkup class
19
+ * @property {API} Api - API class
20
+ * @property {string} mode - Application mode (development/production)
21
+ * @property {boolean} isInitialized - Initialization status
22
+ * @property {AppEnvironment} env - Environment configuration
23
+ * @property {Function} init - Initialize application
24
+ */
25
+
26
+ /**
27
+ * @typedef {Object} AppEnvironment
28
+ * @property {string} mode - Environment mode (web/mobile)
29
+ * @property {boolean} debug - Debug mode flag
30
+ * @property {string} base_url - Base URL
31
+ * @property {string} csrf_token - CSRF token
32
+ * @property {string} router_mode - Router mode (history/hash)
33
+ */
34
+
35
+ /**
36
+ * @typedef {Object} ViewData
37
+ * @property {string} [__SSR_VIEW_ID__] - Server-side rendered view ID
38
+ * @property {*} [key: string] - Additional data properties
39
+ */
40
+
41
+ /**
42
+ * @typedef {Object} SystemData
43
+ * @property {Application} App - Application instance
44
+ * @property {typeof View} View - View class
45
+ * @property {string} __base__ - Base path
46
+ * @property {string} __layout__ - Layout path
47
+ * @property {string} __page__ - Page path
48
+ * @property {string} __component__ - Component path
49
+ * @property {string} __template__ - Template path
50
+ * @property {string} __partial__ - Partial path
51
+ * @property {string} __system__ - System path
52
+ * @property {Object} __env - Environment data
53
+ * @property {Object} __helper - Helper functions
54
+ */
55
+
56
+ /**
57
+ * @typedef {Object} ViewConfig
58
+ * @property {string} superView - Super view path
59
+ * @property {boolean} hasSuperView - Has super view flag
60
+ * @property {string} viewType - View type (view/layout/component)
61
+ * @property {Object} sections - Section definitions
62
+ * @property {WrapperConfig} wrapperConfig - Wrapper configuration
63
+ * @property {Array<string>} __props__ - Property names
64
+ * @property {boolean} hasAwaitData - Has await data flag
65
+ * @property {boolean} hasFetchData - Has fetch data flag
66
+ * @property {boolean} subscribe - Subscribe flag
67
+ * @property {Object|null} fetch - Fetch configuration
68
+ * @property {ViewData} data - View data
69
+ * @property {string} viewId - View ID
70
+ * @property {string} path - View path
71
+ * @property {boolean} usesVars - Uses vars flag
72
+ * @property {boolean} hasSections - Has sections flag
73
+ * @property {boolean} hasSectionPreload - Has section preload flag
74
+ * @property {boolean} hasPrerender - Has prerender flag
75
+ * @property {Array<string>} renderLongSections - Long sections to render
76
+ * @property {Array<string>} renderSections - Sections to render
77
+ * @property {Array<string>} prerenderSections - Sections to prerender
78
+ * @property {Array<ScriptResource>} scripts - Script resources
79
+ * @property {Array<StyleResource>} styles - Style resources
80
+ * @property {Array<Resource>} resources - Other resources
81
+ * @property {Function} commitConstructorData - Commit constructor data
82
+ * @property {Function} updateVariableData - Update variable data
83
+ * @property {Function} updateVariableItem - Update variable item
84
+ * @property {Function} loadServerData - Load server data
85
+ * @property {Function} prerender - Prerender function
86
+ * @property {Function} render - Render function
87
+ * @property {Function} init - Init function
88
+ * @property {Function} destroy - Destroy function
89
+ */
90
+
91
+ /**
92
+ * @typedef {Object} WrapperConfig
93
+ * @property {boolean} enable - Enable wrapper
94
+ * @property {string|null} tag - Wrapper tag name
95
+ * @property {boolean} subscribe - Subscribe to state changes
96
+ * @property {Object} attributes - Wrapper attributes
97
+ */
98
+
99
+ /**
100
+ * @typedef {Object} Resource
101
+ * @property {string} type - Resource type (src/href/code)
102
+ * @property {string} resourceType - Resource type (script/style)
103
+ * @property {string} [src] - External resource URL
104
+ * @property {string} [href] - External stylesheet URL
105
+ * @property {string} [content] - Inline content
106
+ * @property {string} [function] - Function name for code type
107
+ * @property {string} [id] - Resource ID
108
+ * @property {Object} [attributes] - Additional attributes
109
+ */
110
+
111
+ /**
112
+ * @typedef {Resource} ScriptResource
113
+ * @property {'script'} resourceType
114
+ */
115
+
116
+ /**
117
+ * @typedef {Resource} StyleResource
118
+ * @property {'style'} resourceType
119
+ */
120
+
121
+ /**
122
+ * @typedef {Object} StateDefinition
123
+ * @property {*} value - State value
124
+ * @property {Function} setValue - State setter
125
+ * @property {string} key - State key
126
+ * @property {Array<Function>} subscribers - State subscribers
127
+ */
128
+
129
+ /**
130
+ * @typedef {Object} EventConfig
131
+ * @property {string} eventType - Event type (click/input/etc)
132
+ * @property {Array<EventHandler>} handlers - Event handlers
133
+ * @property {string} eventID - Event ID
134
+ */
135
+
136
+ /**
137
+ * @typedef {Object} EventHandler
138
+ * @property {string|Function} handler - Handler function or name
139
+ * @property {Array<*>} params - Handler parameters
140
+ * @property {Object} options - Handler options
141
+ */
142
+
143
+ /**
144
+ * @typedef {Object} OutputComponentConfig
145
+ * @property {string} outputId - Output ID
146
+ * @property {string} stateKey - State key to watch
147
+ * @property {boolean} escaped - Escape HTML flag
148
+ * @property {HTMLElement} element - Output element
149
+ */
150
+
151
+ /**
152
+ * @typedef {Object} WatchComponentConfig
153
+ * @property {string} watchId - Watch ID
154
+ * @property {string} stateKey - State key to watch
155
+ * @property {Function} callback - Watch callback
156
+ */
157
+
158
+ /**
159
+ * @typedef {Object} RouteConfig
160
+ * @property {string} path - Route path
161
+ * @property {string} name - Route name
162
+ * @property {Function|string} handler - Route handler
163
+ * @property {Object} [meta] - Route metadata
164
+ * @property {Array<Function>} [middleware] - Route middleware
165
+ */
166
+
167
+ /**
168
+ * @typedef {Object} RouterConfig
169
+ * @property {string} mode - Router mode (history/hash)
170
+ * @property {string} base - Base path
171
+ * @property {Function} [scrollBehavior] - Scroll behavior function
172
+ */
173
+
174
+ /**
175
+ * @typedef {Object} HTTPConfig
176
+ * @property {string} baseURL - Base URL
177
+ * @property {Object} headers - Default headers
178
+ * @property {number} timeout - Request timeout
179
+ * @property {Function} [onRequest] - Request interceptor
180
+ * @property {Function} [onResponse] - Response interceptor
181
+ * @property {Function} [onError] - Error interceptor
182
+ */
183
+
184
+ /**
185
+ * @typedef {Object} SSRViewData
186
+ * @property {string} viewId - View ID
187
+ * @property {ViewData} data - View data
188
+ * @property {Object} events - Event configurations
189
+ * @property {Array<string>} children - Child view IDs
190
+ */
191
+
192
+ // Export empty object to make this a module
193
+ export { };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Date Helper Utility Module
3
+ * ES6 Module for date operations
4
+ */
5
+
6
+ export class DateHelper {
7
+ static formatDate(date, format = 'YYYY-MM-DD') {
8
+ const d = new Date(date);
9
+ const year = d.getFullYear();
10
+ const month = String(d.getMonth() + 1).padStart(2, '0');
11
+ const day = String(d.getDate()).padStart(2, '0');
12
+
13
+ return format
14
+ .replace('YYYY', year)
15
+ .replace('MM', month)
16
+ .replace('DD', day);
17
+ }
18
+
19
+ static addDays(date, days) {
20
+ const result = new Date(date);
21
+ result.setDate(result.getDate() + days);
22
+ return result;
23
+ }
24
+
25
+ static addMonths(date, months) {
26
+ const result = new Date(date);
27
+ result.setMonth(result.getMonth() + months);
28
+ return result;
29
+ }
30
+
31
+ static isToday(date) {
32
+ const today = new Date();
33
+ const checkDate = new Date(date);
34
+ return today.toDateString() === checkDate.toDateString();
35
+ }
36
+
37
+ static getDaysBetween(date1, date2) {
38
+ const oneDay = 24 * 60 * 60 * 1000;
39
+ const firstDate = new Date(date1);
40
+ const secondDate = new Date(date2);
41
+ return Math.round(Math.abs((firstDate - secondDate) / oneDay));
42
+ }
43
+ }
44
+
45
+ // Register with global App object
46
+ if (typeof window !== 'undefined' && window.App) {
47
+ window.App.DateHelper = DateHelper;
48
+ }
49
+
50
+ // Export for ES6 modules
51
+ export default DateHelper;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Helpers Utility Module
3
+ * ES6 Module for Blade Compiler
4
+ */
5
+
6
+ import { App } from '../app.js';
7
+
8
+ export class Helpers {
9
+ static formatDate(date) {
10
+ return new Date(date).toLocaleDateString();
11
+ }
12
+
13
+ static formatCurrency(amount) {
14
+ return new Intl.NumberFormat('vi-VN', {
15
+ style: 'currency',
16
+ currency: 'VND'
17
+ }).format(amount);
18
+ }
19
+
20
+ static debounce(func, wait) {
21
+ let timeout;
22
+ return function executedFunction(...args) {
23
+ const later = () => {
24
+ clearTimeout(timeout);
25
+ func(...args);
26
+ };
27
+ clearTimeout(timeout);
28
+ timeout = setTimeout(later, wait);
29
+ };
30
+ }
31
+ }
32
+
33
+ // Register with global App object
34
+ if (typeof window !== 'undefined') {
35
+ window.App.Helpers = Helpers;
36
+ }
37
+
38
+ // Export for ES6 modules
39
+ export default Helpers;