@flexireact/core 3.0.1 → 3.0.2

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 (55) hide show
  1. package/dist/cli/index.js +1514 -0
  2. package/dist/cli/index.js.map +1 -0
  3. package/dist/core/client/index.js +373 -0
  4. package/dist/core/client/index.js.map +1 -0
  5. package/dist/core/index.js +6415 -0
  6. package/dist/core/index.js.map +1 -0
  7. package/dist/core/server/index.js +3094 -0
  8. package/dist/core/server/index.js.map +1 -0
  9. package/package.json +80 -80
  10. package/bin/flexireact.js +0 -23
  11. package/cli/generators.ts +0 -616
  12. package/cli/index.ts +0 -1182
  13. package/core/actions/index.ts +0 -364
  14. package/core/api.ts +0 -143
  15. package/core/build/index.ts +0 -425
  16. package/core/cli/logger.ts +0 -353
  17. package/core/client/Link.tsx +0 -345
  18. package/core/client/hydration.ts +0 -147
  19. package/core/client/index.ts +0 -12
  20. package/core/client/islands.ts +0 -143
  21. package/core/client/navigation.ts +0 -212
  22. package/core/client/runtime.ts +0 -52
  23. package/core/config.ts +0 -116
  24. package/core/context.ts +0 -83
  25. package/core/dev.ts +0 -47
  26. package/core/devtools/index.ts +0 -644
  27. package/core/edge/cache.ts +0 -344
  28. package/core/edge/fetch-polyfill.ts +0 -247
  29. package/core/edge/handler.ts +0 -248
  30. package/core/edge/index.ts +0 -81
  31. package/core/edge/ppr.ts +0 -264
  32. package/core/edge/runtime.ts +0 -161
  33. package/core/font/index.ts +0 -306
  34. package/core/helpers.ts +0 -494
  35. package/core/image/index.ts +0 -413
  36. package/core/index.ts +0 -218
  37. package/core/islands/index.ts +0 -293
  38. package/core/loader.ts +0 -111
  39. package/core/logger.ts +0 -242
  40. package/core/metadata/index.ts +0 -622
  41. package/core/middleware/index.ts +0 -416
  42. package/core/plugins/index.ts +0 -373
  43. package/core/render/index.ts +0 -1243
  44. package/core/render.ts +0 -136
  45. package/core/router/index.ts +0 -551
  46. package/core/router.ts +0 -141
  47. package/core/rsc/index.ts +0 -199
  48. package/core/server/index.ts +0 -779
  49. package/core/server.ts +0 -203
  50. package/core/ssg/index.ts +0 -346
  51. package/core/start-dev.ts +0 -6
  52. package/core/start-prod.ts +0 -6
  53. package/core/tsconfig.json +0 -30
  54. package/core/types.ts +0 -239
  55. package/core/utils.ts +0 -176
