@gxp-dev/tools 2.0.62 → 2.0.64
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 +32 -31
- package/bin/gx-devtools.js +74 -54
- package/bin/lib/cli.js +23 -21
- package/bin/lib/commands/add-dependency.js +366 -325
- package/bin/lib/commands/assets.js +137 -139
- package/bin/lib/commands/build.js +169 -174
- package/bin/lib/commands/datastore.js +181 -183
- package/bin/lib/commands/dev.js +127 -131
- package/bin/lib/commands/extensions.js +147 -149
- package/bin/lib/commands/extract-config.js +73 -67
- package/bin/lib/commands/index.js +12 -12
- package/bin/lib/commands/init.js +342 -240
- package/bin/lib/commands/publish.js +69 -75
- package/bin/lib/commands/socket.js +69 -69
- package/bin/lib/commands/ssl.js +14 -14
- package/bin/lib/constants.js +10 -24
- package/bin/lib/tui/App.tsx +761 -705
- package/bin/lib/tui/components/AIPanel.tsx +191 -171
- package/bin/lib/tui/components/CommandInput.tsx +394 -343
- package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
- package/bin/lib/tui/components/Header.tsx +23 -21
- package/bin/lib/tui/components/LogPanel.tsx +244 -220
- package/bin/lib/tui/components/TabBar.tsx +50 -48
- package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
- package/bin/lib/tui/index.tsx +37 -39
- package/bin/lib/tui/services/AIService.ts +518 -462
- package/bin/lib/tui/services/ExtensionService.ts +140 -129
- package/bin/lib/tui/services/GeminiService.ts +367 -337
- package/bin/lib/tui/services/ServiceManager.ts +344 -322
- package/bin/lib/tui/services/SocketService.ts +168 -168
- package/bin/lib/tui/services/ViteService.ts +88 -88
- package/bin/lib/tui/services/index.ts +47 -22
- package/bin/lib/utils/ai-scaffold.js +291 -280
- package/bin/lib/utils/extract-config.js +157 -140
- package/bin/lib/utils/files.js +82 -86
- package/bin/lib/utils/index.js +7 -7
- package/bin/lib/utils/paths.js +34 -34
- package/bin/lib/utils/prompts.js +194 -169
- package/bin/lib/utils/ssl.js +79 -81
- package/browser-extensions/README.md +0 -1
- package/browser-extensions/chrome/background.js +244 -237
- package/browser-extensions/chrome/content.js +32 -29
- package/browser-extensions/chrome/devtools.html +7 -7
- package/browser-extensions/chrome/devtools.js +19 -19
- package/browser-extensions/chrome/inspector.js +802 -767
- package/browser-extensions/chrome/manifest.json +71 -63
- package/browser-extensions/chrome/panel.html +674 -636
- package/browser-extensions/chrome/panel.js +722 -712
- package/browser-extensions/chrome/popup.html +586 -543
- package/browser-extensions/chrome/popup.js +282 -244
- package/browser-extensions/chrome/rules.json +1 -1
- package/browser-extensions/chrome/test-chrome.html +216 -136
- package/browser-extensions/chrome/test-mixed-content.html +284 -189
- package/browser-extensions/chrome/test-uri-pattern.html +221 -198
- package/browser-extensions/firefox/README.md +9 -6
- package/browser-extensions/firefox/background.js +221 -218
- package/browser-extensions/firefox/content.js +55 -52
- package/browser-extensions/firefox/debug-errors.html +386 -228
- package/browser-extensions/firefox/debug-https.html +153 -105
- package/browser-extensions/firefox/devtools.html +7 -7
- package/browser-extensions/firefox/devtools.js +23 -20
- package/browser-extensions/firefox/inspector.js +802 -767
- package/browser-extensions/firefox/manifest.json +68 -68
- package/browser-extensions/firefox/panel.html +674 -636
- package/browser-extensions/firefox/panel.js +722 -712
- package/browser-extensions/firefox/popup.html +572 -535
- package/browser-extensions/firefox/popup.js +281 -236
- package/browser-extensions/firefox/test-gramercy.html +170 -125
- package/browser-extensions/firefox/test-imports.html +59 -55
- package/browser-extensions/firefox/test-masking.html +231 -140
- package/browser-extensions/firefox/test-uri-pattern.html +221 -198
- package/dist/tui/App.d.ts +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +154 -150
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/components/AIPanel.d.ts.map +1 -1
- package/dist/tui/components/AIPanel.js +42 -35
- package/dist/tui/components/AIPanel.js.map +1 -1
- package/dist/tui/components/CommandInput.d.ts +1 -1
- package/dist/tui/components/CommandInput.d.ts.map +1 -1
- package/dist/tui/components/CommandInput.js +92 -62
- package/dist/tui/components/CommandInput.js.map +1 -1
- package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
- package/dist/tui/components/GeminiPanel.js +37 -30
- package/dist/tui/components/GeminiPanel.js.map +1 -1
- package/dist/tui/components/Header.d.ts.map +1 -1
- package/dist/tui/components/Header.js +1 -1
- package/dist/tui/components/Header.js.map +1 -1
- package/dist/tui/components/LogPanel.d.ts +1 -1
- package/dist/tui/components/LogPanel.d.ts.map +1 -1
- package/dist/tui/components/LogPanel.js +26 -24
- package/dist/tui/components/LogPanel.js.map +1 -1
- package/dist/tui/components/TabBar.d.ts +2 -2
- package/dist/tui/components/TabBar.d.ts.map +1 -1
- package/dist/tui/components/TabBar.js +11 -11
- package/dist/tui/components/TabBar.js.map +1 -1
- package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
- package/dist/tui/components/WelcomeScreen.js +6 -6
- package/dist/tui/components/WelcomeScreen.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +8 -8
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/services/AIService.d.ts +2 -2
- package/dist/tui/services/AIService.d.ts.map +1 -1
- package/dist/tui/services/AIService.js +165 -125
- package/dist/tui/services/AIService.js.map +1 -1
- package/dist/tui/services/ExtensionService.d.ts +1 -1
- package/dist/tui/services/ExtensionService.d.ts.map +1 -1
- package/dist/tui/services/ExtensionService.js +33 -26
- package/dist/tui/services/ExtensionService.js.map +1 -1
- package/dist/tui/services/GeminiService.d.ts +1 -1
- package/dist/tui/services/GeminiService.d.ts.map +1 -1
- package/dist/tui/services/GeminiService.js +87 -76
- package/dist/tui/services/GeminiService.js.map +1 -1
- package/dist/tui/services/ServiceManager.d.ts +3 -3
- package/dist/tui/services/ServiceManager.d.ts.map +1 -1
- package/dist/tui/services/ServiceManager.js +72 -58
- package/dist/tui/services/ServiceManager.js.map +1 -1
- package/dist/tui/services/SocketService.d.ts.map +1 -1
- package/dist/tui/services/SocketService.js +32 -32
- package/dist/tui/services/SocketService.js.map +1 -1
- package/dist/tui/services/ViteService.d.ts.map +1 -1
- package/dist/tui/services/ViteService.js +26 -28
- package/dist/tui/services/ViteService.js.map +1 -1
- package/dist/tui/services/index.d.ts +6 -6
- package/dist/tui/services/index.d.ts.map +1 -1
- package/dist/tui/services/index.js +6 -6
- package/dist/tui/services/index.js.map +1 -1
- package/mcp/gxp-api-server.js +83 -81
- package/package.json +109 -93
- package/runtime/PortalContainer.vue +258 -234
- package/runtime/dev-tools/DevToolsModal.vue +153 -155
- package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
- package/runtime/dev-tools/MockDataEditor.vue +456 -433
- package/runtime/dev-tools/SocketSimulator.vue +379 -371
- package/runtime/dev-tools/StoreInspector.vue +517 -455
- package/runtime/dev-tools/index.js +5 -5
- package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
- package/runtime/fallback-layouts/PublicLayout.vue +2 -2
- package/runtime/fallback-layouts/SystemLayout.vue +2 -2
- package/runtime/gxpStringsPlugin.js +159 -134
- package/runtime/index.html +17 -19
- package/runtime/main.js +24 -22
- package/runtime/mock-api/auth-middleware.js +15 -15
- package/runtime/mock-api/image-generator.js +46 -46
- package/runtime/mock-api/index.js +55 -55
- package/runtime/mock-api/response-generator.js +116 -105
- package/runtime/mock-api/route-generator.js +107 -84
- package/runtime/mock-api/socket-triggers.js +94 -93
- package/runtime/mock-api/spec-loader.js +79 -80
- package/runtime/package.json +3 -0
- package/runtime/server.js +68 -68
- package/runtime/stores/gxpPortalConfigStore.js +204 -186
- package/runtime/stores/index.js +2 -2
- package/runtime/vite-inspector-plugin.js +858 -707
- package/runtime/vite-source-tracker-plugin.js +132 -113
- package/runtime/vite.config.js +207 -132
- package/scripts/launch-chrome.js +41 -41
- package/scripts/pack-chrome.js +38 -39
- package/socket-events/AiSessionMessageCreated.json +17 -17
- package/socket-events/SocialStreamPostCreated.json +23 -23
- package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
- package/template/.claude/agents/gxp-developer.md +100 -99
- package/template/.claude/settings.json +7 -7
- package/template/AGENTS.md +30 -23
- package/template/GEMINI.md +20 -20
- package/template/README.md +70 -53
- package/template/app-manifest.json +2 -4
- package/template/configuration.json +10 -10
- package/template/default-styling.css +1 -1
- package/template/index.html +18 -20
- package/template/main.js +24 -22
- package/template/src/DemoPage.vue +415 -362
- package/template/src/Plugin.vue +76 -85
- package/template/src/stores/index.js +3 -3
- package/template/src/stores/test-data.json +164 -172
- package/template/theme-layouts/AdditionalStyling.css +50 -50
- package/template/theme-layouts/PrivateLayout.vue +8 -12
- package/template/theme-layouts/PublicLayout.vue +8 -12
- package/template/theme-layouts/SystemLayout.vue +8 -12
- package/template/vite.extend.js +45 -0
- package/template/vite.config.js +0 -409
package/runtime/vite.config.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { defineConfig, loadEnv } from "vite"
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import externalGlobals from "rollup-plugin-external-globals"
|
|
7
|
-
import { gxpInspectorPlugin } from "./vite-inspector-plugin.js"
|
|
8
|
-
import { gxpSourceTrackerPlugin } from "./vite-source-tracker-plugin.js"
|
|
1
|
+
import { defineConfig, loadEnv, mergeConfig } from "vite"
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "url"
|
|
3
|
+
import vue from "@vitejs/plugin-vue"
|
|
4
|
+
import path from "path"
|
|
5
|
+
import fs from "fs"
|
|
6
|
+
import externalGlobals from "rollup-plugin-external-globals"
|
|
7
|
+
import { gxpInspectorPlugin } from "./vite-inspector-plugin.js"
|
|
8
|
+
import { gxpSourceTrackerPlugin } from "./vite-source-tracker-plugin.js"
|
|
9
9
|
|
|
10
10
|
// Environment URL configuration for API proxy
|
|
11
11
|
const ENVIRONMENT_URLS = {
|
|
@@ -14,26 +14,26 @@ const ENVIRONMENT_URLS = {
|
|
|
14
14
|
testing: "https://api.zenith-develop-testing.env.eventfinity.app",
|
|
15
15
|
develop: "https://api.zenith-develop.env.eventfinity.app",
|
|
16
16
|
local: "https://dashboard.eventfinity.test",
|
|
17
|
-
}
|
|
17
|
+
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Get the API proxy target URL based on environment
|
|
21
21
|
*/
|
|
22
22
|
function getApiProxyTarget(env) {
|
|
23
|
-
const apiEnv = env.API_ENV || "mock"
|
|
23
|
+
const apiEnv = env.API_ENV || "mock"
|
|
24
24
|
|
|
25
25
|
// Custom URL takes precedence
|
|
26
26
|
if (env.API_BASE_URL) {
|
|
27
|
-
return env.API_BASE_URL
|
|
27
|
+
return env.API_BASE_URL
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// Mock uses local mock-api server (no proxy needed, handled separately)
|
|
31
31
|
if (apiEnv === "mock") {
|
|
32
|
-
return null
|
|
32
|
+
return null
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Look up environment URL
|
|
36
|
-
return ENVIRONMENT_URLS[apiEnv] || ENVIRONMENT_URLS.production
|
|
36
|
+
return ENVIRONMENT_URLS[apiEnv] || ENVIRONMENT_URLS.production
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -41,53 +41,53 @@ function getApiProxyTarget(env) {
|
|
|
41
41
|
*/
|
|
42
42
|
function getLibName() {
|
|
43
43
|
try {
|
|
44
|
-
const packageJsonPath = path.resolve(process.cwd(), "package.json")
|
|
44
|
+
const packageJsonPath = path.resolve(process.cwd(), "package.json")
|
|
45
45
|
if (fs.existsSync(packageJsonPath)) {
|
|
46
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
|
|
46
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
|
|
47
47
|
// Convert package name to a valid JS identifier
|
|
48
48
|
// e.g., "@company/my-plugin" -> "MyPlugin"
|
|
49
|
-
const name = packageJson.name || "Plugin"
|
|
49
|
+
const name = packageJson.name || "Plugin"
|
|
50
50
|
return name
|
|
51
51
|
.replace(/[@\/\-]/g, " ")
|
|
52
52
|
.replace(/\b\w/g, (l) => l.toUpperCase())
|
|
53
|
-
.replace(/\s/g, "")
|
|
53
|
+
.replace(/\s/g, "")
|
|
54
54
|
}
|
|
55
55
|
} catch (error) {
|
|
56
|
-
console.warn("Could not read package.json, using default lib name")
|
|
56
|
+
console.warn("Could not read package.json, using default lib name")
|
|
57
57
|
}
|
|
58
|
-
return "Plugin"
|
|
58
|
+
return "Plugin"
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
62
|
* Setup HTTPS configuration if certificates are available
|
|
63
63
|
*/
|
|
64
64
|
function getHttpsConfig(env) {
|
|
65
|
-
const useHttps = env.USE_HTTPS === "true"
|
|
66
|
-
const certPath = env.CERT_PATH
|
|
67
|
-
const keyPath = env.KEY_PATH
|
|
65
|
+
const useHttps = env.USE_HTTPS === "true"
|
|
66
|
+
const certPath = env.CERT_PATH
|
|
67
|
+
const keyPath = env.KEY_PATH
|
|
68
68
|
|
|
69
69
|
if (!useHttps || !certPath || !keyPath) {
|
|
70
|
-
return
|
|
70
|
+
return undefined
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// Resolve paths relative to project root
|
|
74
|
-
const resolvedCertPath = path.resolve(process.cwd(), certPath)
|
|
75
|
-
const resolvedKeyPath = path.resolve(process.cwd(), keyPath)
|
|
74
|
+
const resolvedCertPath = path.resolve(process.cwd(), certPath)
|
|
75
|
+
const resolvedKeyPath = path.resolve(process.cwd(), keyPath)
|
|
76
76
|
|
|
77
77
|
// Check if certificate files exist
|
|
78
78
|
if (!fs.existsSync(resolvedCertPath) || !fs.existsSync(resolvedKeyPath)) {
|
|
79
|
-
console.warn("⚠ SSL certificate files not found, falling back to HTTP")
|
|
80
|
-
return
|
|
79
|
+
console.warn("⚠ SSL certificate files not found, falling back to HTTP")
|
|
80
|
+
return undefined
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
try {
|
|
84
84
|
return {
|
|
85
85
|
key: fs.readFileSync(resolvedKeyPath),
|
|
86
86
|
cert: fs.readFileSync(resolvedCertPath),
|
|
87
|
-
}
|
|
87
|
+
}
|
|
88
88
|
} catch (error) {
|
|
89
|
-
console.warn("⚠ Failed to read SSL certificates, falling back to HTTP")
|
|
90
|
-
return
|
|
89
|
+
console.warn("⚠ Failed to read SSL certificates, falling back to HTTP")
|
|
90
|
+
return undefined
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -98,70 +98,128 @@ function findToolkitPath() {
|
|
|
98
98
|
// Derive from this config file's own location — always reliable regardless
|
|
99
99
|
// of how the package is installed (local, global, npm link, CI, etc.)
|
|
100
100
|
// This file lives at <toolkit>/runtime/vite.config.js, so toolkit root is one level up.
|
|
101
|
-
const configFileDir = path.dirname(fileURLToPath(import.meta.url))
|
|
102
|
-
return path.resolve(configFileDir, "..")
|
|
101
|
+
const configFileDir = path.dirname(fileURLToPath(import.meta.url))
|
|
102
|
+
return path.resolve(configFileDir, "..")
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Check if a file exists locally in the project
|
|
107
107
|
*/
|
|
108
108
|
function hasLocalFile(fileName) {
|
|
109
|
-
const localPath = path.resolve(process.cwd(), fileName)
|
|
110
|
-
return fs.existsSync(localPath)
|
|
109
|
+
const localPath = path.resolve(process.cwd(), fileName)
|
|
110
|
+
return fs.existsSync(localPath)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Load the project-local `vite.extend.js` (or `.mjs`) if one exists.
|
|
115
|
+
*
|
|
116
|
+
* The file may export either a config object or a function
|
|
117
|
+
* `(ctx) => config | Promise<config>`, where `ctx` is
|
|
118
|
+
* `{ mode, command, env, runtimeConfig }`. The returned config is deep-merged
|
|
119
|
+
* into the runtime config via Vite's `mergeConfig` — arrays (plugins) are
|
|
120
|
+
* concatenated, objects (resolve.alias, define, etc.) are merged key-by-key,
|
|
121
|
+
* primitives are overwritten.
|
|
122
|
+
*/
|
|
123
|
+
async function loadExtensionConfig(ctx, runtimeConfig) {
|
|
124
|
+
const candidates = ["vite.extend.js", "vite.extend.mjs"]
|
|
125
|
+
for (const name of candidates) {
|
|
126
|
+
const abs = path.resolve(process.cwd(), name)
|
|
127
|
+
if (!fs.existsSync(abs)) {
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const mod = await import(pathToFileURL(abs).href)
|
|
132
|
+
const exported = mod.default ?? mod
|
|
133
|
+
const extension =
|
|
134
|
+
typeof exported === "function"
|
|
135
|
+
? await exported({ ...ctx, runtimeConfig })
|
|
136
|
+
: exported
|
|
137
|
+
if (extension && typeof extension === "object") {
|
|
138
|
+
console.log(`🧩 Loaded ${name}`)
|
|
139
|
+
return extension
|
|
140
|
+
}
|
|
141
|
+
} catch (err) {
|
|
142
|
+
console.warn(`⚠ Failed to load ${name}:`, err.message)
|
|
143
|
+
}
|
|
144
|
+
return null
|
|
145
|
+
}
|
|
146
|
+
return null
|
|
111
147
|
}
|
|
112
148
|
|
|
113
|
-
export default defineConfig((
|
|
149
|
+
export default defineConfig(async (ctx) => {
|
|
150
|
+
const { mode } = ctx
|
|
114
151
|
// Load environment variables from project directory
|
|
115
|
-
const env = loadEnv(mode, process.cwd(), "")
|
|
152
|
+
const env = loadEnv(mode, process.cwd(), "")
|
|
116
153
|
|
|
117
154
|
// Get lib name from package.json
|
|
118
|
-
const libName = getLibName()
|
|
155
|
+
const libName = getLibName()
|
|
119
156
|
|
|
120
157
|
// Find the toolkit path for runtime imports
|
|
121
|
-
const toolkitPath = findToolkitPath()
|
|
122
|
-
const runtimeDir = path.resolve(toolkitPath, "runtime")
|
|
158
|
+
const toolkitPath = findToolkitPath()
|
|
159
|
+
const runtimeDir = path.resolve(toolkitPath, "runtime")
|
|
123
160
|
|
|
124
161
|
// Check for local dev files (requires both env var AND file to exist)
|
|
125
|
-
const hasLocalIndexHtml = hasLocalFile("index.html")
|
|
126
|
-
const hasLocalMainJs = hasLocalFile("main.js")
|
|
127
|
-
const useLocalIndex = env.USE_LOCAL_INDEX === "true" && hasLocalIndexHtml
|
|
128
|
-
const useLocalMain = env.USE_LOCAL_MAIN === "true" && hasLocalMainJs
|
|
162
|
+
const hasLocalIndexHtml = hasLocalFile("index.html")
|
|
163
|
+
const hasLocalMainJs = hasLocalFile("main.js")
|
|
164
|
+
const useLocalIndex = env.USE_LOCAL_INDEX === "true" && hasLocalIndexHtml
|
|
165
|
+
const useLocalMain = env.USE_LOCAL_MAIN === "true" && hasLocalMainJs
|
|
129
166
|
|
|
130
167
|
// Plugin enable/disable flags
|
|
131
|
-
const useSourceTracker = env.DISABLE_SOURCE_TRACKER !== "true"
|
|
132
|
-
const useInspector = env.DISABLE_INSPECTOR !== "true"
|
|
168
|
+
const useSourceTracker = env.DISABLE_SOURCE_TRACKER !== "true"
|
|
169
|
+
const useInspector = env.DISABLE_INSPECTOR !== "true"
|
|
133
170
|
|
|
134
171
|
// Log which files are being used
|
|
135
|
-
console.log(`📄 index.html: ${useLocalIndex ? "local" : "runtime"}`)
|
|
136
|
-
console.log(`📄 main.js: ${useLocalMain ? "local" : "runtime"}`)
|
|
172
|
+
console.log(`📄 index.html: ${useLocalIndex ? "local" : "runtime"}`)
|
|
173
|
+
console.log(`📄 main.js: ${useLocalMain ? "local" : "runtime"}`)
|
|
137
174
|
|
|
138
175
|
// Create plugin to serve runtime files (index.html and main.js) if no local ones exist
|
|
139
176
|
const runtimeFilesPlugin = {
|
|
140
177
|
name: "runtime-files",
|
|
141
178
|
configureServer(server) {
|
|
142
179
|
server.middlewares.use((req, res, next) => {
|
|
143
|
-
// Serve runtime index.html for root requests
|
|
180
|
+
// Serve runtime index.html for root requests and SPA navigation requests
|
|
181
|
+
// (unless local index.html is opted in). SPA fallback is required so
|
|
182
|
+
// client-side routers (e.g. vue-router createWebHistory) can handle
|
|
183
|
+
// deep links when no physical index.html exists at the project root.
|
|
184
|
+
const rawUrl = req.url || ""
|
|
185
|
+
const urlPath = rawUrl.split("?")[0]
|
|
186
|
+
const accept = req.headers.accept || ""
|
|
187
|
+
const isGetOrHead = req.method === "GET" || req.method === "HEAD"
|
|
188
|
+
const isInternalPath =
|
|
189
|
+
urlPath.startsWith("/@") ||
|
|
190
|
+
urlPath.startsWith("/__") ||
|
|
191
|
+
urlPath.startsWith("/node_modules/") ||
|
|
192
|
+
urlPath.startsWith("/src/") ||
|
|
193
|
+
urlPath.startsWith("/dev-assets/") ||
|
|
194
|
+
urlPath.startsWith("/api-proxy/")
|
|
195
|
+
const hasExtension = path.extname(urlPath) !== ""
|
|
196
|
+
const isSpaNavigation =
|
|
197
|
+
isGetOrHead &&
|
|
198
|
+
!isInternalPath &&
|
|
199
|
+
!hasExtension &&
|
|
200
|
+
accept.includes("text/html")
|
|
201
|
+
|
|
144
202
|
if (
|
|
145
203
|
!useLocalIndex &&
|
|
146
|
-
(
|
|
204
|
+
(urlPath === "/" || urlPath === "/index.html" || isSpaNavigation)
|
|
147
205
|
) {
|
|
148
|
-
const runtimeIndexPath = path.join(runtimeDir, "index.html")
|
|
206
|
+
const runtimeIndexPath = path.join(runtimeDir, "index.html")
|
|
149
207
|
if (fs.existsSync(runtimeIndexPath)) {
|
|
150
208
|
// Read and transform the runtime index.html
|
|
151
209
|
server
|
|
152
210
|
.transformIndexHtml(
|
|
153
|
-
|
|
154
|
-
fs.readFileSync(runtimeIndexPath, "utf-8")
|
|
211
|
+
rawUrl,
|
|
212
|
+
fs.readFileSync(runtimeIndexPath, "utf-8"),
|
|
155
213
|
)
|
|
156
214
|
.then((html) => {
|
|
157
|
-
res.setHeader("Content-Type", "text/html")
|
|
158
|
-
res.end(html)
|
|
215
|
+
res.setHeader("Content-Type", "text/html")
|
|
216
|
+
res.end(html)
|
|
159
217
|
})
|
|
160
218
|
.catch((err) => {
|
|
161
|
-
console.error("Error transforming index.html:", err)
|
|
162
|
-
next(err)
|
|
163
|
-
})
|
|
164
|
-
return
|
|
219
|
+
console.error("Error transforming index.html:", err)
|
|
220
|
+
next(err)
|
|
221
|
+
})
|
|
222
|
+
return
|
|
165
223
|
}
|
|
166
224
|
}
|
|
167
225
|
|
|
@@ -171,77 +229,81 @@ export default defineConfig(({ mode }) => {
|
|
|
171
229
|
(req.url === "/@gx-runtime/main.js" ||
|
|
172
230
|
req.url?.startsWith("/@gx-runtime/main.js?"))
|
|
173
231
|
) {
|
|
174
|
-
const runtimeMainPath = path.join(runtimeDir, "main.js")
|
|
232
|
+
const runtimeMainPath = path.join(runtimeDir, "main.js")
|
|
175
233
|
if (fs.existsSync(runtimeMainPath)) {
|
|
176
234
|
// Use the real path to handle symlinks correctly
|
|
177
|
-
const realMainPath = fs.realpathSync(runtimeMainPath)
|
|
235
|
+
const realMainPath = fs.realpathSync(runtimeMainPath)
|
|
178
236
|
server
|
|
179
237
|
.transformRequest(realMainPath)
|
|
180
238
|
.then((result) => {
|
|
181
239
|
if (result) {
|
|
182
|
-
res.setHeader("Content-Type", "application/javascript")
|
|
183
|
-
res.end(result.code)
|
|
240
|
+
res.setHeader("Content-Type", "application/javascript")
|
|
241
|
+
res.end(result.code)
|
|
184
242
|
} else {
|
|
185
|
-
next()
|
|
243
|
+
next()
|
|
186
244
|
}
|
|
187
245
|
})
|
|
188
246
|
.catch((err) => {
|
|
189
|
-
console.error("Error transforming main.js:", err)
|
|
190
|
-
next(err)
|
|
191
|
-
})
|
|
192
|
-
return
|
|
247
|
+
console.error("Error transforming main.js:", err)
|
|
248
|
+
next(err)
|
|
249
|
+
})
|
|
250
|
+
return
|
|
193
251
|
}
|
|
194
252
|
}
|
|
195
253
|
|
|
196
|
-
next()
|
|
197
|
-
})
|
|
254
|
+
next()
|
|
255
|
+
})
|
|
198
256
|
},
|
|
199
|
-
}
|
|
257
|
+
}
|
|
200
258
|
|
|
201
259
|
// Resolve @layouts: use project's theme-layouts/ if it exists,
|
|
202
260
|
// otherwise fall back to toolkit's runtime/fallback-layouts/
|
|
203
|
-
const projectLayoutsDir = path.resolve(process.cwd(), "theme-layouts")
|
|
204
|
-
const fallbackLayoutsDir = path.resolve(runtimeDir, "fallback-layouts")
|
|
205
|
-
const layoutsDir = fs.existsSync(projectLayoutsDir)
|
|
261
|
+
const projectLayoutsDir = path.resolve(process.cwd(), "theme-layouts")
|
|
262
|
+
const fallbackLayoutsDir = path.resolve(runtimeDir, "fallback-layouts")
|
|
263
|
+
const layoutsDir = fs.existsSync(projectLayoutsDir)
|
|
264
|
+
? projectLayoutsDir
|
|
265
|
+
: fallbackLayoutsDir
|
|
206
266
|
|
|
207
267
|
if (layoutsDir === fallbackLayoutsDir) {
|
|
208
|
-
console.log(
|
|
268
|
+
console.log(
|
|
269
|
+
"📐 Layouts: using toolkit fallbacks (no theme-layouts/ directory)",
|
|
270
|
+
)
|
|
209
271
|
} else {
|
|
210
|
-
console.log("📐 Layouts: using project theme-layouts/")
|
|
272
|
+
console.log("📐 Layouts: using project theme-layouts/")
|
|
211
273
|
}
|
|
212
274
|
|
|
213
275
|
// Determine if HTTPS is enabled
|
|
214
|
-
const useHttps = getHttpsConfig(env) !==
|
|
276
|
+
const useHttps = getHttpsConfig(env) !== undefined
|
|
215
277
|
|
|
216
278
|
// Get API proxy target for non-mock environments
|
|
217
|
-
const apiProxyTarget = getApiProxyTarget(env)
|
|
279
|
+
const apiProxyTarget = getApiProxyTarget(env)
|
|
218
280
|
if (apiProxyTarget) {
|
|
219
|
-
console.log(`🔀 API Proxy: /api-proxy -> ${apiProxyTarget}`)
|
|
281
|
+
console.log(`🔀 API Proxy: /api-proxy -> ${apiProxyTarget}`)
|
|
220
282
|
}
|
|
221
283
|
|
|
222
|
-
|
|
284
|
+
const runtimeConfig = {
|
|
223
285
|
// Root is always the project directory
|
|
224
286
|
root: process.cwd(),
|
|
225
287
|
// Expose environment variables to the browser
|
|
226
288
|
define: {
|
|
227
289
|
"import.meta.env.VITE_API_ENV": JSON.stringify(env.API_ENV || "mock"),
|
|
228
290
|
"import.meta.env.VITE_API_BASE_URL": JSON.stringify(
|
|
229
|
-
env.API_BASE_URL || ""
|
|
291
|
+
env.API_BASE_URL || "",
|
|
230
292
|
),
|
|
231
293
|
"import.meta.env.VITE_API_KEY": JSON.stringify(env.API_KEY || ""),
|
|
232
294
|
"import.meta.env.VITE_API_PROJECT_ID": JSON.stringify(
|
|
233
|
-
env.API_PROJECT_ID || ""
|
|
295
|
+
env.API_PROJECT_ID || "",
|
|
234
296
|
),
|
|
235
297
|
"import.meta.env.VITE_USE_HTTPS": JSON.stringify(
|
|
236
|
-
useHttps ? "true" : "false"
|
|
298
|
+
useHttps ? "true" : "false",
|
|
237
299
|
),
|
|
238
300
|
"import.meta.env.VITE_NODE_PORT": JSON.stringify(env.NODE_PORT || "3060"),
|
|
239
301
|
"import.meta.env.VITE_SOCKET_IO_PORT": JSON.stringify(
|
|
240
|
-
env.SOCKET_IO_PORT || "3069"
|
|
302
|
+
env.SOCKET_IO_PORT || "3069",
|
|
241
303
|
),
|
|
242
304
|
"import.meta.env.SOCKET_URL": JSON.stringify(env.SOCKET_URL || ""),
|
|
243
305
|
"import.meta.env.SOCKET_DRIVER": JSON.stringify(
|
|
244
|
-
env.SOCKET_DRIVER || "io"
|
|
306
|
+
env.SOCKET_DRIVER || "io",
|
|
245
307
|
),
|
|
246
308
|
},
|
|
247
309
|
plugins: [
|
|
@@ -260,7 +322,7 @@ export default defineConfig(({ mode }) => {
|
|
|
260
322
|
},
|
|
261
323
|
{
|
|
262
324
|
include: ["src/**"],
|
|
263
|
-
}
|
|
325
|
+
},
|
|
264
326
|
),
|
|
265
327
|
// Custom request logging and CORS plugin
|
|
266
328
|
{
|
|
@@ -269,47 +331,47 @@ export default defineConfig(({ mode }) => {
|
|
|
269
331
|
server.middlewares.use((req, res, next) => {
|
|
270
332
|
// Health check route
|
|
271
333
|
if (req.url === "/__health") {
|
|
272
|
-
res.statusCode = 200
|
|
273
|
-
res.setHeader("Content-Type", "application/json")
|
|
274
|
-
res.end(JSON.stringify({ status: "ok" }))
|
|
275
|
-
return
|
|
334
|
+
res.statusCode = 200
|
|
335
|
+
res.setHeader("Content-Type", "application/json")
|
|
336
|
+
res.end(JSON.stringify({ status: "ok" }))
|
|
337
|
+
return
|
|
276
338
|
}
|
|
277
339
|
|
|
278
|
-
const start = Date.now()
|
|
279
|
-
const originalEnd = res.end
|
|
340
|
+
const start = Date.now()
|
|
341
|
+
const originalEnd = res.end
|
|
280
342
|
|
|
281
343
|
// Add CORS headers to all responses
|
|
282
|
-
res.setHeader("Access-Control-Allow-Origin", "*")
|
|
344
|
+
res.setHeader("Access-Control-Allow-Origin", "*")
|
|
283
345
|
res.setHeader(
|
|
284
346
|
"Access-Control-Allow-Methods",
|
|
285
|
-
"GET, POST, PUT, DELETE, OPTIONS"
|
|
286
|
-
)
|
|
287
|
-
res.setHeader("Access-Control-Allow-Headers", "*")
|
|
288
|
-
res.setHeader("Access-Control-Allow-Credentials", "false")
|
|
347
|
+
"GET, POST, PUT, DELETE, OPTIONS",
|
|
348
|
+
)
|
|
349
|
+
res.setHeader("Access-Control-Allow-Headers", "*")
|
|
350
|
+
res.setHeader("Access-Control-Allow-Credentials", "false")
|
|
289
351
|
|
|
290
352
|
// Handle preflight requests
|
|
291
353
|
if (req.method === "OPTIONS") {
|
|
292
|
-
res.statusCode = 200
|
|
293
|
-
res.end()
|
|
294
|
-
return
|
|
354
|
+
res.statusCode = 200
|
|
355
|
+
res.end()
|
|
356
|
+
return
|
|
295
357
|
}
|
|
296
358
|
|
|
297
359
|
res.end = function (...args) {
|
|
298
|
-
const duration = Date.now() - start
|
|
299
|
-
const status = res.statusCode
|
|
300
|
-
const method = req.method
|
|
301
|
-
const url = req.url
|
|
302
|
-
const referer = req.headers.referer || "direct"
|
|
303
|
-
const origin = req.headers.origin || "unknown"
|
|
360
|
+
const duration = Date.now() - start
|
|
361
|
+
const status = res.statusCode
|
|
362
|
+
const method = req.method
|
|
363
|
+
const url = req.url
|
|
364
|
+
const referer = req.headers.referer || "direct"
|
|
365
|
+
const origin = req.headers.origin || "unknown"
|
|
304
366
|
|
|
305
367
|
console.log(
|
|
306
|
-
`[${new Date().toISOString()}] ${method} ${url} ${status} (${duration}ms) - Origin: ${origin} - Referer: ${referer}
|
|
307
|
-
)
|
|
308
|
-
originalEnd.apply(this, args)
|
|
309
|
-
}
|
|
368
|
+
`[${new Date().toISOString()}] ${method} ${url} ${status} (${duration}ms) - Origin: ${origin} - Referer: ${referer}`,
|
|
369
|
+
)
|
|
370
|
+
originalEnd.apply(this, args)
|
|
371
|
+
}
|
|
310
372
|
|
|
311
|
-
next()
|
|
312
|
-
})
|
|
373
|
+
next()
|
|
374
|
+
})
|
|
313
375
|
},
|
|
314
376
|
},
|
|
315
377
|
],
|
|
@@ -320,11 +382,13 @@ export default defineConfig(({ mode }) => {
|
|
|
320
382
|
strictPort: true,
|
|
321
383
|
https: getHttpsConfig(env),
|
|
322
384
|
allowedHosts: env.ALLOWED_HOSTS
|
|
323
|
-
? env.ALLOWED_HOSTS.split(",")
|
|
324
|
-
|
|
385
|
+
? env.ALLOWED_HOSTS.split(",")
|
|
386
|
+
.map((h) => h.trim())
|
|
387
|
+
.filter(Boolean)
|
|
388
|
+
: true,
|
|
325
389
|
cors: {
|
|
326
390
|
origin: "*",
|
|
327
|
-
methods: ["GET", "POST", "PUT, DELETE", "OPTIONS"],
|
|
391
|
+
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
328
392
|
allowedHeaders: ["*"],
|
|
329
393
|
credentials: false,
|
|
330
394
|
},
|
|
@@ -332,13 +396,21 @@ export default defineConfig(({ mode }) => {
|
|
|
332
396
|
? {
|
|
333
397
|
protocol: env.HMR_PROTOCOL || "wss",
|
|
334
398
|
host: env.HMR_HOST,
|
|
335
|
-
port:
|
|
336
|
-
|
|
337
|
-
|
|
399
|
+
port:
|
|
400
|
+
parseInt(env.HMR_PORT) ||
|
|
401
|
+
parseInt(env.CLIENT_PORT) ||
|
|
402
|
+
parseInt(env.NODE_PORT) ||
|
|
403
|
+
3060,
|
|
404
|
+
clientPort:
|
|
405
|
+
parseInt(env.HMR_CLIENT_PORT) ||
|
|
406
|
+
parseInt(env.CLIENT_PORT) ||
|
|
407
|
+
parseInt(env.NODE_PORT) ||
|
|
408
|
+
3060,
|
|
409
|
+
}
|
|
338
410
|
: {
|
|
339
411
|
clientPort:
|
|
340
412
|
parseInt(env.CLIENT_PORT) || parseInt(env.NODE_PORT) || 3060,
|
|
341
|
-
|
|
413
|
+
},
|
|
342
414
|
host: true, // Allow access from network
|
|
343
415
|
// Allow serving files from the toolkit runtime directory
|
|
344
416
|
// Also resolve symlinks to allow files from the real path
|
|
@@ -356,30 +428,30 @@ export default defineConfig(({ mode }) => {
|
|
|
356
428
|
configure: (proxy, options) => {
|
|
357
429
|
proxy.on("proxyReq", (proxyReq, req) => {
|
|
358
430
|
// Forward the API key as Authorization header if set
|
|
359
|
-
const apiKey = env.API_KEY
|
|
431
|
+
const apiKey = env.API_KEY
|
|
360
432
|
if (apiKey) {
|
|
361
|
-
proxyReq.setHeader("Authorization", `Bearer ${apiKey}`)
|
|
433
|
+
proxyReq.setHeader("Authorization", `Bearer ${apiKey}`)
|
|
362
434
|
}
|
|
363
435
|
console.log(
|
|
364
436
|
`[API Proxy] ${req.method} ${
|
|
365
437
|
req.url
|
|
366
438
|
} -> ${apiProxyTarget}${req.url.replace(
|
|
367
439
|
/^\/api-proxy/,
|
|
368
|
-
""
|
|
369
|
-
)}
|
|
370
|
-
)
|
|
371
|
-
})
|
|
440
|
+
"",
|
|
441
|
+
)}`,
|
|
442
|
+
)
|
|
443
|
+
})
|
|
372
444
|
proxy.on("proxyRes", (proxyRes, req) => {
|
|
373
445
|
console.log(
|
|
374
|
-
`[API Proxy] ${req.method} ${req.url} <- ${proxyRes.statusCode}
|
|
375
|
-
)
|
|
376
|
-
})
|
|
446
|
+
`[API Proxy] ${req.method} ${req.url} <- ${proxyRes.statusCode}`,
|
|
447
|
+
)
|
|
448
|
+
})
|
|
377
449
|
proxy.on("error", (err, req) => {
|
|
378
|
-
console.error(`[API Proxy] Error: ${err.message}`)
|
|
379
|
-
})
|
|
450
|
+
console.error(`[API Proxy] Error: ${err.message}`)
|
|
451
|
+
})
|
|
380
452
|
},
|
|
381
453
|
},
|
|
382
|
-
|
|
454
|
+
}
|
|
383
455
|
: {},
|
|
384
456
|
},
|
|
385
457
|
build: {
|
|
@@ -427,5 +499,8 @@ export default defineConfig(({ mode }) => {
|
|
|
427
499
|
ssr: {
|
|
428
500
|
external: ["vue", "pinia"],
|
|
429
501
|
},
|
|
430
|
-
}
|
|
431
|
-
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const extension = await loadExtensionConfig(ctx, runtimeConfig)
|
|
505
|
+
return extension ? mergeConfig(runtimeConfig, extension) : runtimeConfig
|
|
506
|
+
})
|