@gxp-dev/tools 2.0.63 → 2.0.65

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
@@ -4,11 +4,11 @@
4
4
  * Builds the plugin for production and packages it as a .gxp file.
5
5
  */
6
6
 
7
- const path = require("path");
8
- const fs = require("fs");
9
- const shell = require("shelljs");
10
- const archiver = require("archiver");
11
- const { findProjectRoot, resolveGxPaths } = require("../utils");
7
+ const path = require("path")
8
+ const fs = require("fs")
9
+ const shell = require("shelljs")
10
+ const AdmZip = require("adm-zip")
11
+ const { findProjectRoot, resolveGxPaths } = require("../utils")
12
12
 
13
13
  /**
14
14
  * Get the plugin name from app-manifest.json (preferred) or package.json
@@ -16,32 +16,34 @@ const { findProjectRoot, resolveGxPaths } = require("../utils");
16
16
  function getPluginName(projectPath) {
17
17
  // Check app-manifest.json first
18
18
  try {
19
- const manifestPath = path.join(projectPath, "app-manifest.json");
19
+ const manifestPath = path.join(projectPath, "app-manifest.json")
20
20
  if (fs.existsSync(manifestPath)) {
21
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
21
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"))
22
22
  if (manifest.name) {
23
- return manifest.name.replace(/[^a-zA-Z0-9-_]/g, "-");
23
+ return manifest.name.replace(/[^a-zA-Z0-9-_]/g, "-")
24
24
  }
25
25
  }
26
26
  } catch (error) {
27
- console.warn("Could not read app-manifest.json, falling back to package.json");
27
+ console.warn(
28
+ "Could not read app-manifest.json, falling back to package.json",
29
+ )
28
30
  }
29
31
 
30
32
  // Fall back to package.json
31
33
  try {
32
- const packageJsonPath = path.join(projectPath, "package.json");
34
+ const packageJsonPath = path.join(projectPath, "package.json")
33
35
  if (fs.existsSync(packageJsonPath)) {
34
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
36
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
35
37
  // Clean the name for use as a filename
36
- const name = packageJson.name || "plugin";
38
+ const name = packageJson.name || "plugin"
37
39
  return name
38
40
  .replace(/^@[^/]+\//, "") // Remove scope like @company/
39
- .replace(/[^a-zA-Z0-9-_]/g, "-"); // Replace invalid chars with dash
41
+ .replace(/[^a-zA-Z0-9-_]/g, "-") // Replace invalid chars with dash
40
42
  }
41
43
  } catch (error) {
42
- console.warn("Could not read package.json, using default plugin name");
44
+ console.warn("Could not read package.json, using default plugin name")
43
45
  }
44
- return "plugin";
46
+ return "plugin"
45
47
  }
46
48
 
47
49
  /**
@@ -51,95 +53,99 @@ function getPluginName(projectPath) {
51
53
  * @param {string} outputPath - Path where .gxpapp file should be created (dist/)
52
54
  */
53
55
  async function packagePlugin(projectPath, buildPath, outputPath) {
54
- const pluginName = getPluginName(projectPath);
56
+ const pluginName = getPluginName(projectPath)
55
57
 
56
- console.log("\n📦 Packaging plugin...");
58
+ console.log("\n📦 Packaging plugin...")
57
59
 
58
60
  // Read app-manifest.json to get asset_dir
59
- const manifestPath = path.join(projectPath, "app-manifest.json");
60
- let assetDir = "/src/assets/"; // Default
61
+ const manifestPath = path.join(projectPath, "app-manifest.json")
62
+ let assetDir = "/src/assets/" // Default
61
63
 
62
64
  if (fs.existsSync(manifestPath)) {
63
65
  try {
64
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
66
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"))
65
67
  if (manifest.asset_dir) {
66
- assetDir = manifest.asset_dir;
68
+ assetDir = manifest.asset_dir
67
69
  }
68
70
  } catch (error) {
69
71
  console.warn(
70
- "⚠️ Could not parse app-manifest.json, using default asset_dir"
71
- );
72
+ "⚠️ Could not parse app-manifest.json, using default asset_dir",
73
+ )
72
74
  }
73
75
  } else {
74
- console.warn("⚠️ app-manifest.json not found");
76
+ console.warn("⚠️ app-manifest.json not found")
75
77
  }
