@gxp-dev/tools 2.0.63 → 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.
Files changed (182) hide show
  1. package/README.md +32 -31
  2. package/bin/gx-devtools.js +74 -54
  3. package/bin/lib/cli.js +23 -21
  4. package/bin/lib/commands/add-dependency.js +366 -325
  5. package/bin/lib/commands/assets.js +137 -139
  6. package/bin/lib/commands/build.js +169 -174
  7. package/bin/lib/commands/datastore.js +181 -183
  8. package/bin/lib/commands/dev.js +127 -131
  9. package/bin/lib/commands/extensions.js +147 -149
  10. package/bin/lib/commands/extract-config.js +73 -67
  11. package/bin/lib/commands/index.js +12 -12
  12. package/bin/lib/commands/init.js +342 -240
  13. package/bin/lib/commands/publish.js +69 -75
  14. package/bin/lib/commands/socket.js +69 -69
  15. package/bin/lib/commands/ssl.js +14 -14
  16. package/bin/lib/constants.js +10 -24
  17. package/bin/lib/tui/App.tsx +761 -705
  18. package/bin/lib/tui/components/AIPanel.tsx +191 -171
  19. package/bin/lib/tui/components/CommandInput.tsx +394 -343
  20. package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
  21. package/bin/lib/tui/components/Header.tsx +23 -21
  22. package/bin/lib/tui/components/LogPanel.tsx +244 -220
  23. package/bin/lib/tui/components/TabBar.tsx +50 -48
  24. package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
  25. package/bin/lib/tui/index.tsx +37 -39
  26. package/bin/lib/tui/services/AIService.ts +518 -462
  27. package/bin/lib/tui/services/ExtensionService.ts +140 -129
  28. package/bin/lib/tui/services/GeminiService.ts +367 -337
  29. package/bin/lib/tui/services/ServiceManager.ts +344 -322
  30. package/bin/lib/tui/services/SocketService.ts +168 -168
  31. package/bin/lib/tui/services/ViteService.ts +88 -88
  32. package/bin/lib/tui/services/index.ts +47 -22
  33. package/bin/lib/utils/ai-scaffold.js +291 -280
  34. package/bin/lib/utils/extract-config.js +157 -140
  35. package/bin/lib/utils/files.js +82 -86
  36. package/bin/lib/utils/index.js +7 -7
  37. package/bin/lib/utils/paths.js +34 -34
  38. package/bin/lib/utils/prompts.js +194 -169
  39. package/bin/lib/utils/ssl.js +79 -81
  40. package/browser-extensions/README.md +0 -1
  41. package/browser-extensions/chrome/background.js +244 -237
  42. package/browser-extensions/chrome/content.js +32 -29
  43. package/browser-extensions/chrome/devtools.html +7 -7
  44. package/browser-extensions/chrome/devtools.js +19 -19
  45. package/browser-extensions/chrome/inspector.js +802 -767
  46. package/browser-extensions/chrome/manifest.json +71 -63
  47. package/browser-extensions/chrome/panel.html +674 -636
  48. package/browser-extensions/chrome/panel.js +722 -712
  49. package/browser-extensions/chrome/popup.html +586 -543
  50. package/browser-extensions/chrome/popup.js +282 -244
  51. package/browser-extensions/chrome/rules.json +1 -1
  52. package/browser-extensions/chrome/test-chrome.html +216 -136
  53. package/browser-extensions/chrome/test-mixed-content.html +284 -189
  54. package/browser-extensions/chrome/test-uri-pattern.html +221 -198
  55. package/browser-extensions/firefox/README.md +9 -6
  56. package/browser-extensions/firefox/background.js +221 -218
  57. package/browser-extensions/firefox/content.js +55 -52
  58. package/browser-extensions/firefox/debug-errors.html +386 -228
  59. package/browser-extensions/firefox/debug-https.html +153 -105
  60. package/browser-extensions/firefox/devtools.html +7 -7
  61. package/browser-extensions/firefox/devtools.js +23 -20
  62. package/browser-extensions/firefox/inspector.js +802 -767
  63. package/browser-extensions/firefox/manifest.json +68 -68
  64. package/browser-extensions/firefox/panel.html +674 -636
  65. package/browser-extensions/firefox/panel.js +722 -712
  66. package/browser-extensions/firefox/popup.html +572 -535
  67. package/browser-extensions/firefox/popup.js +281 -236
  68. package/browser-extensions/firefox/test-gramercy.html +170 -125
  69. package/browser-extensions/firefox/test-imports.html +59 -55
  70. package/browser-extensions/firefox/test-masking.html +231 -140
  71. package/browser-extensions/firefox/test-uri-pattern.html +221 -198
  72. package/dist/tui/App.d.ts +1 -1
  73. package/dist/tui/App.d.ts.map +1 -1
  74. package/dist/tui/App.js +154 -150
  75. package/dist/tui/App.js.map +1 -1
  76. package/dist/tui/components/AIPanel.d.ts.map +1 -1
  77. package/dist/tui/components/AIPanel.js +42 -35
  78. package/dist/tui/components/AIPanel.js.map +1 -1
  79. package/dist/tui/components/CommandInput.d.ts +1 -1
  80. package/dist/tui/components/CommandInput.d.ts.map +1 -1
  81. package/dist/tui/components/CommandInput.js +92 -62
  82. package/dist/tui/components/CommandInput.js.map +1 -1
  83. package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
  84. package/dist/tui/components/GeminiPanel.js +37 -30
  85. package/dist/tui/components/GeminiPanel.js.map +1 -1
  86. package/dist/tui/components/Header.d.ts.map +1 -1
  87. package/dist/tui/components/Header.js +1 -1
  88. package/dist/tui/components/Header.js.map +1 -1
  89. package/dist/tui/components/LogPanel.d.ts +1 -1
  90. package/dist/tui/components/LogPanel.d.ts.map +1 -1
  91. package/dist/tui/components/LogPanel.js +26 -24
  92. package/dist/tui/components/LogPanel.js.map +1 -1
  93. package/dist/tui/components/TabBar.d.ts +2 -2
  94. package/dist/tui/components/TabBar.d.ts.map +1 -1
  95. package/dist/tui/components/TabBar.js +11 -11
  96. package/dist/tui/components/TabBar.js.map +1 -1
  97. package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
  98. package/dist/tui/components/WelcomeScreen.js +6 -6
  99. package/dist/tui/components/WelcomeScreen.js.map +1 -1
  100. package/dist/tui/index.d.ts.map +1 -1
  101. package/dist/tui/index.js +8 -8
  102. package/dist/tui/index.js.map +1 -1
  103. package/dist/tui/services/AIService.d.ts +2 -2
  104. package/dist/tui/services/AIService.d.ts.map +1 -1
  105. package/dist/tui/services/AIService.js +165 -125
  106. package/dist/tui/services/AIService.js.map +1 -1
  107. package/dist/tui/services/ExtensionService.d.ts +1 -1
  108. package/dist/tui/services/ExtensionService.d.ts.map +1 -1
  109. package/dist/tui/services/ExtensionService.js +33 -26
  110. package/dist/tui/services/ExtensionService.js.map +1 -1
  111. package/dist/tui/services/GeminiService.d.ts +1 -1
  112. package/dist/tui/services/GeminiService.d.ts.map +1 -1
  113. package/dist/tui/services/GeminiService.js +87 -76
  114. package/dist/tui/services/GeminiService.js.map +1 -1
  115. package/dist/tui/services/ServiceManager.d.ts +3 -3
  116. package/dist/tui/services/ServiceManager.d.ts.map +1 -1
  117. package/dist/tui/services/ServiceManager.js +72 -58
  118. package/dist/tui/services/ServiceManager.js.map +1 -1
  119. package/dist/tui/services/SocketService.d.ts.map +1 -1
  120. package/dist/tui/services/SocketService.js +32 -32
  121. package/dist/tui/services/SocketService.js.map +1 -1
  122. package/dist/tui/services/ViteService.d.ts.map +1 -1
  123. package/dist/tui/services/ViteService.js +26 -28
  124. package/dist/tui/services/ViteService.js.map +1 -1
  125. package/dist/tui/services/index.d.ts +6 -6
  126. package/dist/tui/services/index.d.ts.map +1 -1
  127. package/dist/tui/services/index.js +6 -6
  128. package/dist/tui/services/index.js.map +1 -1
  129. package/mcp/gxp-api-server.js +83 -81
  130. package/package.json +109 -93
  131. package/runtime/PortalContainer.vue +258 -234
  132. package/runtime/dev-tools/DevToolsModal.vue +153 -155
  133. package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
  134. package/runtime/dev-tools/MockDataEditor.vue +456 -433
  135. package/runtime/dev-tools/SocketSimulator.vue +379 -371
  136. package/runtime/dev-tools/StoreInspector.vue +517 -455
  137. package/runtime/dev-tools/index.js +5 -5
  138. package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
  139. package/runtime/fallback-layouts/PublicLayout.vue +2 -2
  140. package/runtime/fallback-layouts/SystemLayout.vue +2 -2
  141. package/runtime/gxpStringsPlugin.js +159 -134
  142. package/runtime/index.html +17 -19
  143. package/runtime/main.js +24 -22
  144. package/runtime/mock-api/auth-middleware.js +15 -15
  145. package/runtime/mock-api/image-generator.js +46 -46
  146. package/runtime/mock-api/index.js +55 -55
  147. package/runtime/mock-api/response-generator.js +116 -105
  148. package/runtime/mock-api/route-generator.js +107 -84
  149. package/runtime/mock-api/socket-triggers.js +94 -93
  150. package/runtime/mock-api/spec-loader.js +79 -80
  151. package/runtime/package.json +3 -0
  152. package/runtime/server.js +68 -68
  153. package/runtime/stores/gxpPortalConfigStore.js +204 -186
  154. package/runtime/stores/index.js +2 -2
  155. package/runtime/vite-inspector-plugin.js +858 -707
  156. package/runtime/vite-source-tracker-plugin.js +132 -113
  157. package/runtime/vite.config.js +191 -139
  158. package/scripts/launch-chrome.js +41 -41
  159. package/scripts/pack-chrome.js +38 -39
  160. package/socket-events/AiSessionMessageCreated.json +17 -17
  161. package/socket-events/SocialStreamPostCreated.json +23 -23
  162. package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
  163. package/template/.claude/agents/gxp-developer.md +100 -99
  164. package/template/.claude/settings.json +7 -7
  165. package/template/AGENTS.md +30 -23
  166. package/template/GEMINI.md +20 -20
  167. package/template/README.md +70 -53
  168. package/template/app-manifest.json +2 -4
  169. package/template/configuration.json +10 -10
  170. package/template/default-styling.css +1 -1
  171. package/template/index.html +18 -20
  172. package/template/main.js +24 -22
  173. package/template/src/DemoPage.vue +415 -362
  174. package/template/src/Plugin.vue +76 -85
  175. package/template/src/stores/index.js +3 -3
  176. package/template/src/stores/test-data.json +164 -172
  177. package/template/theme-layouts/AdditionalStyling.css +50 -50
  178. package/template/theme-layouts/PrivateLayout.vue +8 -12
  179. package/template/theme-layouts/PublicLayout.vue +8 -12
  180. package/template/theme-layouts/SystemLayout.vue +8 -12
  181. package/template/vite.extend.js +45 -0
  182. package/template/vite.config.js +0 -409