@@ -1,373 +0,0 @@
1
- /**
2
- * FlexiReact Plugin System
3
- *
4
- * Plugins can extend FlexiReact's functionality by hooking into various lifecycle events.
5
- *
6
- * Usage:
7
- * Create a flexireact.plugin.js file:
8
- *
9
- * export default {
10
- * name: 'my-plugin',
11
- *
12
- * // Called when the server starts
13
- * onServerStart(server) {},
14
- *
15
- * // Called before each request
16
- * onRequest(req, res) {},
17
- *
18
- * // Called before rendering a page
19
- * onBeforeRender(page, props) {},
20
- *
21
- * // Called after rendering a page
22
- * onAfterRender(html, page) {},
23
- *
24
- * // Called during build
25
- * onBuild(config) {},
26
- *
27
- * // Modify esbuild config
28
- * esbuildConfig(config) {},
29
- * };
30
- */
31
-
32
- import fs from 'fs';
33
- import path from 'path';
34
- import { pathToFileURL } from 'url';
35
-
36
- /**
37
- * Plugin lifecycle hooks
38
- */
39
- export const PluginHooks = {
40
- // Server lifecycle
41
- SERVER_START: 'onServerStart',
42
- SERVER_STOP: 'onServerStop',
43
-
44
- // Request lifecycle
45
- REQUEST: 'onRequest',
46
- RESPONSE: 'onResponse',
47
-
48
- // Render lifecycle
49
- BEFORE_RENDER: 'onBeforeRender',
50
- AFTER_RENDER: 'onAfterRender',
51
-
52
- // Build lifecycle
53
- BUILD_START: 'onBuildStart',
54
- BUILD_END: 'onBuildEnd',
55
-
56
- // Route lifecycle
57
- ROUTES_LOADED: 'onRoutesLoaded',
58
-
59
- // Config
60
- CONFIG: 'onConfig',
61
- ESBUILD_CONFIG: 'esbuildConfig'
62
- };
63
-
64
- /**
65
- * Plugin manager class
66
- */
67
- export class PluginManager {
68
- plugins: any[];
69
- hooks: Map<string, any[]>;
70
-
71
- constructor() {
72
- this.plugins = [];
73
- this.hooks = new Map();
74
-
75
- // Initialize hook arrays
76
- for (const hook of Object.values(PluginHooks)) {
77
- this.hooks.set(hook as string, []);
78
- }
79
- }
80
-
81
- /**
82
- * Registers a plugin
83
- */
84
- register(plugin) {
85
- if (!plugin.name) {
86
- throw new Error('Plugin must have a name');
87
- }
88
-
89
- // Check for duplicate
90
- if (this.plugins.find(p => p.name === plugin.name)) {
91
- console.warn(`Plugin "${plugin.name}" is already registered`);
92
- return;
93
- }
94
-
95
- this.plugins.push(plugin);
96
-
97
- // Register hooks
98
- for (const [hookName, handlers] of this.hooks) {
99
- if (typeof plugin[hookName] === 'function') {
100
- handlers.push({
101
- plugin: plugin.name,
102
- handler: plugin[hookName].bind(plugin)
103
- });
104
- }
105
- }
106
-
107
- console.log(` ✓ Plugin loaded: ${plugin.name}`);
108
- }
109
-
110
- /**
111
- * Unregisters a plugin
112
- */
113
- unregister(pluginName) {
114
- const index = this.plugins.findIndex(p => p.name === pluginName);
115
- if (index === -1) return;
116
-
117
- this.plugins.splice(index, 1);
118
-
119
- // Remove hooks
120
- for (const handlers of this.hooks.values()) {
121
- const hookIndex = handlers.findIndex(h => h.plugin === pluginName);
122
- if (hookIndex !== -1) {
123
- handlers.splice(hookIndex, 1);
124
- }
125
- }
126
- }
127
-
128
- /**
129
- * Runs a hook with all registered handlers
130
- */
131
- async runHook(hookName, ...args) {
132
- const handlers = this.hooks.get(hookName) || [];
133
- const results = [];
134
-
135
- for (const { plugin, handler } of handlers) {
136
- try {
137
- const result = await handler(...args);
138
- results.push({ plugin, result });
139
- } catch (error) {
140
- console.error(`Plugin "${plugin}" error in ${hookName}:`, error);
141
- results.push({ plugin, error });
142
- }
143
- }
144
-
145
- return results;
146
- }
147
-
148
- /**
149
- * Runs a hook that can modify a value (waterfall)
150
- */
151
- async runWaterfallHook(hookName, initialValue, ...args) {
152
- const handlers = this.hooks.get(hookName) || [];
153
- let value = initialValue;
154
-
155
- for (const { plugin, handler } of handlers) {
156
- try {
157
- const result = await handler(value, ...args);
158
- if (result !== undefined) {
159
- value = result;
160
- }
161
- } catch (error) {
162
- console.error(`Plugin "${plugin}" error in ${hookName}:`, error);
163
- }
164
- }
165
-
166
- return value;
167
- }
168
-
169
- /**
170
- * Checks if any plugin handles a hook
171
- */
172
- hasHook(hookName) {
173
- const handlers = this.hooks.get(hookName) || [];
174
- return handlers.length > 0;
175
- }
176
-
177
- /**
178
- * Gets all registered plugins
179
- */
180
- getPlugins() {
181
- return [...this.plugins];
182
- }
183
- }
184
-
185
- // Global plugin manager instance
186
- export const pluginManager = new PluginManager();
187
-
188
- /**
189
- * Loads plugins from project and config
190
- */
191
- export async function loadPlugins(projectRoot, config) {
192
- console.log('\n📦 Loading plugins...\n');
193
-
194
- // Load from flexireact.plugin.js
195
- const pluginPath = path.join(projectRoot, 'flexireact.plugin.js');
196
-
197
- if (fs.existsSync(pluginPath)) {
198
- try {
199
- const url = pathToFileURL(pluginPath).href;
200
- const module = await import(`${url}?t=${Date.now()}`);
201
- const plugin = module.default;
202
-
203
- if (plugin) {
204
- pluginManager.register(plugin);
205
- }
206
- } catch (error) {
207
- console.error('Failed to load flexireact.plugin.js:', error);
208
- }
209
- }
210
-
211
- // Load plugins from config
212
- if (config.plugins && Array.isArray(config.plugins)) {
213
- for (const pluginConfig of config.plugins) {
214
- try {
215
- if (typeof pluginConfig === 'string') {
216
- // Load from node_modules
217
- const module = await import(pluginConfig);
218
- pluginManager.register(module.default);
219
- } else if (typeof pluginConfig === 'object') {
220
- // Inline plugin
221
- pluginManager.register(pluginConfig);
222
- } else if (typeof pluginConfig === 'function') {
223
- // Plugin factory
224
- pluginManager.register(pluginConfig());
225
- }
226
- } catch (error) {
227
- console.error(`Failed to load plugin:`, error);
228
- }
229
- }
230
- }
231
-
232
- console.log(`\n Total plugins: ${pluginManager.getPlugins().length}\n`);
233
-
234
- return pluginManager;
235
- }
236
-
237
- /**
238
- * Creates a plugin
239
- */
240
- export function definePlugin(options) {
241
- return {
242
- name: options.name || 'unnamed-plugin',
243
- ...options
244
- };
245
- }
246
-
247
- /**
248
- * Built-in plugins
249
- */
250
- export const builtinPlugins = {
251
- /**
252
- * Analytics plugin
253
- */
254
- analytics(options: { trackingId?: string } = {}) {
255
- const { trackingId } = options;
256
-
257
- return definePlugin({
258
- name: 'flexi-analytics',
259
-
260
- onAfterRender(html) {
261
- if (!trackingId) return html;
262
-
263
- const script = `
264
- <script async src="https://www.googletagmanager.com/gtag/js?id=${trackingId}"></script>
265
- <script>
266
- window.dataLayer = window.dataLayer || [];
267
- function gtag(){dataLayer.push(arguments);}
268
- gtag('js', new Date());
269
- gtag('config', '${trackingId}');
270
- </script>
271
- `;
272
-
273
- return html.replace('</head>', `${script}</head>`);
274
- }
275
- });
276
- },
277
-
278
- /**
279
- * PWA plugin
280
- */
281
- pwa(options: { manifest?: string; serviceWorker?: string } = {}) {
282
- const { manifest = '/manifest.json', serviceWorker = '/sw.js' } = options;
283
-
284
- return definePlugin({
285
- name: 'flexi-pwa',
286
-
287
- onAfterRender(html) {
288
- const tags = `
289
- <link rel="manifest" href="${manifest}">
290
- <script>
291
- if ('serviceWorker' in navigator) {
292
- navigator.serviceWorker.register('${serviceWorker}');
293
- }
294
- </script>
295
- `;
296
-
297
- return html.replace('</head>', `${tags}</head>`);
298
- }
299
- });
300
- },
301
-
302
- /**
303
- * SEO plugin
304
- */
305
- seo(options: { defaultTitle?: string; titleTemplate?: string; defaultDescription?: string } = {}) {
306
- const { defaultTitle, titleTemplate = '%s', defaultDescription } = options;
307
-
308
- return definePlugin({
309
- name: 'flexi-seo',
310
-
311
- onBeforeRender(page, props) {
312
- const title = props.title || page.title || defaultTitle;
313
- const description = props.description || page.description || defaultDescription;
314
-
315
- return {
316
- ...props,
317
- _seo: {
318
- title: titleTemplate.replace('%s', title),
319
- description
320
- }
321
- };
322
- }
323
- });
324
- },
325
-
326
- /**
327
- * Compression plugin (for production)
328
- */
329
- compression() {
330
- return definePlugin({
331
- name: 'flexi-compression',
332
-
333
- onResponse(req, res, html) {
334
- // Note: Actual compression would require zlib
335
- // This is a placeholder for the concept
336
- res.setHeader('Content-Encoding', 'identity');
337
- return html;
338
- }
339
- });
340
- },
341
-
342
- /**
343
- * Security headers plugin
344
- */
345
- securityHeaders(options: { headers?: Record<string, string> } = {}) {
346
- const headers: Record<string, string> = {
347
- 'X-Content-Type-Options': 'nosniff',
348
- 'X-Frame-Options': 'DENY',
349
- 'X-XSS-Protection': '1; mode=block',
350
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
351
- ...options.headers
352
- };
353
-
354
- return definePlugin({
355
- name: 'flexi-security',
356
-
357
- onRequest(req, res) {
358
- for (const [key, value] of Object.entries(headers)) {
359
- res.setHeader(key, value);
360
- }
361
- }
362
- });
363
- }
364
- };
365
-
366
- export default {
367
- PluginManager,
368
- PluginHooks,
369
- pluginManager,
370
- loadPlugins,
371
- definePlugin,
372
- builtinPlugins
373
- };