@gxp-dev/tools 2.0.5

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 (145) hide show
  1. package/.github/workflows/npm-publish.yml +48 -0
  2. package/CLAUDE.md +400 -0
  3. package/README.md +247 -0
  4. package/REFACTOR_PLAN.md +194 -0
  5. package/bin/gx-devtools.js +87 -0
  6. package/bin/lib/cli.js +251 -0
  7. package/bin/lib/commands/assets.js +337 -0
  8. package/bin/lib/commands/build.js +259 -0
  9. package/bin/lib/commands/datastore.js +433 -0
  10. package/bin/lib/commands/dev.js +328 -0
  11. package/bin/lib/commands/extensions.js +298 -0
  12. package/bin/lib/commands/index.js +35 -0
  13. package/bin/lib/commands/init.js +307 -0
  14. package/bin/lib/commands/publish.js +189 -0
  15. package/bin/lib/commands/socket.js +158 -0
  16. package/bin/lib/commands/ssl.js +47 -0
  17. package/bin/lib/constants.js +120 -0
  18. package/bin/lib/tui/App.tsx +600 -0
  19. package/bin/lib/tui/components/CommandInput.tsx +278 -0
  20. package/bin/lib/tui/components/GeminiPanel.tsx +161 -0
  21. package/bin/lib/tui/components/Header.tsx +27 -0
  22. package/bin/lib/tui/components/LogPanel.tsx +122 -0
  23. package/bin/lib/tui/components/TabBar.tsx +56 -0
  24. package/bin/lib/tui/components/WelcomeScreen.tsx +80 -0
  25. package/bin/lib/tui/index.tsx +63 -0
  26. package/bin/lib/tui/services/ExtensionService.ts +122 -0
  27. package/bin/lib/tui/services/GeminiService.ts +395 -0
  28. package/bin/lib/tui/services/ServiceManager.ts +336 -0
  29. package/bin/lib/tui/services/SocketService.ts +204 -0
  30. package/bin/lib/tui/services/ViteService.ts +107 -0
  31. package/bin/lib/tui/services/index.ts +13 -0
  32. package/bin/lib/utils/files.js +180 -0
  33. package/bin/lib/utils/index.js +17 -0
  34. package/bin/lib/utils/paths.js +138 -0
  35. package/bin/lib/utils/prompts.js +71 -0
  36. package/bin/lib/utils/ssl.js +233 -0
  37. package/browser-extensions/README.md +1 -0
  38. package/browser-extensions/chrome/background.js +857 -0
  39. package/browser-extensions/chrome/content.js +51 -0
  40. package/browser-extensions/chrome/devtools.html +9 -0
  41. package/browser-extensions/chrome/devtools.js +23 -0
  42. package/browser-extensions/chrome/icons/gx_off_128.png +0 -0
  43. package/browser-extensions/chrome/icons/gx_off_16.png +0 -0
  44. package/browser-extensions/chrome/icons/gx_off_32.png +0 -0
  45. package/browser-extensions/chrome/icons/gx_off_64.png +0 -0
  46. package/browser-extensions/chrome/icons/gx_on_128.png +0 -0
  47. package/browser-extensions/chrome/icons/gx_on_16.png +0 -0
  48. package/browser-extensions/chrome/icons/gx_on_32.png +0 -0
  49. package/browser-extensions/chrome/icons/gx_on_64.png +0 -0
  50. package/browser-extensions/chrome/inspector.js +1087 -0
  51. package/browser-extensions/chrome/manifest.json +70 -0
  52. package/browser-extensions/chrome/panel.html +638 -0
  53. package/browser-extensions/chrome/panel.js +862 -0
  54. package/browser-extensions/chrome/popup.html +399 -0
  55. package/browser-extensions/chrome/popup.js +515 -0
  56. package/browser-extensions/chrome/rules.json +1 -0
  57. package/browser-extensions/chrome/test-chrome.html +145 -0
  58. package/browser-extensions/chrome/test-mixed-content.html +190 -0
  59. package/browser-extensions/chrome/test-uri-pattern.html +199 -0
  60. package/browser-extensions/firefox/README.md +134 -0
  61. package/browser-extensions/firefox/background.js +804 -0
  62. package/browser-extensions/firefox/content.js +120 -0
  63. package/browser-extensions/firefox/debug-errors.html +229 -0
  64. package/browser-extensions/firefox/debug-https.html +113 -0
  65. package/browser-extensions/firefox/devtools.html +9 -0
  66. package/browser-extensions/firefox/devtools.js +24 -0
  67. package/browser-extensions/firefox/icons/gx_off_128.png +0 -0
  68. package/browser-extensions/firefox/icons/gx_off_16.png +0 -0
  69. package/browser-extensions/firefox/icons/gx_off_32.png +0 -0
  70. package/browser-extensions/firefox/icons/gx_off_64.png +0 -0
  71. package/browser-extensions/firefox/icons/gx_on_128.png +0 -0
  72. package/browser-extensions/firefox/icons/gx_on_16.png +0 -0
  73. package/browser-extensions/firefox/icons/gx_on_32.png +0 -0
  74. package/browser-extensions/firefox/icons/gx_on_64.png +0 -0
  75. package/browser-extensions/firefox/inspector.js +1087 -0
  76. package/browser-extensions/firefox/manifest.json +67 -0
  77. package/browser-extensions/firefox/panel.html +638 -0
  78. package/browser-extensions/firefox/panel.js +862 -0
  79. package/browser-extensions/firefox/popup.html +525 -0
  80. package/browser-extensions/firefox/popup.js +536 -0
  81. package/browser-extensions/firefox/test-gramercy.html +126 -0
  82. package/browser-extensions/firefox/test-imports.html +58 -0
  83. package/browser-extensions/firefox/test-masking.html +147 -0
  84. package/browser-extensions/firefox/test-uri-pattern.html +199 -0
  85. package/docs/DOCUSAURUS_IMPORT.md +378 -0
  86. package/docs/_category_.json +8 -0
  87. package/docs/app-manifest.md +272 -0
  88. package/docs/building-for-platform.md +315 -0
  89. package/docs/dev-tools.md +291 -0
  90. package/docs/getting-started.md +180 -0
  91. package/docs/gxp-store.md +305 -0
  92. package/docs/index.md +44 -0
  93. package/package.json +77 -0
  94. package/runtime/PortalContainer.vue +326 -0
  95. package/runtime/dev-tools/DevToolsModal.vue +217 -0
  96. package/runtime/dev-tools/LayoutSwitcher.vue +221 -0
  97. package/runtime/dev-tools/MockDataEditor.vue +621 -0
  98. package/runtime/dev-tools/SocketSimulator.vue +562 -0
  99. package/runtime/dev-tools/StoreInspector.vue +644 -0
  100. package/runtime/dev-tools/index.js +6 -0
  101. package/runtime/gxpStringsPlugin.js +428 -0
  102. package/runtime/index.html +22 -0
  103. package/runtime/main.js +32 -0
  104. package/runtime/mock-api/auth-middleware.js +97 -0
  105. package/runtime/mock-api/image-generator.js +221 -0
  106. package/runtime/mock-api/index.js +197 -0
  107. package/runtime/mock-api/response-generator.js +394 -0
  108. package/runtime/mock-api/route-generator.js +323 -0
  109. package/runtime/mock-api/socket-triggers.js +371 -0
  110. package/runtime/mock-api/spec-loader.js +300 -0
  111. package/runtime/server.js +180 -0
  112. package/runtime/stores/gxpPortalConfigStore.js +554 -0
  113. package/runtime/stores/index.js +6 -0
  114. package/runtime/vite-inspector-plugin.js +749 -0
  115. package/runtime/vite-source-tracker-plugin.js +232 -0
  116. package/runtime/vite.config.js +402 -0
  117. package/scripts/launch-chrome.js +90 -0
  118. package/scripts/pack-chrome.js +91 -0
  119. package/socket-events/AiSessionMessageCreated.json +18 -0
  120. package/socket-events/SocialStreamPostCreated.json +24 -0
  121. package/socket-events/SocialStreamPostVariantCompleted.json +23 -0
  122. package/template/README.md +332 -0
  123. package/template/app-manifest.json +32 -0
  124. package/template/dev-assets/images/avatar-placeholder.png +0 -0
  125. package/template/dev-assets/images/background-placeholder.jpg +0 -0
  126. package/template/dev-assets/images/banner-placeholder.jpg +0 -0
  127. package/template/dev-assets/images/icon-placeholder.png +0 -0
  128. package/template/dev-assets/images/logo-placeholder.png +0 -0
  129. package/template/dev-assets/images/product-placeholder.jpg +0 -0
  130. package/template/dev-assets/images/thumbnail-placeholder.jpg +0 -0
  131. package/template/env.example +51 -0
  132. package/template/gitignore +53 -0
  133. package/template/index.html +22 -0
  134. package/template/main.js +28 -0
  135. package/template/src/DemoPage.vue +459 -0
  136. package/template/src/Plugin.vue +38 -0
  137. package/template/src/stores/index.js +9 -0
  138. package/template/src/stores/test-data.json +173 -0
  139. package/template/theme-layouts/AdditionalStyling.css +0 -0
  140. package/template/theme-layouts/PrivateLayout.vue +39 -0
  141. package/template/theme-layouts/PublicLayout.vue +39 -0
  142. package/template/theme-layouts/SystemLayout.vue +39 -0
  143. package/template/vite.config.js +333 -0
  144. package/tsconfig.tui.json +21 -0
  145. package/vite.config.js +164 -0