76
78
 
77
79
  // Resolve asset directory path (remove leading slash for path.join)
78
- const assetDirClean = assetDir.replace(/^\//, "").replace(/\/$/, "");
79
- const assetSourcePath = path.join(projectPath, assetDirClean);
80
- const assetDestPath = path.join(buildPath, "assets");
80
+ const assetDirClean = assetDir.replace(/^\//, "").replace(/\/$/, "")
81
+ const assetSourcePath = path.join(projectPath, assetDirClean)
82
+ const assetDestPath = path.join(buildPath, "assets")
81
83
 
82
84
  // Copy assets to dist/build/assets
83
85
  if (fs.existsSync(assetSourcePath)) {
84
86
  console.log(
85
- `📂 Copying assets from ${assetDirClean}/ to dist/build/assets/`
86
- );
87
+ `📂 Copying assets from ${assetDirClean}/ to dist/build/assets/`,
88
+ )
87
89
 
88
90
  // Create assets directory in build
89
91
  if (!fs.existsSync(assetDestPath)) {
90
- fs.mkdirSync(assetDestPath, { recursive: true });
92
+ fs.mkdirSync(assetDestPath, { recursive: true })
91
93
  }
92
94
 
93
95
  // Copy all files from asset source to build/assets
94
- copyDirectorySync(assetSourcePath, assetDestPath);
95
- console.log("✓ Assets copied");
96
+ copyDirectorySync(assetSourcePath, assetDestPath)
97
+ console.log("✓ Assets copied")
96
98
  } else {
97
- console.log(`ℹ️ No assets directory found at ${assetDirClean}/`);
99
+ console.log(`ℹ️ No assets directory found at ${assetDirClean}/`)
98
100
  }
99
101
 
100
102
  // Process app-manifest.json for bundle
101
- let manifest = null;
103
+ let manifest = null
102
104
  if (fs.existsSync(manifestPath)) {
103
105
  // Parse manifest for optional bundle files
104
106
  try {
105
- manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
107
+ manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"))
106
108
  } catch (error) {
107
- console.warn("⚠️ Could not parse app-manifest.json");
109
+ console.warn("⚠️ Could not parse app-manifest.json")
108
110
  }
109
111
  }
110
112
 
111
113
  // Process optional bundle files (appInstructions, defaultStyling, configuration)
112
114
  if (manifest) {
113
- processOptionalBundleFiles(manifest, projectPath, buildPath);
115
+ processOptionalBundleFiles(manifest, projectPath, buildPath)
114
116
 
115
117
  // Create a clean copy of manifest without the optional file keys (to avoid duplication)
116
- const cleanedManifest = { ...manifest };
117
- delete cleanedManifest.appInstructionsFile;
118
- delete cleanedManifest.appInstructions;
119
- delete cleanedManifest.defaultStylingFile;
120
- delete cleanedManifest.defaultStyling;
121
- delete cleanedManifest.configurationFile;
122
- delete cleanedManifest.configuration;
118
+ const cleanedManifest = { ...manifest }
119
+ delete cleanedManifest.appInstructionsFile
120
+ delete cleanedManifest.appInstructions
121
+ delete cleanedManifest.defaultStylingFile
122
+ delete cleanedManifest.defaultStyling
123
+ delete cleanedManifest.configurationFile
124
+ delete cleanedManifest.configuration
123
125
 
124
126
  // Write cleaned manifest to dist/build/
125
- const manifestDestPath = path.join(buildPath, "app-manifest.json");
126
- fs.writeFileSync(manifestDestPath, JSON.stringify(cleanedManifest, null, 2), "utf-8");
127
- console.log("✓ app-manifest.json written to dist/build/ (cleaned)");
127
+ const manifestDestPath = path.join(buildPath, "app-manifest.json")
128
+ fs.writeFileSync(
129
+ manifestDestPath,
130
+ JSON.stringify(cleanedManifest, null, 2),
131
+ "utf-8",
132
+ )
133
+ console.log("✓ app-manifest.json written to dist/build/ (cleaned)")
128
134
  }
129
135
 
130
136
  // Create the .gxp package (zip file) in dist/
131
- const gxpFileName = `${pluginName}.gxpapp`;
132
- const gxpFilePath = path.join(outputPath, gxpFileName);
137
+ const gxpFileName = `${pluginName}.gxpapp`
138
+ const gxpFilePath = path.join(outputPath, gxpFileName)
133
139
 
134
- console.log(`📦 Creating ${gxpFileName}...`);
140
+ console.log(`📦 Creating ${gxpFileName}...`)
135
141
 
136
- await createGxpPackage(buildPath, gxpFilePath);
142
+ await createGxpPackage(buildPath, gxpFilePath)
137
143
 
138
- console.log(`\n✅ Plugin packaged successfully!`);
139
- console.log(`📁 Build files: dist/build/`);
140
- console.log(`📁 Package: dist/${gxpFileName}`);
144
+ console.log(`\n✅ Plugin packaged successfully!`)
145
+ console.log(`📁 Build files: dist/build/`)
146
+ console.log(`📁 Package: dist/${gxpFileName}`)
141
147
 
142
- return gxpFilePath;
148
+ return gxpFilePath
143
149
  }
