@gxp-dev/tools 2.0.6 → 2.0.8

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 (100) hide show
  1. package/bin/lib/commands/build.js +18 -12
  2. package/browser-extensions/README.md +1 -0
  3. package/browser-extensions/chrome/background.js +857 -0
  4. package/browser-extensions/chrome/content.js +51 -0
  5. package/browser-extensions/chrome/devtools.html +9 -0
  6. package/browser-extensions/chrome/devtools.js +23 -0
  7. package/browser-extensions/chrome/icons/gx_off_128.png +0 -0
  8. package/browser-extensions/chrome/icons/gx_off_16.png +0 -0
  9. package/browser-extensions/chrome/icons/gx_off_32.png +0 -0
  10. package/browser-extensions/chrome/icons/gx_off_64.png +0 -0
  11. package/browser-extensions/chrome/icons/gx_on_128.png +0 -0
  12. package/browser-extensions/chrome/icons/gx_on_16.png +0 -0
  13. package/browser-extensions/chrome/icons/gx_on_32.png +0 -0
  14. package/browser-extensions/chrome/icons/gx_on_64.png +0 -0
  15. package/browser-extensions/chrome/inspector.js +1087 -0
  16. package/browser-extensions/chrome/manifest.json +70 -0
  17. package/browser-extensions/chrome/panel.html +638 -0
  18. package/browser-extensions/chrome/panel.js +862 -0
  19. package/browser-extensions/chrome/popup.html +399 -0
  20. package/browser-extensions/chrome/popup.js +515 -0
  21. package/browser-extensions/chrome/rules.json +1 -0
  22. package/browser-extensions/chrome/test-chrome.html +145 -0
  23. package/browser-extensions/chrome/test-mixed-content.html +190 -0
  24. package/browser-extensions/chrome/test-uri-pattern.html +199 -0
  25. package/browser-extensions/firefox/README.md +134 -0
  26. package/browser-extensions/firefox/background.js +804 -0
  27. package/browser-extensions/firefox/content.js +120 -0
  28. package/browser-extensions/firefox/debug-errors.html +229 -0
  29. package/browser-extensions/firefox/debug-https.html +113 -0
  30. package/browser-extensions/firefox/devtools.html +9 -0
  31. package/browser-extensions/firefox/devtools.js +24 -0
  32. package/browser-extensions/firefox/icons/gx_off_128.png +0 -0
  33. package/browser-extensions/firefox/icons/gx_off_16.png +0 -0
  34. package/browser-extensions/firefox/icons/gx_off_32.png +0 -0
  35. package/browser-extensions/firefox/icons/gx_off_64.png +0 -0
  36. package/browser-extensions/firefox/icons/gx_on_128.png +0 -0
  37. package/browser-extensions/firefox/icons/gx_on_16.png +0 -0
  38. package/browser-extensions/firefox/icons/gx_on_32.png +0 -0
  39. package/browser-extensions/firefox/icons/gx_on_64.png +0 -0
  40. package/browser-extensions/firefox/inspector.js +1087 -0
  41. package/browser-extensions/firefox/manifest.json +67 -0
  42. package/browser-extensions/firefox/panel.html +638 -0
  43. package/browser-extensions/firefox/panel.js +862 -0
  44. package/browser-extensions/firefox/popup.html +525 -0
  45. package/browser-extensions/firefox/popup.js +536 -0
  46. package/browser-extensions/firefox/test-gramercy.html +126 -0
  47. package/browser-extensions/firefox/test-imports.html +58 -0
  48. package/browser-extensions/firefox/test-masking.html +147 -0
  49. package/browser-extensions/firefox/test-uri-pattern.html +199 -0
  50. package/package.json +7 -2
  51. package/runtime/PortalContainer.vue +326 -0
  52. package/runtime/dev-tools/DevToolsModal.vue +217 -0
  53. package/runtime/dev-tools/LayoutSwitcher.vue +221 -0
  54. package/runtime/dev-tools/MockDataEditor.vue +621 -0
  55. package/runtime/dev-tools/SocketSimulator.vue +562 -0
  56. package/runtime/dev-tools/StoreInspector.vue +644 -0
  57. package/runtime/dev-tools/index.js +6 -0
  58. package/runtime/gxpStringsPlugin.js +428 -0
  59. package/runtime/index.html +22 -0
  60. package/runtime/main.js +32 -0
  61. package/runtime/mock-api/auth-middleware.js +97 -0
  62. package/runtime/mock-api/image-generator.js +221 -0
  63. package/runtime/mock-api/index.js +197 -0
  64. package/runtime/mock-api/response-generator.js +394 -0
  65. package/runtime/mock-api/route-generator.js +323 -0
  66. package/runtime/mock-api/socket-triggers.js +371 -0
  67. package/runtime/mock-api/spec-loader.js +300 -0
  68. package/runtime/server.js +180 -0
  69. package/runtime/stores/gxpPortalConfigStore.js +554 -0
  70. package/runtime/stores/index.js +6 -0
  71. package/runtime/vite-inspector-plugin.js +749 -0
  72. package/runtime/vite-source-tracker-plugin.js +232 -0
  73. package/runtime/vite.config.js +402 -0
  74. package/scripts/launch-chrome.js +90 -0
  75. package/scripts/pack-chrome.js +91 -0
  76. package/socket-events/AiSessionMessageCreated.json +18 -0
  77. package/socket-events/SocialStreamPostCreated.json +24 -0
  78. package/socket-events/SocialStreamPostVariantCompleted.json +23 -0
  79. package/template/README.md +332 -0
  80. package/template/app-manifest.json +32 -0
  81. package/template/dev-assets/images/avatar-placeholder.png +0 -0
  82. package/template/dev-assets/images/background-placeholder.jpg +0 -0
  83. package/template/dev-assets/images/banner-placeholder.jpg +0 -0
  84. package/template/dev-assets/images/icon-placeholder.png +0 -0
  85. package/template/dev-assets/images/logo-placeholder.png +0 -0
  86. package/template/dev-assets/images/product-placeholder.jpg +0 -0
  87. package/template/dev-assets/images/thumbnail-placeholder.jpg +0 -0
  88. package/template/env.example +51 -0
  89. package/template/gitignore +53 -0
  90. package/template/index.html +22 -0
  91. package/template/main.js +28 -0
  92. package/template/src/DemoPage.vue +459 -0
  93. package/template/src/Plugin.vue +38 -0
  94. package/template/src/stores/index.js +9 -0
  95. package/template/src/stores/test-data.json +173 -0
  96. package/template/theme-layouts/AdditionalStyling.css +0 -0
  97. package/template/theme-layouts/PrivateLayout.vue +39 -0
  98. package/template/theme-layouts/PublicLayout.vue +39 -0
  99. package/template/theme-layouts/SystemLayout.vue +39 -0
  100. package/template/vite.config.js +333 -0