@@ -0,0 +1,433 @@
1
+ /**
2
+ * Datastore Command
3
+ *
4
+ * Manages GxP datastore test data and configuration.
5
+ */
6
+
7
+ const path = require("path");
8
+ const fs = require("fs");
9
+ const shell = require("shelljs");
10
+ const {
11
+ findProjectRoot,
12
+ resolveGxPaths,
13
+ promptUser,
14
+ safeCopyFile,
15
+ } = require("../utils");
16
+
17
+ /**
18
+ * Datastore commands for managing test data
19
+ */
20
+ function datastoreCommand(argv) {
21
+ const action = argv.action;
22
+
23
+ switch (action) {
24
+ case "list":
25
+ listDatastoreVariables();
26
+ break;
27
+ case "add":
28
+ addDatastoreVariable(argv);
29
+ break;
30
+ case "scan-strings":
31
+ scanComponentStrings(argv);
32
+ break;
33
+ case "config":
34
+ switchDatastoreConfig(argv);
35
+ break;
36
+ case "init":
37
+ initDatastoreInExistingProject();
38
+ break;
39
+ default:
40
+ console.log("Available datastore commands:");
41
+ console.log(" list - List all store variables");
42
+ console.log(" add - Add a new variable to the store");
43
+ console.log(
44
+ " scan-strings - Scan components for hardcoded strings"
45
+ );
46
+ console.log(" config [name] - Switch between test configurations");
47
+ console.log(" init - Add datastore to existing project");
48
+ }
49
+ }
50
+
51
+ function listDatastoreVariables() {
52
+ const projectPath = findProjectRoot();
53
+ const testDataPath = path.join(projectPath, "src/stores/test-data.json");
54
+
55
+ if (!fs.existsSync(testDataPath)) {
56
+ console.error('❌ No datastore found. Run "gxdev datastore init" first.');
57
+ return;
58
+ }
59
+
60
+ try {
61
+ const testData = JSON.parse(fs.readFileSync(testDataPath, "utf-8"));
62
+
63
+ console.log("📊 GxP Datastore Variables:");
64
+ console.log("");
65
+
66
+ if (testData.pluginVars && Object.keys(testData.pluginVars).length > 0) {
67
+ console.log("🔧 Plugin Variables:");
68
+ Object.entries(testData.pluginVars).forEach(([key, value]) => {
69
+ console.log(` ${key}: ${JSON.stringify(value)}`);
70
+ });
71
+ console.log("");
72
+ }
73
+
74
+ if (testData.stringsList && Object.keys(testData.stringsList).length > 0) {
75
+ console.log("📝 Strings:");
76
+ Object.entries(testData.stringsList).forEach(([key, value]) => {
77
+ console.log(` ${key}: "${value}"`);
78
+ });
79
+ console.log("");
80
+ }
81
+
82
+ if (testData.assetList && Object.keys(testData.assetList).length > 0) {
83
+ console.log("đŸ–ŧī¸ Assets:");
84
+ Object.entries(testData.assetList).forEach(([key, value]) => {
85
+ console.log(` ${key}: ${value}`);
86
+ });
87
+ console.log("");
88
+ }
89
+
90
+ if (
91
+ testData.dependencyList &&
92
+ Object.keys(testData.dependencyList).length > 0
93
+ ) {
94
+ console.log("🔗 Dependencies:");
95
+ Object.entries(testData.dependencyList).forEach(([key, value]) => {
96
+ console.log(` ${key}: ${value}`);
97
+ });
98
+ console.log("");
99
+ }
100
+ } catch (error) {
101
+ console.error("❌ Error reading test data:", error.message);
102
+ }
103
+ }
104
+
105
+ async function addDatastoreVariable(argv) {
106
+ if (argv.type && argv.key && argv.value) {
107
+ // Use provided arguments
108
+ addVariable(argv.type, argv.key, argv.value);
109
+ } else {
110
+ // Interactive mode
111
+ console.log("Add a new variable to the datastore:");
112
+ console.log("1. string - Text content for UI");
113
+ console.log("2. setting - Configuration variable");
114
+ console.log("3. asset - Asset URL or path");
115
+ console.log("");
116
+
117
+ const type = await promptUser(
118
+ "What type of variable? (string/setting/asset): "
119
+ );
120
+ const key = await promptUser("Variable key/name: ");
121
+ const value = await promptUser("Default value: ");
122
+
123
+ addVariable(type, key, value);
124
+ }
125
+ }
126
+
127
+ function addVariable(type, key, value) {
128
+ const projectPath = findProjectRoot();
129
+ const testDataPath = path.join(projectPath, "src/stores/test-data.json");
130
+
131
+ if (!fs.existsSync(testDataPath)) {
132
+ console.error(
133
+ "❌ No datastore found. Initialize project with datastore first."
134
+ );
135
+ return;
136
+ }
137
+
138
+ try {
139
+ const testData = JSON.parse(fs.readFileSync(testDataPath, "utf-8"));
140
+
141
+ switch (type.toLowerCase()) {
142
+ case "string":
143
+ testData.stringsList = testData.stringsList || {};
144
+ testData.stringsList[key] = value;
145
+ console.log(`✓ Added string: ${key} = "${value}"`);
146
+ break;
147
+ case "setting":
148
+ testData.pluginVars = testData.pluginVars || {};
149
+ // Try to parse as JSON for numbers/booleans, fallback to string
150
+ try {
151
+ testData.pluginVars[key] = JSON.parse(value);
152
+ } catch {
153
+ testData.pluginVars[key] = value;
154
+ }
155
+ console.log(
156
+ `✓ Added setting: ${key} = ${JSON.stringify(
157
+ testData.pluginVars[key]
158
+ )}`
159
+ );
160
+ break;
161
+ case "asset":
162
+ testData.assetList = testData.assetList || {};
163
+ testData.assetList[key] = value;
164
+ console.log(`✓ Added asset: ${key} = ${value}`);
165
+ break;
166
+ default:
167
+ console.error("❌ Invalid type. Use: string, setting, or asset");
168
+ return;
169
+ }
170
+
171
+ fs.writeFileSync(testDataPath, JSON.stringify(testData, null, 2));
172
+ console.log("💾 Datastore updated successfully!");
173
+ } catch (error) {
174
+ console.error("❌ Error updating datastore:", error.message);
175
+ }
176
+ }
177
+
178
+ async function scanComponentStrings(argv) {
179
+ const projectPath = findProjectRoot();
180
+ const componentPath =
181
+ argv.component ||
182
+ (await promptUser("Component file path (e.g., src/Plugin.vue): "));
183
+ const fullPath = path.join(projectPath, componentPath);
184
+
185
+ if (!fs.existsSync(fullPath)) {
186
+ console.error(`❌ Component not found: ${componentPath}`);
187
+ return;
188
+ }
189
+
190
+ try {
191
+ const content = fs.readFileSync(fullPath, "utf-8");
192
+
193
+ // Extract strings from template section
194
+ const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
195
+ if (!templateMatch) {
196
+ console.log("❌ No template section found");
197
+ return;
198
+ }
199
+
200
+ const template = templateMatch[1];
201
+
202
+ // Find text content within HTML elements (simplified regex)
203
+ const stringMatches = template.match(/>\s*([^<>]+[a-zA-Z][^<>]*)\s*</g);
204
+
205
+ if (!stringMatches || stringMatches.length === 0) {
206
+ console.log("â„šī¸ No hardcoded strings found in template");
207
+ return;
208
+ }
209
+
210
+ console.log(
211
+ `🔍 Found ${stringMatches.length} potential strings in ${componentPath}:`
212
+ );
213
+ console.log("");
214
+
215
+ const testDataPath = path.join(projectPath, "src/stores/test-data.json");
216
+ let testData = {};
217
+
218
+ if (fs.existsSync(testDataPath)) {
219
+ testData = JSON.parse(fs.readFileSync(testDataPath, "utf-8"));
220
+ }
221
+
222
+ testData.stringsList = testData.stringsList || {};
223
+
224
+ for (const match of stringMatches) {
225
+ const text = match.replace(/>\s*/, "").replace(/\s*</, "").trim();
226
+
227
+ if (text.length > 2 && !text.includes("{{") && !text.includes("v-")) {
228
+ const key = text
229
+ .toLowerCase()
230
+ .replace(/[^a-z0-9\s]/g, "")
231
+ .replace(/\s+/g, "_")
232
+ .substring(0, 30);
233
+
234
+ if (!testData.stringsList[key]) {
235
+ const add = await promptUser(`Add "${text}" as "${key}"? (y/N): `);
236
+ if (add.toLowerCase() === "y" || add.toLowerCase() === "yes") {
237
+ testData.stringsList[key] = text;
238
+ console.log(`✓ Added: ${key} = "${text}"`);
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ fs.writeFileSync(testDataPath, JSON.stringify(testData, null, 2));
245
+ console.log("💾 Scan complete!");
246
+ } catch (error) {
247
+ console.error("❌ Error scanning component:", error.message);
248
+ }
249
+ }
250
+
251
+ async function switchDatastoreConfig(argv) {
252
+ const projectPath = findProjectRoot();
253
+ const storeDir = path.join(projectPath, "src/Store");
254
+
255
+ if (!fs.existsSync(storeDir)) {
256
+ console.error(
257
+ "❌ No datastore found. Initialize project with datastore first."
258
+ );
259
+ return;
260
+ }
261
+
262
+ if (argv.config) {
263
+ // Switch to specified config
264
+ const configPath = path.join(storeDir, `test-data-${argv.config}.json`);
265
+ const defaultPath = path.join(storeDir, "test-data.json");
266
+
267
+ if (fs.existsSync(configPath)) {
268
+ fs.copyFileSync(configPath, defaultPath);
269
+ console.log(`✓ Switched to configuration: ${argv.config}`);
270
+ } else {
271
+ console.error(`❌ Configuration not found: ${argv.config}`);
272
+ }
273
+ } else {
274
+ // List available configurations
275
+ const files = fs
276
+ .readdirSync(storeDir)
277
+ .filter((f) => f.startsWith("test-data-") && f.endsWith(".json"))
278
+ .map((f) => f.replace("test-data-", "").replace(".json", ""));
279
+
280
+ if (files.length === 0) {
281
+ console.log("â„šī¸ No additional configurations found");
282
+ console.log(
283
+ "💡 Create a new config: cp src/stores/test-data.json src/stores/test-data-production.json"
284
+ );
285
+ } else {
286
+ console.log("Available configurations:");
287
+ files.forEach((config) => console.log(` ${config}`));
288
+ console.log("");
289
+ console.log("Switch with: gxdev datastore config <name>");
290
+ }
291
+ }
292
+ }
293
+
294
+ async function initDatastoreInExistingProject() {
295
+ const projectPath = findProjectRoot();
296
+ const packageJsonPath = path.join(projectPath, "package.json");
297
+
298
+ if (!fs.existsSync(packageJsonPath)) {
299
+ console.error(
300
+ "❌ No package.json found. Make sure you are in a GxP project directory."
301
+ );
302
+ return;
303
+ }
304
+
305
+ const storeDir = path.join(projectPath, "src/stores");
306
+ if (fs.existsSync(storeDir)) {
307
+ console.error("❌ Datastore already exists in this project.");
308
+ return;
309
+ }
310
+
311
+ console.log("đŸ—ƒī¸ Adding GxP Datastore to existing project...");
312
+
313
+ try {
314
+ // Read current package.json
315
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
316
+
317
+ // Add Pinia and axios dependencies
318
+ if (!packageJson.dependencies) {
319
+ packageJson.dependencies = {};
320
+ }
321
+
322
+ packageJson.dependencies.pinia = "^2.1.7";
323
+ packageJson.dependencies.axios = "^1.6.0";
324
+
325
+ // Add datastore scripts
326
+ if (!packageJson.scripts) {
327
+ packageJson.scripts = {};
328
+ }
329
+
330
+ packageJson.scripts["datastore:list"] = "gxdev datastore list";
331
+ packageJson.scripts["datastore:add"] = "gxdev datastore add";
332
+ packageJson.scripts["datastore:scan"] = "gxdev datastore scan-strings";
333
+ packageJson.scripts["datastore:config"] = "gxdev datastore config";
334
+
335
+ // Write updated package.json
336
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
337
+ console.log("✓ Updated package.json");
338
+
339
+ // Create store directory
340
+ fs.mkdirSync(storeDir, { recursive: true });
341
+
342
+ // Copy store files
343
+ const paths = resolveGxPaths();
344
+ const storeFiles = [
345
+ {
346
+ src: "stores/index.js",
347
+ dest: "src/stores/index.js",
348
+ desc: "Pinia store setup",
349
+ },
350
+ {
351
+ src: "stores/gxpPortalConfigStore.js",
352
+ dest: "src/stores/gxpPortalConfigStore.js",
353
+ desc: "GxP datastore",
354
+ },
355
+ {
356
+ src: "stores/test-data.json",
357
+ dest: "src/stores/test-data.json",
358
+ desc: "Test data configuration",
359
+ },
360
+ ];
361
+
362
+ storeFiles.forEach((file) => {
363
+ const srcPath = path.join(paths.templateDir, file.src);
364
+ const destPath = path.join(projectPath, file.dest);
365
+ safeCopyFile(srcPath, destPath, file.desc);
366
+ });
367
+
368
+ // Update main.js to include Pinia
369
+ const mainJsPath = path.join(projectPath, "main.js");
370
+ if (fs.existsSync(mainJsPath)) {
371
+ let mainJsContent = fs.readFileSync(mainJsPath, "utf-8");
372
+
373
+ // Add Pinia import
374
+ if (!mainJsContent.includes("pinia")) {
375
+ const importLine = 'import { pinia } from "./src/stores/index.js";';
376
+ const importIndex = mainJsContent.indexOf("import * as Vue");
377
+ if (importIndex !== -1) {
378
+ mainJsContent =
379
+ mainJsContent.slice(0, importIndex) +
380
+ importLine +
381
+ "\n" +
382
+ mainJsContent.slice(importIndex);
383
+ } else {
384
+ mainJsContent = importLine + "\n" + mainJsContent;
385
+ }
386
+
387
+ // Add Pinia use
388
+ if (!mainJsContent.includes("app.use(pinia)")) {
389
+ const useIndex = mainJsContent.indexOf("app.use(GxComponentKit);");
390
+ if (useIndex !== -1) {
391
+ const endOfLine = mainJsContent.indexOf("\n", useIndex);
392
+ mainJsContent =
393
+ mainJsContent.slice(0, endOfLine) +
394
+ "\napp.use(pinia);" +
395
+ mainJsContent.slice(endOfLine);
396
+ }
397
+ }
398
+
399
+ fs.writeFileSync(mainJsPath, mainJsContent);
400
+ console.log("✓ Updated main.js");
401
+ }
402
+ }
403
+
404
+ // Install new dependencies
405
+ console.log("đŸ“Ļ Installing dependencies...");
406
+ const result = shell.exec("npm install", {
407
+ cwd: projectPath,
408
+ silent: false,
409
+ });
410
+
411
+ if (result.code === 0) {
412
+ console.log("✅ GxP Datastore added successfully!");
413
+ console.log("");
414
+ console.log("📊 Manage test data with: npm run datastore:add");
415
+ console.log("🔍 Scan components for strings: npm run datastore:scan");
416
+ console.log("📋 List all store variables: npm run datastore:list");
417
+ console.log("");
418
+ console.log("💡 Update your components to use the store:");
419
+ console.log(' import { useGxpStore } from "/src/stores/index.js"');
420
+ console.log(" const gxpStore = useGxpStore()");
421
+ } else {
422
+ console.error(
423
+ '❌ Failed to install dependencies. Please run "npm install" manually.'
424
+ );
425
+ }
426
+ } catch (error) {
427
+ console.error("❌ Error adding datastore:", error.message);
428
+ }
429
+ }
430
+
431
+ module.exports = {
432
+ datastoreCommand,
433
+ };