@@ -14,10 +14,10 @@
14
14
  * 5. Prompt to launch browser with extension
15
15
  */
16
16
 
17
- const path = require("path");
18
- const fs = require("fs");
19
- const { spawn } = require("child_process");
20
- const { REQUIRED_DEPENDENCIES } = require("../constants");
17
+ const path = require("path")
18
+ const fs = require("fs")
19
+ const { spawn } = require("child_process")
20
+ const { REQUIRED_DEPENDENCIES } = require("../constants")
21
21
  const {
22
22
  findProjectRoot,
23
23
  resolveGxPaths,
@@ -35,7 +35,7 @@ const {
35
35
  updateEnvWithCertPaths,
36
36
  runAIScaffolding,
37
37
  getAvailableProviders,
38
- } = require("../utils");
38
+ } = require("../utils")
39
39
 
40
40
  /**
41
41
  * Copy template files to project
@@ -75,14 +75,14 @@ function copyTemplateFiles(projectPath, paths, overwrite = false) {
75
75
  dest: "src/DemoPage.vue",
76
76
  desc: "DemoPage.vue (Example component)",
77
77
  },
78
- ];
78
+ ]
79
79
 
80
80
  // Copy template files
81
81
  filesToCopy.forEach((file) => {
82
- const srcPath = path.join(paths.templateDir, file.src);
83
- const destPath = path.join(projectPath, file.dest);
84
- safeCopyFile(srcPath, destPath, file.desc, overwrite);
85
- });
82
+ const srcPath = path.join(paths.templateDir, file.src)
83
+ const destPath = path.join(projectPath, file.dest)
84
+ safeCopyFile(srcPath, destPath, file.desc, overwrite)
85
+ })
86
86
  }
87
87
 
88
88
  function copyBundleFiles(projectPath, paths, overwrite = false) {
@@ -112,6 +112,11 @@ function copyBundleFiles(projectPath, paths, overwrite = false) {
112
112
  dest: "app-manifest.json",
113
113
  desc: "app-manifest.json",
114
114
  },
115
+ {
116
+ src: "vite.extend.js",
117
+ dest: "vite.extend.js",
118
+ desc: "vite.extend.js (customize the Vite runtime config)",
119
+ },
115
120
  { src: "env.example", dest: ".env.example", desc: ".env.example" },
116
121
  { src: "gitignore", dest: ".gitignore", desc: ".gitignore" },
117
122
  {
@@ -140,14 +145,14 @@ function copyBundleFiles(projectPath, paths, overwrite = false) {
140
145
  dest: ".claude/settings.json",
141
146
  desc: "Claude Code MCP settings (GxP API server)",
142
147
  },
143
- ];
148
+ ]
144
149
 
145
150
  // Copy template files
146
151
  filesToCopy.forEach((file) => {
147
- const srcPath = path.join(paths.templateDir, file.src);
148
- const destPath = path.join(projectPath, file.dest);
149
- safeCopyFile(srcPath, destPath, file.desc, overwrite);
150
- });
152
+ const srcPath = path.join(paths.templateDir, file.src)
153
+ const destPath = path.join(projectPath, file.dest)
154
+ safeCopyFile(srcPath, destPath, file.desc, overwrite)
155
+ })
151
156
  }
152
157
  /**
153
158
  * Copy extension scripts to project
@@ -156,47 +161,57 @@ function copyBundleFiles(projectPath, paths, overwrite = false) {
156
161
  * @param {boolean} overwrite - If true, overwrite existing files
157
162
  */