144
150
 
145
151
  /**
@@ -152,58 +158,71 @@ function processOptionalBundleFiles(manifest, projectPath, buildPath) {
152
158
  // Handle appInstructions
153
159
  if (manifest.appInstructionsFile) {
154
160
  // Copy file from specified path
155
- const srcPath = path.join(projectPath, manifest.appInstructionsFile);
156
- const destPath = path.join(buildPath, "appInstructions.md");
161
+ const srcPath = path.join(projectPath, manifest.appInstructionsFile)
162
+ const destPath = path.join(buildPath, "appInstructions.md")
157
163
  if (fs.existsSync(srcPath)) {
158
- fs.copyFileSync(srcPath, destPath);
159
- console.log(`✓ appInstructions.md copied from ${manifest.appInstructionsFile}`);
164
+ fs.copyFileSync(srcPath, destPath)
165
+ console.log(
166
+ `✓ appInstructions.md copied from ${manifest.appInstructionsFile}`,
167
+ )
160
168
  } else {
161
- console.warn(`⚠️ appInstructionsFile not found: ${manifest.appInstructionsFile}`);
169
+ console.warn(
170
+ `⚠️ appInstructionsFile not found: ${manifest.appInstructionsFile}`,
171
+ )
162
172
  }
163
173
  } else if (manifest.appInstructions) {
164
174
  // Write text content to file
165
- const destPath = path.join(buildPath, "appInstructions.md");
166
- fs.writeFileSync(destPath, manifest.appInstructions, "utf-8");
167
- console.log("✓ appInstructions.md created from manifest text");
175
+ const destPath = path.join(buildPath, "appInstructions.md")
176
+ fs.writeFileSync(destPath, manifest.appInstructions, "utf-8")
177
+ console.log("✓ appInstructions.md created from manifest text")
168
178
  }
169
179
 
170
180
  // Handle defaultStyling
171
181
  if (manifest.defaultStylingFile) {
172
182
  // Copy file from specified path
173
- const srcPath = path.join(projectPath, manifest.defaultStylingFile);
174
- const destPath = path.join(buildPath, "default-styling.css");
183
+ const srcPath = path.join(projectPath, manifest.defaultStylingFile)
184
+ const destPath = path.join(buildPath, "default-styling.css")
175
185
  if (fs.existsSync(srcPath)) {
176
- fs.copyFileSync(srcPath, destPath);
177
- console.log(`✓ default-styling.css copied from ${manifest.defaultStylingFile}`);
186
+ fs.copyFileSync(srcPath, destPath)
187
+ console.log(
188
+ `✓ default-styling.css copied from ${manifest.defaultStylingFile}`,
189
+ )
178
190
  } else {
179
- console.warn(`⚠️ defaultStylingFile not found: ${manifest.defaultStylingFile}`);
191
+ console.warn(
192
+ `⚠️ defaultStylingFile not found: ${manifest.defaultStylingFile}`,
193
+ )
180
194
  }
181
195
  } else if (manifest.defaultStyling) {
182
196
  // Write text content to file
183
- const destPath = path.join(buildPath, "default-styling.css");
184
- fs.writeFileSync(destPath, manifest.defaultStyling, "utf-8");
185
- console.log("✓ default-styling.css created from manifest text");
197
+ const destPath = path.join(buildPath, "default-styling.css")
198
+ fs.writeFileSync(destPath, manifest.defaultStyling, "utf-8")
199
+ console.log("✓ default-styling.css created from manifest text")
186
200
  }
187
201
 
188
202
  // Handle configuration
189
203
  if (manifest.configurationFile) {
190
204
  // Copy file from specified path
191
- const srcPath = path.join(projectPath, manifest.configurationFile);
192
- const destPath = path.join(buildPath, "configuration.json");
205
+ const srcPath = path.join(projectPath, manifest.configurationFile)
206
+ const destPath = path.join(buildPath, "configuration.json")
193
207
  if (fs.existsSync(srcPath)) {
194
- fs.copyFileSync(srcPath, destPath);
195
- console.log(`✓ configuration.json copied from ${manifest.configurationFile}`);
208
+ fs.copyFileSync(srcPath, destPath)
209
+ console.log(
210
+ `✓ configuration.json copied from ${manifest.configurationFile}`,
211
+ )
196
212
  } else {
197
- console.warn(`⚠️ configurationFile not found: ${manifest.configurationFile}`);
213
+ console.warn(
214
+ `⚠️ configurationFile not found: ${manifest.configurationFile}`,
215
+ )
198
216
  }
199
217
  } else if (manifest.configuration) {
200
218
  // Write JSON content to file
201
- const destPath = path.join(buildPath, "configuration.json");
202
- const jsonContent = typeof manifest.configuration === "string"
203
- ? manifest.configuration
204
- : JSON.stringify(manifest.configuration, null, 2);
205
- fs.writeFileSync(destPath, jsonContent, "utf-8");
206
- console.log("✓ configuration.json created from manifest JSON");
219
+ const destPath = path.join(buildPath, "configuration.json")
220
+ const jsonContent =
221
+ typeof manifest.configuration === "string"
222
+ ? manifest.configuration
223
+ : JSON.stringify(manifest.configuration, null, 2)
224
+ fs.writeFileSync(destPath, jsonContent, "utf-8")
225
+ console.log("✓ configuration.json created from manifest JSON")
207
226
  }
208
227
  }
209
228
 
@@ -212,22 +231,22 @@ function processOptionalBundleFiles(manifest, projectPath, buildPath) {
212
231
  */
