@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
|
@@ -5,22 +5,21 @@
|
|
|
5
5
|
* Falls back to local files when the platform API is unreachable.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const fs = require("fs")
|
|
9
|
-
const path = require("path")
|
|
10
|
-
const axios = require("axios")
|
|
11
|
-
const https = require("https")
|
|
8
|
+
const fs = require("fs")
|
|
9
|
+
const path = require("path")
|
|
10
|
+
const axios = require("axios")
|
|
11
|
+
const https = require("https")
|
|
12
12
|
|
|
13
13
|
// Import environment URLs from constants
|
|
14
|
-
let ENVIRONMENT_URLS
|
|
14
|
+
let ENVIRONMENT_URLS
|
|
15
15
|
try {
|
|
16
16
|
// When running from node_modules
|
|
17
|
-
ENVIRONMENT_URLS = require("../../bin/lib/constants").ENVIRONMENT_URLS
|
|
17
|
+
ENVIRONMENT_URLS = require("../../bin/lib/constants").ENVIRONMENT_URLS
|
|
18
18
|
} catch {
|
|
19
19
|
// Fallback for direct execution
|
|
20
|
-
ENVIRONMENT_URLS = require(
|
|
21
|
-
__dirname,
|
|
22
|
-
|
|
23
|
-
)).ENVIRONMENT_URLS;
|
|
20
|
+
ENVIRONMENT_URLS = require(
|
|
21
|
+
path.join(__dirname, "../../bin/lib/constants"),
|
|
22
|
+
).ENVIRONMENT_URLS
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
// Spec cache
|
|
@@ -29,16 +28,16 @@ const cache = {
|
|
|
29
28
|
asyncApi: null,
|
|
30
29
|
webhooks: null,
|
|
31
30
|
lastFetch: null,
|
|
32
|
-
}
|
|
31
|
+
}
|
|
33
32
|
|
|
34
33
|
// Default cache TTL (5 minutes)
|
|
35
|
-
const DEFAULT_CACHE_TTL = 5 * 60 * 1000
|
|
34
|
+
const DEFAULT_CACHE_TTL = 5 * 60 * 1000
|
|
36
35
|
|
|
37
36
|
/**
|
|
38
37
|
* Get cache TTL from environment or use default
|
|
39
38
|
*/
|
|
40
39
|
function getCacheTTL() {
|
|
41
|
-
return parseInt(process.env.MOCK_API_CACHE_TTL) || DEFAULT_CACHE_TTL
|
|
40
|
+
return parseInt(process.env.MOCK_API_CACHE_TTL) || DEFAULT_CACHE_TTL
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
/**
|
|
@@ -47,17 +46,17 @@ function getCacheTTL() {
|
|
|
47
46
|
* @returns {object} Environment URLs configuration
|
|
48
47
|
*/
|
|
49
48
|
function getEnvironmentConfig(env) {
|
|
50
|
-
const envName = env || process.env.API_ENV || "production"
|
|
51
|
-
const config = ENVIRONMENT_URLS[envName]
|
|
49
|
+
const envName = env || process.env.API_ENV || "production"
|
|
50
|
+
const config = ENVIRONMENT_URLS[envName]
|
|
52
51
|
|
|
53
52
|
if (!config) {
|
|
54
53
|
console.warn(
|
|
55
|
-
`ā ļø Unknown environment "${envName}", falling back to production
|
|
56
|
-
)
|
|
57
|
-
return ENVIRONMENT_URLS.production
|
|
54
|
+
`ā ļø Unknown environment "${envName}", falling back to production`,
|
|
55
|
+
)
|
|
56
|
+
return ENVIRONMENT_URLS.production
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
return config
|
|
59
|
+
return config
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
/**
|
|
@@ -69,7 +68,7 @@ function createHttpClient() {
|
|
|
69
68
|
httpsAgent: new https.Agent({
|
|
70
69
|
rejectUnauthorized: process.env.NODE_ENV === "production",
|
|
71
70
|
}),
|
|
72
|
-
})
|
|
71
|
+
})
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
/**
|
|
@@ -79,19 +78,19 @@ function createHttpClient() {
|
|
|
79
78
|
* @returns {object|null} Parsed JSON spec or null on error
|
|
80
79
|
*/
|
|
81
80
|
async function fetchSpec(url, specName) {
|
|
82
|
-
const client = createHttpClient()
|
|
81
|
+
const client = createHttpClient()
|
|
83
82
|
|
|
84
83
|
try {
|
|
85
|
-
console.log(`š” Fetching ${specName} from ${url}`)
|
|
86
|
-
const response = await client.get(url)
|
|
87
|
-
console.log(`ā
${specName} loaded successfully`)
|
|
88
|
-
return response.data
|
|
84
|
+
console.log(`š” Fetching ${specName} from ${url}`)
|
|
85
|
+
const response = await client.get(url)
|
|
86
|
+
console.log(`ā
${specName} loaded successfully`)
|
|
87
|
+
return response.data
|
|
89
88
|
} catch (error) {
|
|
90
89
|
const message = error.response
|
|
91
90
|
? `HTTP ${error.response.status}`
|
|
92
|
-
: error.message
|
|
93
|
-
console.warn(`ā ļø Failed to fetch ${specName}: ${message}`)
|
|
94
|
-
return null
|
|
91
|
+
: error.message
|
|
92
|
+
console.warn(`ā ļø Failed to fetch ${specName}: ${message}`)
|
|
93
|
+
return null
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
96
|
|
|
@@ -103,21 +102,21 @@ async function fetchSpec(url, specName) {
|
|
|
103
102
|
* @returns {object|null} Parsed JSON spec or null if not found
|
|
104
103
|
*/
|
|
105
104
|
function loadLocalSpec(projectRoot, filename, specName) {
|
|
106
|
-
const filePath = path.join(projectRoot, filename)
|
|
105
|
+
const filePath = path.join(projectRoot, filename)
|
|
107
106
|
|
|
108
107
|
if (!fs.existsSync(filePath)) {
|
|
109
|
-
return null
|
|
108
|
+
return null
|
|
110
109
|
}
|
|
111
110
|
|
|
112
111
|
try {
|
|
113
|
-
console.log(`š Loading local ${specName} from ${filename}`)
|
|
114
|
-
const content = fs.readFileSync(filePath, "utf-8")
|
|
115
|
-
const spec = JSON.parse(content)
|
|
116
|
-
console.log(`ā
Local ${specName} loaded successfully`)
|
|
117
|
-
return spec
|
|
112
|
+
console.log(`š Loading local ${specName} from ${filename}`)
|
|
113
|
+
const content = fs.readFileSync(filePath, "utf-8")
|
|
114
|
+
const spec = JSON.parse(content)
|
|
115
|
+
console.log(`ā
Local ${specName} loaded successfully`)
|
|
116
|
+
return spec
|
|
118
117
|
} catch (error) {
|
|
119
|
-
console.warn(`ā ļø Failed to parse local ${specName}: ${error.message}`)
|
|
120
|
-
return null
|
|
118
|
+
console.warn(`ā ļø Failed to parse local ${specName}: ${error.message}`)
|
|
119
|
+
return null
|
|
121
120
|
}
|
|
122
121
|
}
|
|
123
122
|
|
|
@@ -127,17 +126,17 @@ function loadLocalSpec(projectRoot, filename, specName) {
|
|
|
127
126
|
* @returns {object|null} OpenAPI spec
|
|
128
127
|
*/
|
|
129
128
|
async function fetchOpenApiSpec(projectRoot) {
|
|
130
|
-
const config = getEnvironmentConfig()
|
|
129
|
+
const config = getEnvironmentConfig()
|
|
131
130
|
|
|
132
131
|
// Try remote first
|
|
133
|
-
let spec = await fetchSpec(config.openApiSpec, "OpenAPI spec")
|
|
132
|
+
let spec = await fetchSpec(config.openApiSpec, "OpenAPI spec")
|
|
134
133
|
|
|
135
134
|
// Fallback to local
|
|
136
135
|
if (!spec && projectRoot) {
|
|
137
|
-
spec = loadLocalSpec(projectRoot, "openapi.json", "OpenAPI spec")
|
|
136
|
+
spec = loadLocalSpec(projectRoot, "openapi.json", "OpenAPI spec")
|
|
138
137
|
}
|
|
139
138
|
|
|
140
|
-
return spec
|
|
139
|
+
return spec
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
/**
|
|
@@ -146,17 +145,17 @@ async function fetchOpenApiSpec(projectRoot) {
|
|
|
146
145
|
* @returns {object|null} AsyncAPI spec
|
|
147
146
|
*/
|
|
148
147
|
async function fetchAsyncApiSpec(projectRoot) {
|
|
149
|
-
const config = getEnvironmentConfig()
|
|
148
|
+
const config = getEnvironmentConfig()
|
|
150
149
|
|
|
151
150
|
// Try remote first
|
|
152
|
-
let spec = await fetchSpec(config.asyncApiSpec, "AsyncAPI spec")
|
|
151
|
+
let spec = await fetchSpec(config.asyncApiSpec, "AsyncAPI spec")
|
|
153
152
|
|
|
154
153
|
// Fallback to local
|
|
155
154
|
if (!spec && projectRoot) {
|
|
156
|
-
spec = loadLocalSpec(projectRoot, "asyncapi.json", "AsyncAPI spec")
|
|
155
|
+
spec = loadLocalSpec(projectRoot, "asyncapi.json", "AsyncAPI spec")
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
return spec
|
|
158
|
+
return spec
|
|
160
159
|
}
|
|
161
160
|
|
|
162
161
|
/**
|
|
@@ -165,17 +164,17 @@ async function fetchAsyncApiSpec(projectRoot) {
|
|
|
165
164
|
* @returns {object|null} Webhook spec
|
|
166
165
|
*/
|
|
167
166
|
async function fetchWebhookSpec(projectRoot) {
|
|
168
|
-
const config = getEnvironmentConfig()
|
|
167
|
+
const config = getEnvironmentConfig()
|
|
169
168
|
|
|
170
169
|
// Try remote first
|
|
171
|
-
let spec = await fetchSpec(config.webhookSpec, "Webhook spec")
|
|
170
|
+
let spec = await fetchSpec(config.webhookSpec, "Webhook spec")
|
|
172
171
|
|
|
173
172
|
// Fallback to local
|
|
174
173
|
if (!spec && projectRoot) {
|
|
175
|
-
spec = loadLocalSpec(projectRoot, "webhooks.json", "Webhook spec")
|
|
174
|
+
spec = loadLocalSpec(projectRoot, "webhooks.json", "Webhook spec")
|
|
176
175
|
}
|
|
177
176
|
|
|
178
|
-
return spec
|
|
177
|
+
return spec
|
|
179
178
|
}
|
|
180
179
|
|
|
181
180
|
/**
|
|
@@ -184,11 +183,11 @@ async function fetchWebhookSpec(projectRoot) {
|
|
|
184
183
|
*/
|
|
185
184
|
function isCacheValid() {
|
|
186
185
|
if (!cache.lastFetch) {
|
|
187
|
-
return false
|
|
186
|
+
return false
|
|
188
187
|
}
|
|
189
188
|
|
|
190
|
-
const elapsed = Date.now() - cache.lastFetch
|
|
191
|
-
return elapsed < getCacheTTL()
|
|
189
|
+
const elapsed = Date.now() - cache.lastFetch
|
|
190
|
+
return elapsed < getCacheTTL()
|
|
192
191
|
}
|
|
193
192
|
|
|
194
193
|
/**
|
|
@@ -200,45 +199,45 @@ function isCacheValid() {
|
|
|
200
199
|
async function loadSpecs(projectRoot, forceRefresh = false) {
|
|
201
200
|
// Return cached if valid and not forcing refresh
|
|
202
201
|
if (!forceRefresh && isCacheValid()) {
|
|
203
|
-
console.log("š¦ Using cached specs")
|
|
202
|
+
console.log("š¦ Using cached specs")
|
|
204
203
|
return {
|
|
205
204
|
openApi: cache.openApi,
|
|
206
205
|
asyncApi: cache.asyncApi,
|
|
207
206
|
webhooks: cache.webhooks,
|
|
208
|
-
}
|
|
207
|
+
}
|
|
209
208
|
}
|
|
210
209
|
|
|
211
|
-
const root = projectRoot || process.cwd()
|
|
210
|
+
const root = projectRoot || process.cwd()
|
|
212
211
|
|
|
213
|
-
console.log("š Loading API specs...")
|
|
214
|
-
console.log(` Environment: ${process.env.API_ENV || "production"}`)
|
|
212
|
+
console.log("š Loading API specs...")
|
|
213
|
+
console.log(` Environment: ${process.env.API_ENV || "production"}`)
|
|
215
214
|
|
|
216
215
|
// Fetch all specs in parallel
|
|
217
216
|
const [openApi, asyncApi, webhooks] = await Promise.all([
|
|
218
217
|
fetchOpenApiSpec(root),
|
|
219
218
|
fetchAsyncApiSpec(root),
|
|
220
219
|
fetchWebhookSpec(root),
|
|
221
|
-
])
|
|
220
|
+
])
|
|
222
221
|
|
|
223
222
|
// Update cache
|
|
224
|
-
cache.openApi = openApi
|
|
225
|
-
cache.asyncApi = asyncApi
|
|
226
|
-
cache.webhooks = webhooks
|
|
227
|
-
cache.lastFetch = Date.now()
|
|
223
|
+
cache.openApi = openApi
|
|
224
|
+
cache.asyncApi = asyncApi
|
|
225
|
+
cache.webhooks = webhooks
|
|
226
|
+
cache.lastFetch = Date.now()
|
|
228
227
|
|
|
229
228
|
// Log summary
|
|
230
|
-
const loaded = []
|
|
231
|
-
if (openApi) loaded.push("OpenAPI")
|
|
232
|
-
if (asyncApi) loaded.push("AsyncAPI")
|
|
233
|
-
if (webhooks) loaded.push("Webhooks")
|
|
229
|
+
const loaded = []
|
|
230
|
+
if (openApi) loaded.push("OpenAPI")
|
|
231
|
+
if (asyncApi) loaded.push("AsyncAPI")
|
|
232
|
+
if (webhooks) loaded.push("Webhooks")
|
|
234
233
|
|
|
235
234
|
if (loaded.length > 0) {
|
|
236
|
-
console.log(`ā
Loaded specs: ${loaded.join(", ")}`)
|
|
235
|
+
console.log(`ā
Loaded specs: ${loaded.join(", ")}`)
|
|
237
236
|
} else {
|
|
238
|
-
console.warn("ā ļø No specs were loaded")
|
|
237
|
+
console.warn("ā ļø No specs were loaded")
|
|
239
238
|
}
|
|
240
239
|
|
|
241
|
-
return { openApi, asyncApi, webhooks }
|
|
240
|
+
return { openApi, asyncApi, webhooks }
|
|
242
241
|
}
|
|
243
242
|
|
|
244
243
|
/**
|
|
@@ -247,13 +246,13 @@ async function loadSpecs(projectRoot, forceRefresh = false) {
|
|
|
247
246
|
* @returns {object} Freshly loaded specs
|
|
248
247
|
*/
|
|
249
248
|
async function refreshSpecs(projectRoot) {
|
|
250
|
-
console.log("š Refreshing API specs...")
|
|
251
|
-
cache.openApi = null
|
|
252
|
-
cache.asyncApi = null
|
|
253
|
-
cache.webhooks = null
|
|
254
|
-
cache.lastFetch = null
|
|
249
|
+
console.log("š Refreshing API specs...")
|
|
250
|
+
cache.openApi = null
|
|
251
|
+
cache.asyncApi = null
|
|
252
|
+
cache.webhooks = null
|
|
253
|
+
cache.lastFetch = null
|
|
255
254
|
|
|
256
|
-
return loadSpecs(projectRoot, true)
|
|
255
|
+
return loadSpecs(projectRoot, true)
|
|
257
256
|
}
|
|
258
257
|
|
|
259
258
|
/**
|
|
@@ -261,8 +260,8 @@ async function refreshSpecs(projectRoot) {
|
|
|
261
260
|
* @returns {object} Cache status info
|
|
262
261
|
*/
|
|
263
262
|
function getCacheStatus() {
|
|
264
|
-
const ttl = getCacheTTL()
|
|
265
|
-
const elapsed = cache.lastFetch ? Date.now() - cache.lastFetch : null
|
|
263
|
+
const ttl = getCacheTTL()
|
|
264
|
+
const elapsed = cache.lastFetch ? Date.now() - cache.lastFetch : null
|
|
266
265
|
|
|
267
266
|
return {
|
|
268
267
|
hasOpenApi: !!cache.openApi,
|
|
@@ -272,7 +271,7 @@ function getCacheStatus() {
|
|
|
272
271
|
cacheValid: isCacheValid(),
|
|
273
272
|
ttlMs: ttl,
|
|
274
273
|
expiresIn: elapsed !== null ? Math.max(0, ttl - elapsed) : null,
|
|
275
|
-
}
|
|
274
|
+
}
|
|
276
275
|
}
|
|
277
276
|
|
|
278
277
|
/**
|
|
@@ -284,7 +283,7 @@ function getCachedSpecs() {
|
|
|
284
283
|
openApi: cache.openApi,
|
|
285
284
|
asyncApi: cache.asyncApi,
|
|
286
285
|
webhooks: cache.webhooks,
|
|
287
|
-
}
|
|
286
|
+
}
|
|
288
287
|
}
|
|
289
288
|
|
|
290
289
|
module.exports = {
|
|
@@ -297,4 +296,4 @@ module.exports = {
|
|
|
297
296
|
getCacheStatus,
|
|
298
297
|
getCachedSpecs,
|
|
299
298
|
isCacheValid,
|
|
300
|
-
}
|
|
299
|
+
}
|
package/runtime/server.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
const express = require("express")
|
|
2
|
-
const cors = require("cors")
|
|
3
|
-
const fs = require("fs")
|
|
4
|
-
const path = require("path")
|
|
5
|
-
const dotenv = require("dotenv")
|
|
1
|
+
const express = require("express")
|
|
2
|
+
const cors = require("cors")
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const dotenv = require("dotenv")
|
|
6
6
|
|
|
7
7
|
// Load .env file from project directory (process.cwd())
|
|
8
|
-
const envPath = path.join(process.cwd(), ".env")
|
|
8
|
+
const envPath = path.join(process.cwd(), ".env")
|
|
9
9
|
if (fs.existsSync(envPath)) {
|
|
10
|
-
dotenv.config({ path: envPath })
|
|
10
|
+
dotenv.config({ path: envPath })
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const app = express()
|
|
13
|
+
const app = express()
|
|
14
14
|
|
|
15
15
|
app.use(
|
|
16
16
|
cors({
|
|
17
17
|
origin: "*",
|
|
18
|
-
})
|
|
19
|
-
)
|
|
18
|
+
}),
|
|
19
|
+
)
|
|
20
20
|
|
|
21
21
|
// Middleware to parse JSON
|
|
22
|
-
app.use(express.json())
|
|
22
|
+
app.use(express.json())
|
|
23
23
|
|
|
24
24
|
// Serve static development assets
|
|
25
|
-
const devAssetsDir = path.join(process.cwd(), "dev-assets")
|
|
25
|
+
const devAssetsDir = path.join(process.cwd(), "dev-assets")
|
|
26
26
|
if (fs.existsSync(devAssetsDir)) {
|
|
27
|
-
app.use("/dev-assets", express.static(devAssetsDir))
|
|
28
|
-
console.log("š Serving development assets from /dev-assets")
|
|
27
|
+
app.use("/dev-assets", express.static(devAssetsDir))
|
|
28
|
+
console.log("š Serving development assets from /dev-assets")
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -33,92 +33,92 @@ if (fs.existsSync(devAssetsDir)) {
|
|
|
33
33
|
*/
|
|
34
34
|
function findExistingCertificates(certsDir) {
|
|
35
35
|
if (!fs.existsSync(certsDir)) {
|
|
36
|
-
return null
|
|
36
|
+
return null
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const files = fs.readdirSync(certsDir)
|
|
39
|
+
const files = fs.readdirSync(certsDir)
|
|
40
40
|
|
|
41
41
|
// Look for localhost certificates (with or without suffixes)
|
|
42
42
|
const certFile = files.find(
|
|
43
43
|
(f) =>
|
|
44
|
-
f.startsWith("localhost") && f.endsWith(".pem") && !f.includes("-key")
|
|
45
|
-
)
|
|
44
|
+
f.startsWith("localhost") && f.endsWith(".pem") && !f.includes("-key"),
|
|
45
|
+
)
|
|
46
46
|
const keyFile = files.find(
|
|
47
|
-
(f) => f.startsWith("localhost") && f.endsWith("-key.pem")
|
|
48
|
-
)
|
|
47
|
+
(f) => f.startsWith("localhost") && f.endsWith("-key.pem"),
|
|
48
|
+
)
|
|
49
49
|
|
|
50
50
|
if (certFile && keyFile) {
|
|
51
|
-
const certPath = path.join(certsDir, certFile)
|
|
52
|
-
const keyPath = path.join(certsDir, keyFile)
|
|
51
|
+
const certPath = path.join(certsDir, certFile)
|
|
52
|
+
const keyPath = path.join(certsDir, keyFile)
|
|
53
53
|
|
|
54
54
|
// Verify files actually exist and have content
|
|
55
55
|
try {
|
|
56
|
-
const certStats = fs.statSync(certPath)
|
|
57
|
-
const keyStats = fs.statSync(keyPath)
|
|
56
|
+
const certStats = fs.statSync(certPath)
|
|
57
|
+
const keyStats = fs.statSync(keyPath)
|
|
58
58
|
|
|
59
59
|
if (certStats.size > 0 && keyStats.size > 0) {
|
|
60
|
-
return { certPath, keyPath }
|
|
60
|
+
return { certPath, keyPath }
|
|
61
61
|
}
|
|
62
62
|
} catch (error) {
|
|
63
63
|
// Files don't exist or can't be read
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
return null
|
|
67
|
+
return null
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// Check for SSL certificates using improved detection
|
|
71
|
-
const certsDir = path.join(process.cwd(), ".certs")
|
|
72
|
-
const existingCerts = findExistingCertificates(certsDir)
|
|
71
|
+
const certsDir = path.join(process.cwd(), ".certs")
|
|
72
|
+
const existingCerts = findExistingCertificates(certsDir)
|
|
73
73
|
|
|
74
|
-
let server
|
|
75
|
-
let protocol = "HTTP"
|
|
74
|
+
let server
|
|
75
|
+
let protocol = "HTTP"
|
|
76
76
|
|
|
77
77
|
if (existingCerts) {
|
|
78
78
|
// Use HTTPS if certificates are available
|
|
79
|
-
const https = require("https")
|
|
79
|
+
const https = require("https")
|
|
80
80
|
const options = {
|
|
81
81
|
cert: fs.readFileSync(existingCerts.certPath),
|
|
82
82
|
key: fs.readFileSync(existingCerts.keyPath),
|
|
83
|
-
}
|
|
84
|
-
server = https.createServer(options, app)
|
|
85
|
-
protocol = "HTTPS"
|
|
86
|
-
console.log(`š Using certificate: ${path.basename(existingCerts.certPath)}`)
|
|
87
|
-
console.log(`š Using key: ${path.basename(existingCerts.keyPath)}`)
|
|
83
|
+
}
|
|
84
|
+
server = https.createServer(options, app)
|
|
85
|
+
protocol = "HTTPS"
|
|
86
|
+
console.log(`š Using certificate: ${path.basename(existingCerts.certPath)}`)
|
|
87
|
+
console.log(`š Using key: ${path.basename(existingCerts.keyPath)}`)
|
|
88
88
|
} else {
|
|
89
89
|
// Fall back to HTTP if no certificates
|
|
90
|
-
const http = require("http")
|
|
91
|
-
server = http.createServer(app)
|
|
90
|
+
const http = require("http")
|
|
91
|
+
server = http.createServer(app)
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const { Server } = require("socket.io")
|
|
94
|
+
const { Server } = require("socket.io")
|
|
95
95
|
|
|
96
96
|
const io = new Server(server, {
|
|
97
97
|
cors: {
|
|
98
98
|
origin: "*",
|
|
99
99
|
},
|
|
100
|
-
})
|
|
100
|
+
})
|
|
101
101
|
|
|
102
102
|
io.on("connection", (socket) => {
|
|
103
103
|
socket.onAny((event, data) => {
|
|
104
|
-
socket.broadcast.emit(event, data)
|
|
105
|
-
})
|
|
106
|
-
})
|
|
104
|
+
socket.broadcast.emit(event, data)
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
107
|
|
|
108
108
|
// HTTP endpoint for CLI to send socket events
|
|
109
109
|
app.post("/emit", (req, res) => {
|
|
110
|
-
const { event, channel, data } = req.body
|
|
110
|
+
const { event, channel, data } = req.body
|
|
111
111
|
|
|
112
112
|
if (!event) {
|
|
113
|
-
return res.status(400).json({ error: "Event name is required" })
|
|
113
|
+
return res.status(400).json({ error: "Event name is required" })
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
console.log(`š” CLI triggered socket event: ${event}`)
|
|
117
|
-
console.log(`šŗ Channel: ${channel}`)
|
|
118
|
-
console.log(`š¦ Data:`, data)
|
|
116
|
+
console.log(`š” CLI triggered socket event: ${event}`)
|
|
117
|
+
console.log(`šŗ Channel: ${channel}`)
|
|
118
|
+
console.log(`š¦ Data:`, data)
|
|
119
119
|
|
|
120
120
|
// Emit to all connected clients
|
|
121
|
-
io.emit(event, data)
|
|
121
|
+
io.emit(event, data)
|
|
122
122
|
|
|
123
123
|
res.json({
|
|
124
124
|
success: true,
|
|
@@ -126,8 +126,8 @@ app.post("/emit", (req, res) => {
|
|
|
126
126
|
event,
|
|
127
127
|
channel,
|
|
128
128
|
data,
|
|
129
|
-
})
|
|
130
|
-
})
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
131
|
|
|
132
132
|
// Basic health check endpoint
|
|
133
133
|
app.get("/health", (req, res) => {
|
|
@@ -136,8 +136,8 @@ app.get("/health", (req, res) => {
|
|
|
136
136
|
protocol,
|
|
137
137
|
mockApiEnabled: process.env.MOCK_API_ENABLED === "true",
|
|
138
138
|
timestamp: new Date().toISOString(),
|
|
139
|
-
})
|
|
140
|
-
})
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* Initialize and start the server
|
|
@@ -146,35 +146,35 @@ async function startServer() {
|
|
|
146
146
|
// Mount Mock API if enabled
|
|
147
147
|
if (process.env.MOCK_API_ENABLED === "true") {
|
|
148
148
|
try {
|
|
149
|
-
const { createMockApiRouter } = require("./mock-api")
|
|
149
|
+
const { createMockApiRouter } = require("./mock-api")
|
|
150
150
|
const mockRouter = await createMockApiRouter(io, {
|
|
151
151
|
projectRoot: process.cwd(),
|
|
152
|
-
})
|
|
153
|
-
app.use(mockRouter)
|
|
152
|
+
})
|
|
153
|
+
app.use(mockRouter)
|
|
154
154
|
} catch (error) {
|
|
155
|
-
console.error("ā Failed to initialize Mock API:", error.message)
|
|
156
|
-
console.log(" Continuing without Mock API...")
|
|
155
|
+
console.error("ā Failed to initialize Mock API:", error.message)
|
|
156
|
+
console.log(" Continuing without Mock API...")
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
const socketIoPort = process.env.SOCKET_IO_PORT || 3069
|
|
160
|
+
const socketIoPort = process.env.SOCKET_IO_PORT || 3069
|
|
161
161
|
|
|
162
162
|
server.listen(socketIoPort, () => {
|
|
163
163
|
console.log(
|
|
164
|
-
`\nš Socket.IO server running on ${protocol} at port ${socketIoPort}
|
|
165
|
-
)
|
|
164
|
+
`\nš Socket.IO server running on ${protocol} at port ${socketIoPort}`,
|
|
165
|
+
)
|
|
166
166
|
if (protocol === "HTTPS") {
|
|
167
|
-
console.log("š Using SSL certificates for secure WebSocket connections")
|
|
167
|
+
console.log("š Using SSL certificates for secure WebSocket connections")
|
|
168
168
|
}
|
|
169
|
-
console.log("š” Socket event simulation available at POST /emit")
|
|
169
|
+
console.log("š” Socket event simulation available at POST /emit")
|
|
170
170
|
if (process.env.MOCK_API_ENABLED === "true") {
|
|
171
|
-
console.log("š Mock API enabled - routes available under /api/*")
|
|
171
|
+
console.log("š Mock API enabled - routes available under /api/*")
|
|
172
172
|
}
|
|
173
|
-
})
|
|
173
|
+
})
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
// Start the server
|
|
177
177
|
startServer().catch((error) => {
|
|
178
|
-
console.error("Failed to start server:", error)
|
|
179
|
-
process.exit(1)
|
|
180
|
-
})
|
|
178
|
+
console.error("Failed to start server:", error)
|
|
179
|
+
process.exit(1)
|
|
180
|
+
})
|