158
163
  function copyExtensionScripts(projectPath, paths, overwrite = false) {
159
- const scriptsDir = path.join(projectPath, "scripts");
164
+ const scriptsDir = path.join(projectPath, "scripts")
160
165
  if (!fs.existsSync(scriptsDir)) {
161
- fs.mkdirSync(scriptsDir, { recursive: true });
166
+ fs.mkdirSync(scriptsDir, { recursive: true })
162
167
  }
163
168
 
164
169
  // Copy launch-chrome.js script
165
170
  const launchChromeSource = path.join(
166
171
  paths.templateDir,
167
- "../scripts/launch-chrome.js"
168
- );
169
- const launchChromeDest = path.join(scriptsDir, "launch-chrome.js");
172
+ "../scripts/launch-chrome.js",
173
+ )
174
+ const launchChromeDest = path.join(scriptsDir, "launch-chrome.js")
170
175
  if (fs.existsSync(launchChromeSource)) {
171
- safeCopyFile(launchChromeSource, launchChromeDest, "Chrome launcher script", overwrite);
176
+ safeCopyFile(
177
+ launchChromeSource,
178
+ launchChromeDest,
179
+ "Chrome launcher script",
180
+ overwrite,
181
+ )
172
182
  }
173
183
 
174
184
  // Copy pack-chrome.js script
175
185
  const packChromeSource = path.join(
176
186
  paths.templateDir,
177
- "../scripts/pack-chrome.js"
178
- );
179
- const packChromeDest = path.join(scriptsDir, "pack-chrome.js");
187
+ "../scripts/pack-chrome.js",
188
+ )
189
+ const packChromeDest = path.join(scriptsDir, "pack-chrome.js")
180
190
  if (fs.existsSync(packChromeSource)) {
181
- safeCopyFile(packChromeSource, packChromeDest, "Chrome packaging script", overwrite);
191
+ safeCopyFile(
192
+ packChromeSource,
193
+ packChromeDest,
194
+ "Chrome packaging script",
195
+ overwrite,
196
+ )
182
197
  }
183
198
 
184
199
  // Copy socket events directory
185
- const socketEventsSource = paths.socketEventsDir;
186
- const socketEventsDest = path.join(projectPath, "socket-events");
200
+ const socketEventsSource = paths.socketEventsDir
201
+ const socketEventsDest = path.join(projectPath, "socket-events")
187
202
  if (fs.existsSync(socketEventsSource)) {
188
203
  if (!fs.existsSync(socketEventsDest)) {
189
- fs.mkdirSync(socketEventsDest, { recursive: true });
204
+ fs.mkdirSync(socketEventsDest, { recursive: true })
190
205
  }
191
206
 
192
207
  const eventFiles = fs
193
208
  .readdirSync(socketEventsSource)
194
- .filter((file) => file.endsWith(".json"));
209
+ .filter((file) => file.endsWith(".json"))
195
210
  eventFiles.forEach((file) => {
196
- const srcPath = path.join(socketEventsSource, file);
197
- const destPath = path.join(socketEventsDest, file);
198
- safeCopyFile(srcPath, destPath, `Socket event: ${file}`, overwrite);
199
- });
211
+ const srcPath = path.join(socketEventsSource, file)
212
+ const destPath = path.join(socketEventsDest, file)
213
+ safeCopyFile(srcPath, destPath, `Socket event: ${file}`, overwrite)
214
+ })
200
215
  }