213
232
  function copyDirectorySync(src, dest) {
214
233
  if (!fs.existsSync(dest)) {
215
- fs.mkdirSync(dest, { recursive: true });
234
+ fs.mkdirSync(dest, { recursive: true })
216
235
  }
217
236
 
218
- const entries = fs.readdirSync(src, { withFileTypes: true });
237
+ const entries = fs.readdirSync(src, { withFileTypes: true })
219
238
 
220
239
  for (const entry of entries) {
221
- const srcPath = path.join(src, entry.name);
222
- const destPath = path.join(dest, entry.name);
240
+ const srcPath = path.join(src, entry.name)
241
+ const destPath = path.join(dest, entry.name)
223
242
 
224
243
  // Skip .gitkeep files
225
- if (entry.name === ".gitkeep") continue;
244
+ if (entry.name === ".gitkeep") continue
226
245
 
227
246
  if (entry.isDirectory()) {
228
- copyDirectorySync(srcPath, destPath);
247
+ copyDirectorySync(srcPath, destPath)
229
248
  } else {
230
- fs.copyFileSync(srcPath, destPath);
249
+ fs.copyFileSync(srcPath, destPath)
231
250
  }
232
251
  }
233
252
  }
@@ -235,117 +254,93 @@ function copyDirectorySync(src, dest) {
235
254
  /**
236
255
  * Create the .gxp package (zip file containing plugin files)
237
256
  */
238
- function createGxpPackage(distPath, outputPath) {
239
- return new Promise((resolve, reject) => {
240
- const output = fs.createWriteStream(outputPath);
241
- const archive = archiver("zip", {
242
- zlib: { level: 9 }, // Maximum compression
243
- });
244
-
245
- output.on("close", () => {
246
- const sizeKB = (archive.pointer() / 1024).toFixed(2);
247
- console.log(`✓ Package created (${sizeKB} KB)`);
248
- resolve();
249
- });
250
-
251
- archive.on("error", (err) => {
252
- reject(err);
253
- });
254
-
255
- archive.pipe(output);
256
-
257
- // Add all JS files from dist
258
- const jsFiles = fs.readdirSync(distPath).filter((f) => f.endsWith(".js"));
259
- jsFiles.forEach((file) => {
260
- archive.file(path.join(distPath, file), { name: file });
261
- });
262
-
263
- // Add all CSS files from dist
264
- const cssFiles = fs.readdirSync(distPath).filter((f) => f.endsWith(".css"));
265
- cssFiles.forEach((file) => {
266
- archive.file(path.join(distPath, file), { name: file });
267
- });
268
-
269
- // Add app-manifest.json
270
- const manifestPath = path.join(distPath, "app-manifest.json");
271
- if (fs.existsSync(manifestPath)) {
272
- archive.file(manifestPath, { name: "app-manifest.json" });
273
- }
257
+ async function createGxpPackage(distPath, outputPath) {
258
+ const zip = new AdmZip()
274
259
 
275
- // Add assets directory
276
- const assetsPath = path.join(distPath, "assets");
277
- if (fs.existsSync(assetsPath)) {
278
- archive.directory(assetsPath, "assets");
260
+ const addFileIfExists = (filePath, zipName) => {
261
+ if (fs.existsSync(filePath)) {
262
+ zip.addLocalFile(filePath, "", zipName)
279
263
  }
264
+ }
280
265
 
281
- // Add optional bundle files
282
- const appInstructionsPath = path.join(distPath, "appInstructions.md");
283
- if (fs.existsSync(appInstructionsPath)) {
284
- archive.file(appInstructionsPath, { name: "appInstructions.md" });
266
+ // Add all JS and CSS files from dist (flat, at zip root)
267
+ for (const file of fs.readdirSync(distPath)) {
268
+ if (file.endsWith(".js") || file.endsWith(".css")) {
269
+ zip.addLocalFile(path.join(distPath, file))
285
270
  }
271
+ }
286
272
 
287
- const defaultStylingPath = path.join(distPath, "default-styling.css");
288
- if (fs.existsSync(defaultStylingPath)) {
289
- archive.file(defaultStylingPath, { name: "default-styling.css" });
290
- }
273
+ addFileIfExists(path.join(distPath, "app-manifest.json"), "app-manifest.json")
291
274
 
292
- const configurationPath = path.join(distPath, "configuration.json");
293
- if (fs.existsSync(configurationPath)) {
294
- archive.file(configurationPath, { name: "configuration.json" });
295
- }
275
+ // Add assets directory (recursive) under "assets/" in the zip
276
+ const assetsPath = path.join(distPath, "assets")
277
+ if (fs.existsSync(assetsPath)) {
278
+ zip.addLocalFolder(assetsPath, "assets")
279
+ }
296
280
 
297
- archive.finalize();
298
- });
281
+ addFileIfExists(
282
+ path.join(distPath, "appInstructions.md"),
283
+ "appInstructions.md",
284
+ )
285
+ addFileIfExists(
286
+ path.join(distPath, "default-styling.css"),
287
+ "default-styling.css",
288
+ )
289
+ addFileIfExists(
290
+ path.join(distPath, "configuration.json"),
291
+ "configuration.json",
292
+ )
293
+
294
+ await zip.writeZipPromise(outputPath)
295
+
296
+ const sizeKB = (fs.statSync(outputPath).size / 1024).toFixed(2)
297
+ console.log(`✓ Package created (${sizeKB} KB)`)
299
298
  }
300
299
 
301
300
  /**
302
301
  * Build command - builds the plugin for production
303
302
  */
304
303
  async function buildCommand(argv) {
305
- const projectPath = findProjectRoot();
306
- const paths = resolveGxPaths();
307
- const distPath = path.join(projectPath, "dist");
308
- const buildPath = path.join(distPath, "build");
309
-
310
- console.log("🔨 Building plugin...\n");
311
-
312
- // check if vite.config.js exists locally
313
- let viteConfigPath = paths.viteConfigPath;
314
- const localViteConfigPath = path.join(projectPath, "vite.config.js");
315
- if (fs.existsSync(localViteConfigPath)) {
316
- viteConfigPath = localViteConfigPath;
317
- console.log(`📁 Using local vite.config.js: ${viteConfigPath}`);
318
- }
304
+ const projectPath = findProjectRoot()
305
+ const paths = resolveGxPaths()
306
+ const distPath = path.join(projectPath, "dist")
307
+ const buildPath = path.join(distPath, "build")
308
+
309
+ console.log("🔨 Building plugin...\n")
310
+
311
+ // Vite config always comes from the runtime. Projects extend it via an
312
+ // optional `vite.extend.js` at the project root.
313
+ const viteConfigPath = paths.viteConfigPath
319
314
 
320
315
  // Set environment variables directly on process.env for cross-platform compatibility.
321
316
  // Using shell-level "export"/"set" syntax breaks on Windows due to cmd.exe quote parsing.
322
317
  if (!process.env.NODE_LOG_LEVEL) {
323
- process.env.NODE_LOG_LEVEL = argv["node-log-level"] || "error";
318
+ process.env.NODE_LOG_LEVEL = argv["node-log-level"] || "error"
324
319
  }
325
320
  if (!process.env.COMPONENT_PATH) {
326
- process.env.COMPONENT_PATH = argv["component-path"] || "./src/Plugin.vue";
321
+ process.env.COMPONENT_PATH = argv["component-path"] || "./src/Plugin.vue"
327
322
  }
328
323
 
329
324
  // Normalize path separators to forward slashes for cross-platform shell compatibility
330
- const normalizedViteConfigPath = viteConfigPath.replace(/\\/g, "/");
331
- const command = `npx vite build --config "${normalizedViteConfigPath}"`;
325
+ const normalizedViteConfigPath = viteConfigPath.replace(/\\/g, "/")
326
+ const command = `npx vite build --config "${normalizedViteConfigPath}"`
332
327
 
333
- const result = shell.exec(command);
328
+ const result = shell.exec(command)
334
329
 
335
330
  // Only proceed with packaging if build succeeded
336
331
  if (result.code === 0) {
337
332
  try {
338
333
  // Move built files from dist/ to dist/build/
339
- await moveBuildFiles(distPath, buildPath);
334
+ await moveBuildFiles(distPath, buildPath)
340
335
  // Package the plugin (reads from buildPath, outputs .gxpapp to distPath)
341
- await packagePlugin(projectPath, buildPath, distPath);
336
+ await packagePlugin(projectPath, buildPath, distPath)
342
337
  } catch (error) {
343
- console.error("❌ Error packaging plugin:", error.message);
344
- process.exit(1);
338
+ console.error("❌ Error packaging plugin:", error.message)
339
+ process.exit(1)
345
340
  }
346
341
  } else {
347
- console.error("❌ Build failed");
348
- process.exit(1);
342
+ console.error("❌ Build failed")
343
+ process.exit(1)
349
344
  }
350
345
  }
351
346
 
@@ -355,20 +350,20 @@ async function buildCommand(argv) {
355
350
  async function moveBuildFiles(distPath, buildPath) {
356
351
  // Create build directory
357
352
  if (!fs.existsSync(buildPath)) {
358
- fs.mkdirSync(buildPath, { recursive: true });
353
+ fs.mkdirSync(buildPath, { recursive: true })
359
354
  }
360
355
 
361
356
  // Move all JS and CSS files to build directory
362
- const files = fs.readdirSync(distPath);
357
+ const files = fs.readdirSync(distPath)
363
358
  for (const file of files) {
364
359
  if (file.endsWith(".js") || file.endsWith(".css")) {
365
- const srcFile = path.join(distPath, file);
366
- const destFile = path.join(buildPath, file);
367
- fs.renameSync(srcFile, destFile);
360
+ const srcFile = path.join(distPath, file)
361
+ const destFile = path.join(buildPath, file)
362
+ fs.renameSync(srcFile, destFile)
368
363
  }
369
364
  }
370
365
  }
371
366
 
372
367
  module.exports = {
373
368
  buildCommand,
374
- };
369
+ }