@@ -0,0 +1,173 @@
1
+ {
2
+ "pluginVars": {
3
+ "primary_color": "#FFD600",
4
+ "projectId": 39,
5
+ "apiPageAuthId": "46|j7vCLmx2KG70Ig8R5mtUcNMFcHExvFPZEOv31kKGe1033f2b",
6
+ "apiBaseUrl": "https://api.efcloud.app",
7
+ "idle_timeout": "30",
8
+ "background_color": "#ffffff",
9
+ "text_color": "#333333",
10
+ "start_background_color": "#000596",
11
+ "start_text_color": "#FFFFFF",
12
+ "final_background_color": "#4CAF50",
13
+ "final_text_color": "#ffffff",
14
+ "loading_spinner_color": "#dedede",
15
+ "loading_spinner_accent_color": "#000596",
16
+ "error_modal_background_color": "#FFFFFF",
17
+ "error_modal_text_color": "#000596",
18
+ "line_1": "Welcome to Your App!",
19
+ "line_2": "Touch to begin your experience",
20
+ "line_3": "Get started by touching the button below"
21
+ },
22
+ "stringsList": {
23
+ "line_1": "Welcome to Your App!",
24
+ "line_2": "Touch to begin your experience",
25
+ "line_3": "Get started by touching the button below",
26
+ "start_line_one": "Welcome to Your App!",
27
+ "start_line_two": "Touch to begin your experience",
28
+ "start_touch_start": "Get started by touching the button below",
29
+ "final_line_one": "Thank You!",
30
+ "final_line_two": "Your experience has been completed successfully",
31
+ "final_line_three": "Touch anywhere to start over",
32
+ "welcome_text": "Hello World",
33
+ "loading_text": "Loading...",
34
+ "error_title": "Oops!",
35
+ "error_message": "Something went wrong. Please try again.",
36
+ "continue_button": "Continue",
37
+ "back_button": "Back",
38
+ "retry_button": "Try Again"
39
+ },
40
+ "assetList": {
41
+ "main_logo": "/dev-assets/images/logo-placeholder.png",
42
+ "background_image": "/dev-assets/images/background-placeholder.jpg",
43
+ "product_image": "/dev-assets/images/product-placeholder.jpg",
44
+ "avatar_placeholder": "/dev-assets/images/avatar-placeholder.png",
45
+ "icon_placeholder": "/dev-assets/images/icon-placeholder.png",
46
+ "thumbnail": "/dev-assets/images/thumbnail-placeholder.jpg",
47
+ "banner_image": "/dev-assets/images/banner-placeholder.jpg"
48
+ },
49
+ "dependencyList": [
50
+ {
51
+ "model": "AiInterface",
52
+ "events": {
53
+ "created": "AiSessionMessageCreated",
54
+ "updated": "AiSessionMessageUpdated"
55
+ },
56
+ "identifier": "ai_interface_background_remover",
57
+ "permissions": [
58
+ "manage_ai_interfaces",
59
+ "view_ai_interfaces",
60
+ "view_ai_sessions",
61
+ "view_ai_session_messages"
62
+ ]
63
+ },
64
+ {
65
+ "model": "AiInterface",
66
+ "events": {
67
+ "created": "AiSessionMessageCreated",
68
+ "updated": "AiSessionMessageUpdated"
69
+ },
70
+ "identifier": "ai_interface_background_generator",
71
+ "permissions": [
72
+ "manage_ai_interfaces",
73
+ "view_ai_interfaces",
74
+ "view_ai_sessions",
75
+ "view_ai_session_messages"
76
+ ]
77
+ },
78
+ {
79
+ "model": "AiInterface",
80
+ "events": {
81
+ "created": "AiSessionMessageCreated",
82
+ "updated": "AiSessionMessageUpdated"
83
+ },
84
+ "identifier": "ai_interface",
85
+ "permissions": [
86
+ "manage_ai_interfaces",
87
+ "view_ai_interfaces",
88
+ "view_ai_sessions",
89
+ "view_ai_session_messages"
90
+ ]
91
+ },
92
+ {
93
+ "model": "SocialStream",
94
+ "events": {
95
+ "created": "SocialStreamPostCreated",
96
+ "deleted": "SocialStreamPostDeleted",
97
+ "updated": "SocialStreamPostUpdated",
98
+ "variantCompleted": "SocialStreamPostVariantCompleted"
99
+ },
100
+ "identifier": "social_stream",
101
+ "permissions": [
102
+ "view_social_streams",
103
+ "view_social_stream_posts",
104
+ "create_social_stream_posts",
105
+ "manage_social_stream_posts"
106
+ ]
107
+ },
108
+ {
109
+ "model": "SocialStreamPost",
110
+ "identifier": "social_stream_posts",
111
+ "permissions": [
112
+ "view_social_stream_posts:viewAny"
113
+ ]
114
+ },
115
+ {
116
+ "key": "slug",
117
+ "model": "Group",
118
+ "events": [],
119
+ "identifier": "groups",
120
+ "permissions": [
121
+ "view_groups",
122
+ "view_attendees"
123
+ ]
124
+ },
125
+ {
126
+ "model": "Attendee",
127
+ "identifier": "attendees",
128
+ "permissions": [
129
+ "create_attendees:viewAny",
130
+ "view_attendees:viewAny"
131
+ ]
132
+ }
133
+ ],
134
+ "permissionFlags": [
135
+ "can_access_camera",
136
+ "can_save_data",
137
+ "can_share_content"
138
+ ],
139
+ "auth": {
140
+ "token": "test-token-12345",
141
+ "user_id": "test-user-67890",
142
+ "expires_at": "2024-12-31T23:59:59Z"
143
+ },
144
+ "userSession": {
145
+ "session_id": "session-abc123",
146
+ "started_at": "2024-01-01T00:00:00Z",
147
+ "ip_address": "127.0.0.1",
148
+ "user_agent": "Test Browser"
149
+ },
150
+ "pluginData": {
151
+ "plugin_id": "test-plugin-123",
152
+ "version": "1.0.0",
153
+ "environment": "development"
154
+ },
155
+ "portalAssets": {
156
+ "favicon": "/portal/favicon.ico",
157
+ "logo": "/portal/logo.png",
158
+ "theme_css": "/portal/theme.css"
159
+ },
160
+ "portal": {
161
+ "name": "Test Portal",
162
+ "theme_colors": {
163
+ "primary": "#FFD600",
164
+ "secondary": "#000596",
165
+ "accent": "#4CAF50"
166
+ },
167
+ "custom_settings": {
168
+ "allow_guest_access": true,
169
+ "session_timeout": 1800,
170
+ "max_file_size": "10MB"
171
+ }
172
+ }
173
+ }
File without changes
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <slot />
3
+ </template>
4
+
5
+ <style scoped>
6
+
7
+ </style>
8
+
9
+ <script setup>
10
+ import { ref } from "vue";
11
+ defineOptions({
12
+ inheritAttrs: false,
13
+ });
14
+
15
+ const props = defineProps({
16
+ usrLang: {
17
+ type: String,
18
+ required: true,
19
+ },
20
+ portalSettings: {
21
+ type: Object,
22
+ required: true,
23
+ },
24
+ portalLanguage: {
25
+ type: Object,
26
+ required: true,
27
+ },
28
+ portalNavigation: {
29
+ type: Array,
30
+ required: true,
31
+ },
32
+ portalAssets: {
33
+ type: Object,
34
+ required: true,
35
+ },
36
+ });
37
+
38
+ </script>
39
+
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <slot />
3
+ </template>
4
+
5
+ <style scoped>
6
+
7
+ </style>
8
+
9
+ <script setup>
10
+ import { ref } from "vue";
11
+ defineOptions({
12
+ inheritAttrs: false,
13
+ });
14
+
15
+ const props = defineProps({
16
+ usrLang: {
17
+ type: String,
18
+ required: true,
19
+ },
20
+ portalSettings: {
21
+ type: Object,
22
+ required: true,
23
+ },
24
+ portalLanguage: {
25
+ type: Object,
26
+ required: true,
27
+ },
28
+ portalNavigation: {
29
+ type: Array,
30
+ required: true,
31
+ },
32
+ portalAssets: {
33
+ type: Object,
34
+ required: true,
35
+ },
36
+ });
37
+
38
+ </script>
39
+
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <slot />
3
+ </template>
4
+
5
+ <style scoped>
6
+
7
+ </style>
8
+
9
+ <script setup>
10
+ import { ref } from "vue";
11
+ defineOptions({
12
+ inheritAttrs: false,
13
+ });
14
+
15
+ const props = defineProps({
16
+ usrLang: {
17
+ type: String,
18
+ required: true,
19
+ },
20
+ portalSettings: {
21
+ type: Object,
22
+ required: true,
23
+ },
24
+ portalLanguage: {
25
+ type: Object,
26
+ required: true,
27
+ },
28
+ portalNavigation: {
29
+ type: Array,
30
+ required: true,
31
+ },
32
+ portalAssets: {
33
+ type: Object,
34
+ required: true,
35
+ },
36
+ });
37
+
38
+ </script>
39
+
@@ -0,0 +1,333 @@
1
+ import { defineConfig, loadEnv } from "vite";
2
+ import vue from "@vitejs/plugin-vue";
3
+ import path from "path";
4
+ import fs from "fs";
5
+ import externalGlobals from "rollup-plugin-external-globals";
6
+
7
+ // Environment URL configuration for API proxy
8
+ const ENVIRONMENT_URLS = {
9
+ production: "https://api.gramercy.cloud",
10
+ staging: "https://api.efz-staging.env.eventfinity.app",
11
+ testing: "https://api.zenith-develop-testing.env.eventfinity.app",
12
+ develop: "https://api.zenith-develop.env.eventfinity.app",
13
+ local: "https://dashboard.eventfinity.test",
14
+ };
15
+
16
+ /**
17
+ * Get the API proxy target URL based on environment
18
+ */
19
+ function getApiProxyTarget(env) {
20
+ const apiEnv = env.API_ENV || "mock";
21
+
22
+ // Custom URL takes precedence
23
+ if (env.API_BASE_URL) {
24
+ return env.API_BASE_URL;
25
+ }
26
+
27
+ // Mock uses local mock-api server (no proxy needed, handled separately)
28
+ if (apiEnv === "mock") {
29
+ return null;
30
+ }
31
+
32
+ // Look up environment URL
33
+ return ENVIRONMENT_URLS[apiEnv] || ENVIRONMENT_URLS.production;
34
+ }
35
+
36
+ /**
37
+ * Get the library name from package.json
38
+ */
39
+ function getLibName() {
40
+ try {
41
+ const packageJsonPath = path.resolve(process.cwd(), "package.json");
42
+ if (fs.existsSync(packageJsonPath)) {
43
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
44
+ // Convert package name to a valid JS identifier
45
+ // e.g., "@company/my-plugin" -> "MyPlugin"
46
+ const name = packageJson.name || "Plugin";
47
+ return name
48
+ .replace(/[@\/\-]/g, " ")
49
+ .replace(/\b\w/g, (l) => l.toUpperCase())
50
+ .replace(/\s/g, "");
51
+ }
52
+ } catch (error) {
53
+ console.warn("Could not read package.json, using default lib name");
54
+ }
55
+ return "Plugin";
56
+ }
57
+
58
+ /**
59
+ * Setup HTTPS configuration if certificates are available
60
+ */
61
+ function getHttpsConfig(env) {
62
+ const useHttps = env.USE_HTTPS === "true";
63
+ const certPath = env.CERT_PATH;
64
+ const keyPath = env.KEY_PATH;
65
+
66
+ if (!useHttps || !certPath || !keyPath) {
67
+ return false;
68
+ }
69
+
70
+ // Resolve paths relative to project root
71
+ const resolvedCertPath = path.resolve(process.cwd(), certPath);
72
+ const resolvedKeyPath = path.resolve(process.cwd(), keyPath);
73
+
74
+ // Check if certificate files exist
75
+ if (!fs.existsSync(resolvedCertPath) || !fs.existsSync(resolvedKeyPath)) {
76
+ console.warn("⚠ SSL certificate files not found, falling back to HTTP");
77
+ return false;
78
+ }
79
+
80
+ try {
81
+ return {
82
+ key: fs.readFileSync(resolvedKeyPath),
83
+ cert: fs.readFileSync(resolvedCertPath),
84
+ };
85
+ } catch (error) {
86
+ console.warn("⚠ Failed to read SSL certificates, falling back to HTTP");
87
+ return false;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Find the gx-devtools package directory (works for both local and global installs)
93
+ */
94
+ function findToolkitPath() {
95
+ const packageName = "@gramercytech/gx-devtools";
96
+
97
+ // Try local node_modules first
98
+ const localPath = path.resolve(process.cwd(), "node_modules", packageName);
99
+ if (fs.existsSync(localPath)) {
100
+ return localPath;
101
+ }
102
+
103
+ // Try to find via require.resolve
104
+ try {
105
+ const pkgPath = require.resolve(`${packageName}/package.json`);
106
+ return path.dirname(pkgPath);
107
+ } catch (e) {
108
+ // Fallback: assume we're in the toolkit itself during development
109
+ return process.cwd();
110
+ }
111
+ }
112
+
113
+ // Dynamically import the inspector plugin from the toolkit
114
+ let gxpInspectorPlugin;
115
+ let gxpSourceTrackerPlugin;
116
+ try {
117
+ const toolkitPathForPlugin = findToolkitPath();
118
+ const pluginPath = path.join(
119
+ toolkitPathForPlugin,
120
+ "runtime/vite-inspector-plugin.js"
121
+ );
122
+ if (fs.existsSync(pluginPath)) {
123
+ const pluginModule = await import(pluginPath);
124
+ gxpInspectorPlugin = pluginModule.gxpInspectorPlugin;
125
+ }
126
+ // Load source tracker plugin for injecting data-gxp-source attributes
127
+ const trackerPath = path.join(
128
+ toolkitPathForPlugin,
129
+ "runtime/vite-source-tracker-plugin.js"
130
+ );
131
+ if (fs.existsSync(trackerPath)) {
132
+ const trackerModule = await import(trackerPath);
133
+ gxpSourceTrackerPlugin = trackerModule.gxpSourceTrackerPlugin;
134
+ }
135
+ } catch (e) {
136
+ console.warn("Could not load GxP Inspector plugin:", e.message);
137
+ }
138
+
139
+ export default defineConfig(({ mode }) => {
140
+ // Load environment variables
141
+ const env = loadEnv(mode, process.cwd(), "");
142
+
143
+ // Get lib name from package.json
144
+ const libName = getLibName();
145
+
146
+ // Find the toolkit path for runtime imports
147
+ const toolkitPath = findToolkitPath();
148
+
149
+ // Determine if HTTPS is enabled
150
+ const useHttps = getHttpsConfig(env) !== false;
151
+
152
+ // Get API proxy target for non-mock environments
153
+ const apiProxyTarget = getApiProxyTarget(env);
154
+ if (apiProxyTarget) {
155
+ console.log(`🔀 API Proxy: /api-proxy -> ${apiProxyTarget}`);
156
+ }
157
+
158
+ return {
159
+ // Expose environment variables to the browser
160
+ define: {
161
+ "import.meta.env.VITE_API_ENV": JSON.stringify(env.API_ENV || "mock"),
162
+ "import.meta.env.VITE_API_BASE_URL": JSON.stringify(
163
+ env.API_BASE_URL || ""
164
+ ),
165
+ "import.meta.env.VITE_API_KEY": JSON.stringify(env.API_KEY || ""),
166
+ "import.meta.env.VITE_API_PROJECT_ID": JSON.stringify(
167
+ env.API_PROJECT_ID || ""
168
+ ),
169
+ "import.meta.env.VITE_USE_HTTPS": JSON.stringify(
170
+ useHttps ? "true" : "false"
171
+ ),
172
+ "import.meta.env.VITE_NODE_PORT": JSON.stringify(env.NODE_PORT || "3060"),
173
+ "import.meta.env.VITE_SOCKET_IO_PORT": JSON.stringify(
174
+ env.SOCKET_IO_PORT || "3069"
175
+ ),
176
+ },
177
+ plugins: [
178
+ // Source tracker must come before vue() to transform templates before compilation
179
+ ...(gxpSourceTrackerPlugin ? [gxpSourceTrackerPlugin()] : []),
180
+ vue(),
181
+ // GxP Inspector plugin for browser extension integration (if available)
182
+ ...(gxpInspectorPlugin ? [gxpInspectorPlugin()] : []),
183
+ externalGlobals(
184
+ {
185
+ vue: "Vue",
186
+ pinia: "Pinia",
187
+ "@/stores/gxpPortalConfigStore":
188
+ "(window.useGxpStore || (() => { console.warn('useGxpStore not found on window, using fallback'); return {}; }))",
189
+ },
190
+ {
191
+ include: ["src/**"],
192
+ }
193
+ ),
194
+ // Custom request logging and CORS plugin
195
+ {
196
+ name: "request-logger-cors",
197
+ configureServer(server) {
198
+ server.middlewares.use((req, res, next) => {
199
+ const start = Date.now();
200
+ const originalEnd = res.end;
201
+
202
+ // Add CORS headers to all responses
203
+ res.setHeader("Access-Control-Allow-Origin", "*");
204
+ res.setHeader(
205
+ "Access-Control-Allow-Methods",
206
+ "GET, POST, PUT, DELETE, OPTIONS"
207
+ );
208
+ res.setHeader("Access-Control-Allow-Headers", "*");
209
+ res.setHeader("Access-Control-Allow-Credentials", "false");
210
+
211
+ // Handle preflight requests
212
+ if (req.method === "OPTIONS") {
213
+ res.statusCode = 200;
214
+ res.end();
215
+ return;
216
+ }
217
+
218
+ res.end = function (...args) {
219
+ const duration = Date.now() - start;
220
+ const status = res.statusCode;
221
+ const method = req.method;
222
+ const url = req.url;
223
+ const referer = req.headers.referer || "direct";
224
+ const origin = req.headers.origin || "unknown";
225
+
226
+ console.log(
227
+ `[${new Date().toISOString()}] ${method} ${url} ${status} (${duration}ms) - Origin: ${origin} - Referer: ${referer}`
228
+ );
229
+ originalEnd.apply(this, args);
230
+ };
231
+
232
+ next();
233
+ });
234
+ },
235
+ },
236
+ ],
237
+ logLevel: env.NODE_LOG_LEVEL || "error",
238
+ clearScreen: false,
239
+ server: {
240
+ port: parseInt(env.NODE_PORT) || 3060,
241
+ strictPort: true,
242
+ https: getHttpsConfig(env),
243
+ cors: {
244
+ origin: "*",
245
+ methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
246
+ allowedHeaders: ["*"],
247
+ credentials: false,
248
+ },
249
+ hmr: {
250
+ clientPort:
251
+ parseInt(env.CLIENT_PORT) || parseInt(env.NODE_PORT) || 3060,
252
+ },
253
+ host: true, // Allow access from network
254
+ // API proxy for non-mock environments
255
+ proxy: apiProxyTarget
256
+ ? {
257
+ "/api-proxy": {
258
+ target: apiProxyTarget,
259
+ changeOrigin: true,
260
+ rewrite: (path) => path.replace(/^\/api-proxy/, ""),
261
+ secure: false,
262
+ configure: (proxy, options) => {
263
+ proxy.on("proxyReq", (proxyReq, req) => {
264
+ // Forward the API key as Authorization header if set
265
+ const apiKey = env.API_KEY;
266
+ if (apiKey) {
267
+ proxyReq.setHeader("Authorization", `Bearer ${apiKey}`);
268
+ }
269
+ console.log(
270
+ `[API Proxy] ${req.method} ${
271
+ req.url
272
+ } -> ${apiProxyTarget}${req.url.replace(
273
+ /^\/api-proxy/,
274
+ ""
275
+ )}`
276
+ );
277
+ });
278
+ proxy.on("proxyRes", (proxyRes, req) => {
279
+ console.log(
280
+ `[API Proxy] ${req.method} ${req.url} <- ${proxyRes.statusCode}`
281
+ );
282
+ });
283
+ proxy.on("error", (err, req) => {
284
+ console.error(`[API Proxy] Error: ${err.message}`);
285
+ });
286
+ },
287
+ },
288
+ }
289
+ : {},
290
+ },
291
+ build: {
292
+ lib: {
293
+ entry: [env.COMPONENT_PATH || "./src/Plugin.vue"],
294
+ name: libName,
295
+ fileName: (format) => `plugin.${format}.js`,
296
+ formats: ["es"],
297
+ },
298
+ rollupOptions: {
299
+ // Make sure Vue and Pinia are treated as external dependencies
300
+ external: ["vue", "pinia"],
301
+ output: {
302
+ globals: {
303
+ vue: "Vue",
304
+ pinia: "Pinia",
305
+ },
306
+ },
307
+ },
308
+ },
309
+ resolve: {
310
+ alias: {
311
+ // Client project's source directory
312
+ "@": path.resolve(process.cwd(), "src"),
313
+ // Theme layouts in client project
314
+ "@layouts": path.resolve(process.cwd(), "theme-layouts"),
315
+ // GxP Toolkit runtime (PortalContainer, etc.) - from node_modules
316
+ "@gx-runtime": path.resolve(toolkitPath, "runtime"),
317
+ // Ensure single Vue and Pinia instances
318
+ vue: path.resolve(process.cwd(), "node_modules/vue"),
319
+ pinia: path.resolve(process.cwd(), "node_modules/pinia"),
320
+ },
321
+ // Dedupe Vue and Pinia to ensure only one instance is used
322
+ dedupe: ["vue", "pinia"],
323
+ },
324
+ // Force Vite to pre-bundle these dependencies to ensure single instances
325
+ optimizeDeps: {
326
+ include: ["vue", "pinia"],
327
+ },
328
+ // SSR configuration to handle externals properly
329
+ ssr: {
330
+ external: ["vue", "pinia"],
331
+ },
332
+ };
333
+ });