201
216
  }
202
217
 
@@ -206,19 +221,19 @@ function copyExtensionScripts(projectPath, paths, overwrite = false) {
206
221
  */
207
222
  function createSupportingFiles(projectPath) {
208
223
  // Create /src/assets/ directory
209
- const assetsDir = path.join(projectPath, "src", "assets");
224
+ const assetsDir = path.join(projectPath, "src", "assets")
210
225
  if (!fs.existsSync(assetsDir)) {
211
- fs.mkdirSync(assetsDir, { recursive: true });
212
- fs.writeFileSync(path.join(assetsDir, ".gitkeep"), "");
213
- console.log("āœ“ Created src/assets/ directory for project assets");
226
+ fs.mkdirSync(assetsDir, { recursive: true })
227
+ fs.writeFileSync(path.join(assetsDir, ".gitkeep"), "")
228
+ console.log("āœ“ Created src/assets/ directory for project assets")
214
229
  }
215
230
 
216
231
  // Create .env file from .env.example
217
- const envExamplePath = path.join(projectPath, ".env.example");
218
- const envPath = path.join(projectPath, ".env");
232
+ const envExamplePath = path.join(projectPath, ".env.example")
233
+ const envPath = path.join(projectPath, ".env")
219
234
  if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) {
220
- fs.copyFileSync(envExamplePath, envPath);
221
- console.log("āœ“ Created .env file from .env.example");
235
+ fs.copyFileSync(envExamplePath, envPath)
236
+ console.log("āœ“ Created .env file from .env.example")
222
237
  }
223
238
  }
224
239
 
@@ -228,15 +243,15 @@ function createSupportingFiles(projectPath) {
228
243
  * @returns {object} - { name, description }
229
244
  */
230
245
  function readProjectInfo(projectPath) {
231
- const packageJsonPath = path.join(projectPath, "package.json");
246
+ const packageJsonPath = path.join(projectPath, "package.json")
232
247
  if (fs.existsSync(packageJsonPath)) {
233
- const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
248
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
234
249
  return {
235
250
  name: pkg.name || "",
236
251
  description: pkg.description || "",
237
- };
252
+ }
238
253
  }
239
- return { name: "", description: "" };
254
+ return { name: "", description: "" }
240
255
  }
241
256
 
242
257
  /**
@@ -246,12 +261,12 @@ function readProjectInfo(projectPath) {
246
261
  * @param {string} description - New description
247
262
  */
248
263
  function updatePackageJson(projectPath, name, description) {
249
- const packageJsonPath = path.join(projectPath, "package.json");
264
+ const packageJsonPath = path.join(projectPath, "package.json")
250
265
  if (fs.existsSync(packageJsonPath)) {
251
- const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
252
- pkg.name = name;
253
- pkg.description = description;
254
- fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, "\t"));
266
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
267
+ pkg.name = name
268
+ pkg.description = description
269
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, "\t"))
255
270
  }
256
271
  }
257
272
 
@@ -262,24 +277,24 @@ function updatePackageJson(projectPath, name, description) {
262
277
  * @returns {ChildProcess} - The spawned process
263
278
  */
264
279
  function launchDevServer(projectPath, options = {}) {
265
- const args = ["run"];
280
+ const args = ["run"]
266
281
 
267
282
  if (options.withMock) {
268
- args.push("dev");
283
+ args.push("dev")
269
284
  // The dev script with mock runs through TUI
270
285
  } else {
271
- args.push(options.noHttps ? "dev-http" : "dev");
286
+ args.push(options.noHttps ? "dev-http" : "dev")
272
287
  }
273
288
 
274
- console.log(`\nšŸš€ Starting development server...`);
289
+ console.log(`\nšŸš€ Starting development server...`)
275
290
 
276
291
  const child = spawn("npm", args, {
277
292
  cwd: projectPath,
278
293
  stdio: "inherit",
279
294
  shell: true,
280
- });
295
+ })
281
296
 
282
- return child;
297
+ return child
283
298
  }
284
299
 
285
300
  /**
@@ -288,16 +303,16 @@ function launchDevServer(projectPath, options = {}) {
288
303
  * @param {string} browser - 'chrome' or 'firefox'
289
304
  */
290
305
  function launchBrowserExtension(projectPath, browser) {
291
- console.log(`\n🌐 Launching ${browser} with GxP extension...`);
306
+ console.log(`\n🌐 Launching ${browser} with GxP extension...`)
292
307
 
293
- const gxdevPath = path.join(__dirname, "..", "..", "gx-devtools.js");
308
+ const gxdevPath = path.join(__dirname, "..", "..", "gx-devtools.js")
294
309
 
295
310
  spawn("node", [gxdevPath, `ext:${browser}`], {
296
311
  cwd: projectPath,
297
312
  stdio: "inherit",
298
313
  shell: true,
299
314
  detached: true,
300
- }).unref();
315
+ }).unref()
301
316
  }
302
317
 
303
318
  /**
@@ -307,183 +322,258 @@ function launchBrowserExtension(projectPath, browser) {
307
322
  * @param {boolean} isLocal - Whether initialized in current directory
308
323
  */
309
324
  async function runInteractiveConfig(projectPath, initialName, isLocal = false) {
310
- console.log("");
311
- console.log("─".repeat(50));
312
- console.log("šŸ“ Configure Your Plugin");
313
- console.log("─".repeat(50));
325
+ console.log("")
326
+ console.log("─".repeat(50))
327
+ console.log("šŸ“ Configure Your Plugin")
328
+ console.log("─".repeat(50))
314
329
 
315
330
  // Read current values from package.json
316
- const projectInfo = readProjectInfo(projectPath);
317
- const defaultName = projectInfo.name || initialName || path.basename(projectPath);
318
- const defaultDescription = projectInfo.description || "A GxP kiosk plugin";
331
+ const projectInfo = readProjectInfo(projectPath)
332
+ const defaultName =
333
+ projectInfo.name || initialName || path.basename(projectPath)
334
+ const defaultDescription = projectInfo.description || "A GxP plugin"
319
335
 
320
336
  // 1. App Name - with prepopulated value and custom option
321
337
  const appName = await arrowSelectPrompt("App name", [
322
- { label: defaultName, value: defaultName, description: "From package.json" },
323
- { label: "Enter custom name", value: "__custom__", isCustomInput: true, defaultValue: defaultName },
324
- ]);
338
+ {
339
+ label: defaultName,
340
+ value: defaultName,
341
+ description: "From package.json",
342
+ },
343
+ {
344
+ label: "Enter custom name",
345
+ value: "__custom__",
346
+ isCustomInput: true,
347
+ defaultValue: defaultName,
348
+ },
349
+ ])
325
350
 
326
351
  // 2. Description - with prepopulated value and custom option
327
352
  const description = await arrowSelectPrompt("Description", [
328
- { label: defaultDescription, value: defaultDescription, description: "From package.json" },
329
- { label: "Enter custom description", value: "__custom__", isCustomInput: true, defaultValue: "" },
330
- ]);
353
+ {
354
+ label: defaultDescription,
355
+ value: defaultDescription,
356
+ description: "From package.json",
357
+ },
358
+ {
359
+ label: "Enter custom description",
360
+ value: "__custom__",
361
+ isCustomInput: true,
362
+ defaultValue: "",
363
+ },
364
+ ])
331
365
 
332
366
  // Update package.json and app-manifest with new values
333
- updatePackageJson(projectPath, appName, description);
334
- updateAppManifest(projectPath, appName, description);
367
+ updatePackageJson(projectPath, appName, description)
368
+ updateAppManifest(projectPath, appName, description)
335
369
 
336
370
  // 3. AI Scaffolding
337
- console.log("");
338
- console.log("─".repeat(50));
339
- console.log("šŸ¤– AI-Powered Scaffolding");
340
- console.log("─".repeat(50));
341
- console.log(" Describe what you want to build and AI will generate");
342
- console.log(" starter components, views, and manifest configuration.");
343
- console.log("");
371
+ console.log("")
372
+ console.log("─".repeat(50))
373
+ console.log("šŸ¤– AI-Powered Scaffolding")
374
+ console.log("─".repeat(50))
375
+ console.log(" Describe what you want to build and AI will generate")
376
+ console.log(" starter components, views, and manifest configuration.")
377
+ console.log("")
344
378
 
345
379
  // Check available AI providers
346
- const providers = await getAvailableProviders();
347
- const availableProviders = providers.filter((p) => p.available);
380
+ const providers = await getAvailableProviders()
381
+ const availableProviders = providers.filter((p) => p.available)
348
382
 
349
- let aiChoice = "skip";
350
- let selectedProvider = null;
383
+ let aiChoice = "skip"
384
+ let selectedProvider = null
351
385
 
352
386
  if (availableProviders.length === 0) {
353
- console.log(" āš ļø No AI providers available.");
354
- console.log(" To enable AI scaffolding, set up one of:");
355
- console.log(" • Claude CLI: npm install -g @anthropic-ai/claude-code && claude login");
356
- console.log(" • Codex CLI: npm install -g @openai/codex && codex auth");
357
- console.log(" • Gemini CLI: npm install -g @google/gemini-cli && gemini");
358
- console.log(" • Gemini API: export GEMINI_API_KEY=your_key");
359
- console.log("");
360
- aiChoice = "skip";
387
+ console.log(" āš ļø No AI providers available.")
388
+ console.log(" To enable AI scaffolding, set up one of:")
389
+ console.log(
390
+ " • Claude CLI: npm install -g @anthropic-ai/claude-code && claude login",
391
+ )
392
+ console.log(" • Codex CLI: npm install -g @openai/codex && codex auth")
393
+ console.log(" • Gemini CLI: npm install -g @google/gemini-cli && gemini")
394
+ console.log(" • Gemini API: export GEMINI_API_KEY=your_key")
395
+ console.log("")
396
+ aiChoice = "skip"
361
397
  } else {
362
398
  // Build provider options
363
- const providerOptions = [
364
- { label: "Skip AI scaffolding", value: "skip" },
365
- ];
399
+ const providerOptions = [{ label: "Skip AI scaffolding", value: "skip" }]
366
400
 
367
401
  for (const provider of availableProviders) {
368
- let authInfo = "";
402
+ let authInfo = ""
369
403
  if (provider.id === "gemini") {
370
404
  switch (provider.method) {
371
405
  case "cli":
372
- authInfo = "logged in";
373
- break;
406
+ authInfo = "logged in"
407
+ break
374
408
  case "api_key":
375
- authInfo = "via API key";
376
- break;
409
+ authInfo = "via API key"
410
+ break
377
411
  case "gcloud":
378
- authInfo = "via gcloud";
379
- break;
412
+ authInfo = "via gcloud"
413
+ break
380
414
  default:
381
- authInfo = "";
415
+ authInfo = ""
382
416
  }
383
417
  } else {
384
- authInfo = "logged in";
418
+ authInfo = "logged in"
385
419
  }
386
420
  providerOptions.push({
387
421
  label: `${provider.name}`,
388
422
  value: provider.id,
389
423
  description: `${authInfo}`,
390
- });
424
+ })
391
425
  }
392
426
 
393
- aiChoice = await arrowSelectPrompt("Choose AI provider for scaffolding", providerOptions);
427
+ aiChoice = await arrowSelectPrompt(
428
+ "Choose AI provider for scaffolding",
429
+ providerOptions,
430
+ )
394
431
  if (aiChoice !== "skip") {
395
- selectedProvider = aiChoice;
432
+ selectedProvider = aiChoice
396
433
  }
397
434
  }
398
435
 
399
- let buildPrompt = "";
436
+ let buildPrompt = ""
400
437
  if (selectedProvider) {
401
438
  buildPrompt = await multiLinePrompt(
402
439
  "šŸ“ Describe your plugin (what it does, key features, UI elements):",
403
- "Press Enter twice when done"
404
- );
440
+ "Press Enter twice when done",
441
+ )
405
442
 
406
443
  if (buildPrompt) {
407
- await runAIScaffolding(projectPath, appName, description, buildPrompt, selectedProvider);
444
+ await runAIScaffolding(
445
+ projectPath,
446
+ appName,
447
+ description,
448
+ buildPrompt,
449
+ selectedProvider,
450
+ )
408
451
  }
409
452
  }
410
453
 
411
454
  // 4. SSL Setup
412
- console.log("");
413
- console.log("─".repeat(50));
414
- console.log("šŸ”’ SSL Configuration");
415
- console.log("─".repeat(50));
416
-
417
- const sslChoice = await arrowSelectPrompt("Set up SSL certificates for HTTPS development?", [
418
- { label: "Yes, set up SSL", value: "yes", description: "Recommended for full feature access" },
419
- { label: "Skip SSL setup", value: "no", description: "Can be set up later with npm run setup-ssl" },
420
- ]);
421
-
422
- let sslSetup = false;
455
+ console.log("")
456
+ console.log("─".repeat(50))
457
+ console.log("šŸ”’ SSL Configuration")
458
+ console.log("─".repeat(50))
459
+
460
+ const sslChoice = await arrowSelectPrompt(
461
+ "Set up SSL certificates for HTTPS development?",
462
+ [
463
+ {
464
+ label: "Yes, set up SSL",
465
+ value: "yes",
466
+ description: "Recommended for full feature access",
467
+ },
468
+ {
469
+ label: "Skip SSL setup",
470
+ value: "no",
471
+ description: "Can be set up later with npm run setup-ssl",
472
+ },
473
+ ],
474
+ )
475
+
476
+ let sslSetup = false
423
477
  if (sslChoice === "yes") {
424
- console.log("\nšŸ”’ Setting up HTTPS development environment...");
425
- ensureMkcertInstalled();
426
- const certs = generateSSLCertificates(projectPath);
478
+ console.log("\nšŸ”’ Setting up HTTPS development environment...")
479
+ ensureMkcertInstalled()
480
+ const certs = generateSSLCertificates(projectPath)
427
481
  if (certs) {
428
- updateEnvWithCertPaths(projectPath, certs);
429
- sslSetup = true;
482
+ updateEnvWithCertPaths(projectPath, certs)
483
+ sslSetup = true
430
484
  }
431
485
  }
432
486
 
433
487
  // 5. Start App
434
- console.log("");
435
- console.log("─".repeat(50));
436
- console.log("šŸš€ Start Development");
437
- console.log("─".repeat(50));
488
+ console.log("")
489
+ console.log("─".repeat(50))
490
+ console.log("šŸš€ Start Development")
491
+ console.log("─".repeat(50))
438
492
 
439
493
  const startOptions = [
440
- { label: "Start app", value: "start", description: sslSetup ? "HTTPS dev server" : "HTTP dev server" },
441
- { label: "Start app with Mock API", value: "start-mock", description: "Dev server + Socket.IO + Mock API" },
494
+ {
495
+ label: "Start app",
496
+ value: "start",
497
+ description: sslSetup ? "HTTPS dev server" : "HTTP dev server",
498
+ },
499
+ {
500
+ label: "Start app with Mock API",
501
+ value: "start-mock",
502
+ description: "Dev server + Socket.IO + Mock API",
503
+ },
442
504
  { label: "Skip", value: "skip" },
443
- ];
505
+ ]
444
506
 
445
- const startChoice = await arrowSelectPrompt("How would you like to start the development server?", startOptions);
507
+ const startChoice = await arrowSelectPrompt(
508
+ "How would you like to start the development server?",
509
+ startOptions,
510
+ )
446
511
 
447
- let devProcess = null;
512
+ let devProcess = null
448
513
  if (startChoice === "start") {
449
514
  // 6. Browser Extension (only if starting)
450
- console.log("");
451
- const browserChoice = await arrowSelectPrompt("Launch browser with GxP extension?", [
452
- { label: "Chrome", value: "chrome", description: "Launch Chrome with DevTools panel" },
453
- { label: "Firefox", value: "firefox", description: "Launch Firefox with DevTools panel" },
454
- { label: "Skip", value: "skip" },
455
- ]);
515
+ console.log("")
516
+ const browserChoice = await arrowSelectPrompt(
517
+ "Launch browser with GxP extension?",
518
+ [
519
+ {
520
+ label: "Chrome",
521
+ value: "chrome",
522
+ description: "Launch Chrome with DevTools panel",
523
+ },
524
+ {
525
+ label: "Firefox",
526
+ value: "firefox",
527
+ description: "Launch Firefox with DevTools panel",
528
+ },
529
+ { label: "Skip", value: "skip" },
530
+ ],
531
+ )
456
532
 
457
533
  if (browserChoice !== "skip") {
458
534
  // Launch browser first (it will connect when server starts)
459
535
  setTimeout(() => {
460
- launchBrowserExtension(projectPath, browserChoice);
461
- }, 3000); // Wait a bit for server to start
536
+ launchBrowserExtension(projectPath, browserChoice)
537
+ }, 3000) // Wait a bit for server to start
462
538
  }
463
539
 
464
- devProcess = launchDevServer(projectPath, { noHttps: !sslSetup });
540
+ devProcess = launchDevServer(projectPath, { noHttps: !sslSetup })
465
541
  } else if (startChoice === "start-mock") {
466
542
  // 6. Browser Extension (only if starting)
467
- console.log("");
468
- const browserChoice = await arrowSelectPrompt("Launch browser with GxP extension?", [
469
- { label: "Chrome", value: "chrome", description: "Launch Chrome with DevTools panel" },
470
- { label: "Firefox", value: "firefox", description: "Launch Firefox with DevTools panel" },
471
- { label: "Skip", value: "skip" },
472
- ]);
543
+ console.log("")
544
+ const browserChoice = await arrowSelectPrompt(
545
+ "Launch browser with GxP extension?",
546
+ [
547
+ {
548
+ label: "Chrome",
549
+ value: "chrome",
550
+ description: "Launch Chrome with DevTools panel",
551
+ },
552
+ {
553
+ label: "Firefox",
554
+ value: "firefox",
555
+ description: "Launch Firefox with DevTools panel",
556
+ },
557
+ { label: "Skip", value: "skip" },
558
+ ],
559
+ )
473
560
 
474
561
  if (browserChoice !== "skip") {
475
562
  setTimeout(() => {
476
- launchBrowserExtension(projectPath, browserChoice);
477
- }, 3000);
563
+ launchBrowserExtension(projectPath, browserChoice)
564
+ }, 3000)
478
565
  }
479
566
 
480
- devProcess = launchDevServer(projectPath, { withMock: true, noHttps: !sslSetup });
567
+ devProcess = launchDevServer(projectPath, {
568
+ withMock: true,
569
+ noHttps: !sslSetup,
570
+ })
481
571
  } else {
482
572
  // Print final instructions
483
- printFinalInstructions(projectPath, appName, sslSetup, isLocal);
573
+ printFinalInstructions(projectPath, appName, sslSetup, isLocal)
484
574
  }
485
575
 
486
- return devProcess;
576
+ return devProcess
487
577
  }
488
578
 
489
579
  /**
@@ -493,149 +583,161 @@ async function runInteractiveConfig(projectPath, initialName, isLocal = false) {
493
583
  * @param {boolean} sslSetup - Whether SSL was set up
494
584
  * @param {boolean} isLocal - Whether initialized in current directory
495
585
  */
496
- function printFinalInstructions(projectPath, projectName, sslSetup, isLocal = false) {
497
- console.log("");
498
- console.log("─".repeat(50));
499
- console.log("āœ… Project setup complete!");
500
- console.log("─".repeat(50));
501
- console.log("");
502
- console.log("šŸŽØ GX ComponentKit component library included!");
503
- console.log("šŸ—ƒļø GxP Datastore included with Pinia integration!");
504
- console.log("");
505
- console.log(`šŸ“ Project location: ${projectPath}`);
506
- console.log("");
507
- console.log("šŸ“– Project structure:");
508
- console.log(" • src/Plugin.vue - Your app entry point (customize this!)");
509
- console.log(" • src/DemoPage.vue - Example component");
510
- console.log(" • theme-layouts/ - Customizable layout templates");
511
- console.log(" • app-manifest.json - Plugin configuration");
512
- console.log("");
513
- console.log("šŸš€ To start development:");
586
+ function printFinalInstructions(
587
+ projectPath,
588
+ projectName,
589
+ sslSetup,
590
+ isLocal = false,
591
+ ) {
592
+ console.log("")
593
+ console.log("─".repeat(50))
594
+ console.log("āœ… Project setup complete!")
595
+ console.log("─".repeat(50))
596
+ console.log("")
597
+ console.log("šŸŽØ GX ComponentKit component library included!")
598
+ console.log("šŸ—ƒļø GxP Datastore included with Pinia integration!")
599
+ console.log("")
600
+ console.log(`šŸ“ Project location: ${projectPath}`)
601
+ console.log("")
602
+ console.log("šŸ“– Project structure:")
603
+ console.log(" • src/Plugin.vue - Your app entry point (customize this!)")
604
+ console.log(" • src/DemoPage.vue - Example component")
605
+ console.log(" • theme-layouts/ - Customizable layout templates")
606
+ console.log(" • app-manifest.json - Plugin configuration")
607
+ console.log("")
608
+ console.log("šŸš€ To start development:")
514
609
  if (!isLocal) {
515
- console.log(` cd ${projectName}`);
610
+ console.log(` cd ${projectName}`)
516
611
  }
517
612
  if (sslSetup) {
518
- console.log(" npm run dev # HTTPS with TUI");
519
- console.log(" npm run dev-http # HTTP only");
613
+ console.log(" npm run dev # HTTPS with TUI")
614
+ console.log(" npm run dev-http # HTTP only")
520
615
  } else {
521
- console.log(" npm run dev-http # HTTP dev server");
522
- console.log(" npm run setup-ssl # Then npm run dev for HTTPS");
616
+ console.log(" npm run dev-http # HTTP dev server")
617
+ console.log(" npm run setup-ssl # Then npm run dev for HTTPS")
523
618
  }
524
- console.log("");
525
- console.log("šŸ“š Documentation: https://docs.gramercytech.com/gxp-toolkit");
526
- console.log("");
619
+ console.log("")
620
+ console.log("šŸ“š Documentation: https://docs.gramercytech.com/gxp-toolkit")
621
+ console.log("")
527
622
  }
528
623
 
529
624
  /**
530
625
  * Initialize command - sets up a new GxP project or updates existing one
531
626
  */
532
627
  async function initCommand(argv) {
533
- const currentDir = process.cwd();
534
- const hasPackageJson = fs.existsSync(path.join(currentDir, "package.json"));
535
- let projectPath = currentDir;
536
- let projectName;
628
+ const currentDir = process.cwd()
629
+ const hasPackageJson = fs.existsSync(path.join(currentDir, "package.json"))
630
+ let projectPath = currentDir
631
+ let projectName
537
632
 
538
- const overwrite = argv.local && argv.yes;
633
+ const overwrite = argv.local && argv.yes
539
634
  // Copy template files
540
- const paths = resolveGxPaths();
635
+ const paths = resolveGxPaths()
541
636
 
542
637
  // Handle --local flag: initialize in current directory
543
638
  if (argv.local) {
544
- projectPath = currentDir;
545
- projectName = argv.name || path.basename(currentDir);
639
+ projectPath = currentDir
640
+ projectName = argv.name || path.basename(currentDir)
546
641
 
547
- console.log("");
548
- console.log(`šŸ“ Initializing project in current directory: ${projectName}`);
642
+ console.log("")
643
+ console.log(`šŸ“ Initializing project in current directory: ${projectName}`)
549
644
  if (overwrite) {
550
- console.log("āš ļø Overwrite mode enabled - existing files will be replaced");
645
+ console.log(
646
+ "āš ļø Overwrite mode enabled - existing files will be replaced",
647
+ )
551
648
  }
552
- console.log("─".repeat(40));
649
+ console.log("─".repeat(40))
553
650
  } else {
554
651
  // Handle existing project update
555
652
  if (hasPackageJson && !argv.name) {
556
- console.log("Updating existing project...");
557
- updateExistingProject(projectPath);
558
- copyBundleFiles(projectPath, paths, false);
559
- console.log("āœ… Project updated!");
560
- return;
653
+ console.log("Updating existing project...")
654
+ updateExistingProject(projectPath)
655
+ copyBundleFiles(projectPath, paths, false)
656
+ console.log("āœ… Project updated!")
657
+ return
561
658
  }
562
659
 
563
660
  // New project - require a name
564
661
  if (!argv.name) {
565
662
  // In non-interactive mode, name is required
566
663
  if (argv.yes) {
567
- console.error("āŒ Project name is required when using --yes flag!");
568
- console.error(" Usage: gxdev init <project-name> --yes");
569
- process.exit(1);
664
+ console.error("āŒ Project name is required when using --yes flag!")
665
+ console.error(" Usage: gxdev init <project-name> --yes")
666
+ process.exit(1)
570
667
  }
571
- console.log("");
572
- console.log("šŸš€ GxP Plugin Creator");
573
- console.log("─".repeat(40));
574
- console.log("");
575
- projectName = await promptUser("šŸ“ Project name: ");
668
+ console.log("")
669
+ console.log("šŸš€ GxP Plugin Creator")
670
+ console.log("─".repeat(40))
671
+ console.log("")
672
+ projectName = await promptUser("šŸ“ Project name: ")
576
673
  if (!projectName) {
577
- console.error("āŒ Project name is required!");
578
- process.exit(1);
674
+ console.error("āŒ Project name is required!")
675
+ process.exit(1)
579
676
  }
580
677
  } else {
581
- projectName = argv.name;
678
+ projectName = argv.name
582
679
  }
583
680
 
584
681
  // Create project directory
585
- projectPath = path.join(currentDir, projectName);
682
+ projectPath = path.join(currentDir, projectName)
586
683
  if (fs.existsSync(projectPath)) {
587
- console.error(`\nāŒ Directory ${projectName} already exists!`);
588
- process.exit(1);
684
+ console.error(`\nāŒ Directory ${projectName} already exists!`)
685
+ process.exit(1)
589
686
  }
590
687
 
591
- console.log("");
592
- console.log(`šŸ“ Creating project: ${projectName}`);
593
- console.log("─".repeat(40));
594
- fs.mkdirSync(projectPath, { recursive: true });
688
+ console.log("")
689
+ console.log(`šŸ“ Creating project: ${projectName}`)
690
+ console.log("─".repeat(40))
691
+ fs.mkdirSync(projectPath, { recursive: true })
595
692
  }
596
693
 
597
694
  // Create package.json (only if it doesn't exist or overwrite is enabled)
598
- const initialDescription = argv.description || "A GxP kiosk plugin";
599
- const packageJsonPath = path.join(projectPath, "package.json");
695
+ const initialDescription = argv.description || "A GxP plugin"
696
+ const packageJsonPath = path.join(projectPath, "package.json")
600
697
  if (!fs.existsSync(packageJsonPath) || overwrite) {
601
- createPackageJson(projectPath, projectName, initialDescription);
698
+ createPackageJson(projectPath, projectName, initialDescription)
602
699
  } else {
603
- console.log("ā­ļø Skipping package.json (already exists)");
700
+ console.log("ā­ļø Skipping package.json (already exists)")
604
701
  }
605
702
 
606
-
607
- copyTemplateFiles(projectPath, paths, overwrite);
608
- copyBundleFiles(projectPath, paths, overwrite);
609
- copyExtensionScripts(projectPath, paths, overwrite);
610
- createSupportingFiles(projectPath);
703
+ copyTemplateFiles(projectPath, paths, overwrite)
704
+ copyBundleFiles(projectPath, paths, overwrite)
705
+ copyExtensionScripts(projectPath, paths, overwrite)
706
+ createSupportingFiles(projectPath)
611
707
 
612
708
  // Install dependencies
613
- console.log("");
614
- installDependencies(projectPath);
709
+ console.log("")
710
+ installDependencies(projectPath)
615
711
 
616
712
  // Change to project directory
617
- process.chdir(projectPath);
713
+ process.chdir(projectPath)
618
714
 
619
715
  // If CLI provided build prompt, skip interactive and just run AI
620
716
  if (argv.build) {
621
- updateAppManifest(projectPath, projectName, initialDescription);
622
- const provider = argv.provider || "gemini"; // Default to gemini for backward compatibility
623
- await runAIScaffolding(projectPath, projectName, initialDescription, argv.build, provider);
624
- printFinalInstructions(projectPath, projectName, false, argv.local);
625
- return;
717
+ updateAppManifest(projectPath, projectName, initialDescription)
718
+ const provider = argv.provider || "gemini" // Default to gemini for backward compatibility
719
+ await runAIScaffolding(
720
+ projectPath,
721
+ projectName,
722
+ initialDescription,
723
+ argv.build,
724
+ provider,
725
+ )
726
+ printFinalInstructions(projectPath, projectName, false, argv.local)
727
+ return
626
728
  }
627
729
 
628
730
  // If --yes flag provided, skip interactive configuration
629
731
  if (argv.yes) {
630
- updateAppManifest(projectPath, projectName, initialDescription);
631
- printFinalInstructions(projectPath, projectName, false, argv.local);
632
- return;
732
+ updateAppManifest(projectPath, projectName, initialDescription)
733
+ printFinalInstructions(projectPath, projectName, false, argv.local)
734
+ return
633
735
  }
634
736
 
635
737
  // Run interactive configuration
636
- await runInteractiveConfig(projectPath, projectName, argv.local);
738
+ await runInteractiveConfig(projectPath, projectName, argv.local)
637
739
  }
638
740
 
639
741
  module.exports = {
640
742
  initCommand,
641
- };
743
+ }