@gxp-dev/tools 2.0.33 → 2.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/lib/cli.js CHANGED
@@ -57,6 +57,18 @@ yargs
57
57
  alias: "p",
58
58
  choices: ["claude", "codex", "gemini"],
59
59
  },
60
+ yes: {
61
+ describe: "Skip interactive prompts and use defaults",
62
+ type: "boolean",
63
+ alias: "y",
64
+ default: false,
65
+ },
66
+ local: {
67
+ describe: "Initialize in current directory instead of creating a new one",
68
+ type: "boolean",
69
+ alias: "l",
70
+ default: false,
71
+ },
60
72
  },
61
73
  initCommand
62
74
  )
@@ -41,8 +41,9 @@ const {
41
41
  * Copy template files to project
42
42
  * @param {string} projectPath - Target project path
43
43
  * @param {object} paths - Resolved GxP paths
44
+ * @param {boolean} overwrite - If true, overwrite existing files
44
45
  */
45
- function copyTemplateFiles(projectPath, paths) {
46
+ function copyTemplateFiles(projectPath, paths, overwrite = false) {
46
47
  const filesToCopy = [
47
48
  {
48
49
  src: "theme-layouts/SystemLayout.vue",
@@ -133,7 +134,7 @@ function copyTemplateFiles(projectPath, paths) {
133
134
  filesToCopy.forEach((file) => {
134
135
  const srcPath = path.join(paths.templateDir, file.src);
135
136
  const destPath = path.join(projectPath, file.dest);
136
- safeCopyFile(srcPath, destPath, file.desc);
137
+ safeCopyFile(srcPath, destPath, file.desc, overwrite);
137
138
  });
138
139
  }
139
140
 
@@ -141,8 +142,9 @@ function copyTemplateFiles(projectPath, paths) {
141
142
  * Copy extension scripts to project
142
143
  * @param {string} projectPath - Target project path
143
144
  * @param {object} paths - Resolved GxP paths
145
+ * @param {boolean} overwrite - If true, overwrite existing files
144
146
  */
145
- function copyExtensionScripts(projectPath, paths) {
147
+ function copyExtensionScripts(projectPath, paths, overwrite = false) {
146
148
  const scriptsDir = path.join(projectPath, "scripts");
147
149
  if (!fs.existsSync(scriptsDir)) {
148
150
  fs.mkdirSync(scriptsDir, { recursive: true });
@@ -155,7 +157,7 @@ function copyExtensionScripts(projectPath, paths) {
155
157
  );
156
158
  const launchChromeDest = path.join(scriptsDir, "launch-chrome.js");
157
159
  if (fs.existsSync(launchChromeSource)) {
158
- safeCopyFile(launchChromeSource, launchChromeDest, "Chrome launcher script");
160
+ safeCopyFile(launchChromeSource, launchChromeDest, "Chrome launcher script", overwrite);
159
161
  }
160
162
 
161
163
  // Copy pack-chrome.js script
@@ -165,7 +167,7 @@ function copyExtensionScripts(projectPath, paths) {
165
167
  );
166
168
  const packChromeDest = path.join(scriptsDir, "pack-chrome.js");
167
169
  if (fs.existsSync(packChromeSource)) {
168
- safeCopyFile(packChromeSource, packChromeDest, "Chrome packaging script");
170
+ safeCopyFile(packChromeSource, packChromeDest, "Chrome packaging script", overwrite);
169
171
  }
170
172
 
171
173
  // Copy socket events directory
@@ -182,7 +184,7 @@ function copyExtensionScripts(projectPath, paths) {
182
184
  eventFiles.forEach((file) => {
183
185
  const srcPath = path.join(socketEventsSource, file);
184
186
  const destPath = path.join(socketEventsDest, file);
185
- safeCopyFile(srcPath, destPath, `Socket event: ${file}`);
187
+ safeCopyFile(srcPath, destPath, `Socket event: ${file}`, overwrite);
186
188
  });
187
189
  }
188
190
  }
@@ -291,8 +293,9 @@ function launchBrowserExtension(projectPath, browser) {
291
293
  * Run interactive configuration after project creation
292
294
  * @param {string} projectPath - Path to project directory
293
295
  * @param {string} initialName - Initial project name from CLI
296
+ * @param {boolean} isLocal - Whether initialized in current directory
294
297
  */
295
- async function runInteractiveConfig(projectPath, initialName) {
298
+ async function runInteractiveConfig(projectPath, initialName, isLocal = false) {
296
299
  console.log("");
297
300
  console.log("─".repeat(50));
298
301
  console.log("📝 Configure Your Plugin");
@@ -466,7 +469,7 @@ async function runInteractiveConfig(projectPath, initialName) {
466
469
  devProcess = launchDevServer(projectPath, { withMock: true, noHttps: !sslSetup });
467
470
  } else {
468
471
  // Print final instructions
469
- printFinalInstructions(projectPath, appName, sslSetup);
472
+ printFinalInstructions(projectPath, appName, sslSetup, isLocal);
470
473
  }
471
474
 
472
475
  return devProcess;
@@ -477,8 +480,9 @@ async function runInteractiveConfig(projectPath, initialName) {
477
480
  * @param {string} projectPath - Project path
478
481
  * @param {string} projectName - Project name
479
482
  * @param {boolean} sslSetup - Whether SSL was set up
483
+ * @param {boolean} isLocal - Whether initialized in current directory
480
484
  */
481
- function printFinalInstructions(projectPath, projectName, sslSetup) {
485
+ function printFinalInstructions(projectPath, projectName, sslSetup, isLocal = false) {
482
486
  console.log("");
483
487
  console.log("─".repeat(50));
484
488
  console.log("✅ Project setup complete!");
@@ -496,7 +500,9 @@ function printFinalInstructions(projectPath, projectName, sslSetup) {
496
500
  console.log(" • app-manifest.json - Plugin configuration");
497
501
  console.log("");
498
502
  console.log("🚀 To start development:");
499
- console.log(` cd ${projectName}`);
503
+ if (!isLocal) {
504
+ console.log(` cd ${projectName}`);
505
+ }
500
506
  if (sslSetup) {
501
507
  console.log(" npm run dev # HTTPS with TUI");
502
508
  console.log(" npm run dev-http # HTTP only");
@@ -517,50 +523,75 @@ async function initCommand(argv) {
517
523
  const hasPackageJson = fs.existsSync(path.join(currentDir, "package.json"));
518
524
  let projectPath = currentDir;
519
525
  let projectName;
526
+ const overwrite = argv.local && argv.yes;
520
527
 
521
- // Handle existing project update
522
- if (hasPackageJson && !argv.name) {
523
- console.log("Updating existing project...");
524
- updateExistingProject(projectPath);
525
- console.log("✅ Project updated!");
526
- return;
527
- }
528
+ // Handle --local flag: initialize in current directory
529
+ if (argv.local) {
530
+ projectPath = currentDir;
531
+ projectName = argv.name || path.basename(currentDir);
528
532
 
529
- // New project - require a name
530
- if (!argv.name) {
531
533
  console.log("");
532
- console.log("🚀 GxP Plugin Creator");
534
+ console.log(`📁 Initializing project in current directory: ${projectName}`);
535
+ if (overwrite) {
536
+ console.log("⚠️ Overwrite mode enabled - existing files will be replaced");
537
+ }
533
538
  console.log("─".repeat(40));
534
- console.log("");
535
- projectName = await promptUser("📝 Project name: ");
536
- if (!projectName) {
537
- console.error(" Project name is required!");
539
+ } else {
540
+ // Handle existing project update
541
+ if (hasPackageJson && !argv.name) {
542
+ console.log("Updating existing project...");
543
+ updateExistingProject(projectPath);
544
+ console.log("✅ Project updated!");
545
+ return;
546
+ }
547
+
548
+ // New project - require a name
549
+ if (!argv.name) {
550
+ // In non-interactive mode, name is required
551
+ if (argv.yes) {
552
+ console.error("❌ Project name is required when using --yes flag!");
553
+ console.error(" Usage: gxdev init <project-name> --yes");
554
+ process.exit(1);
555
+ }
556
+ console.log("");
557
+ console.log("🚀 GxP Plugin Creator");
558
+ console.log("─".repeat(40));
559
+ console.log("");
560
+ projectName = await promptUser("📝 Project name: ");
561
+ if (!projectName) {
562
+ console.error("❌ Project name is required!");
563
+ process.exit(1);
564
+ }
565
+ } else {
566
+ projectName = argv.name;
567
+ }
568
+
569
+ // Create project directory
570
+ projectPath = path.join(currentDir, projectName);
571
+ if (fs.existsSync(projectPath)) {
572
+ console.error(`\n❌ Directory ${projectName} already exists!`);
538
573
  process.exit(1);
539
574
  }
540
- } else {
541
- projectName = argv.name;
542
- }
543
575
 
544
- // Create project directory
545
- projectPath = path.join(currentDir, projectName);
546
- if (fs.existsSync(projectPath)) {
547
- console.error(`\n❌ Directory ${projectName} already exists!`);
548
- process.exit(1);
576
+ console.log("");
577
+ console.log(`📁 Creating project: ${projectName}`);
578
+ console.log("─".repeat(40));
579
+ fs.mkdirSync(projectPath, { recursive: true });
549
580
  }
550
581
 
551
- console.log("");
552
- console.log(`📁 Creating project: ${projectName}`);
553
- console.log("─".repeat(40));
554
- fs.mkdirSync(projectPath, { recursive: true });
555
-
556
- // Create package.json
582
+ // Create package.json (only if it doesn't exist or overwrite is enabled)
557
583
  const initialDescription = argv.description || "A GxP kiosk plugin";
558
- createPackageJson(projectPath, projectName, initialDescription);
584
+ const packageJsonPath = path.join(projectPath, "package.json");
585
+ if (!fs.existsSync(packageJsonPath) || overwrite) {
586
+ createPackageJson(projectPath, projectName, initialDescription);
587
+ } else {
588
+ console.log("⏭️ Skipping package.json (already exists)");
589
+ }
559
590
 
560
591
  // Copy template files
561
592
  const paths = resolveGxPaths();
562
- copyTemplateFiles(projectPath, paths);
563
- copyExtensionScripts(projectPath, paths);
593
+ copyTemplateFiles(projectPath, paths, overwrite);
594
+ copyExtensionScripts(projectPath, paths, overwrite);
564
595
  createSupportingFiles(projectPath);
565
596
 
566
597
  // Install dependencies
@@ -575,12 +606,19 @@ async function initCommand(argv) {
575
606
  updateAppManifest(projectPath, projectName, initialDescription);
576
607
  const provider = argv.provider || "gemini"; // Default to gemini for backward compatibility
577
608
  await runAIScaffolding(projectPath, projectName, initialDescription, argv.build, provider);
578
- printFinalInstructions(projectPath, projectName, false);
609
+ printFinalInstructions(projectPath, projectName, false, argv.local);
610
+ return;
611
+ }
612
+
613
+ // If --yes flag provided, skip interactive configuration
614
+ if (argv.yes) {
615
+ updateAppManifest(projectPath, projectName, initialDescription);
616
+ printFinalInstructions(projectPath, projectName, false, argv.local);
579
617
  return;
580
618
  }
581
619
 
582
620
  // Run interactive configuration
583
- await runInteractiveConfig(projectPath, projectName);
621
+ await runInteractiveConfig(projectPath, projectName, argv.local);
584
622
  }
585
623
 
586
624
  module.exports = {
@@ -16,10 +16,15 @@ const { loadGlobalConfig } = require("./paths");
16
16
 
17
17
  /**
18
18
  * Copies a file from source to destination, creating directories if needed
19
+ * @param {string} src - Source file path
20
+ * @param {string} dest - Destination file path
21
+ * @param {string} description - Description for logging
22
+ * @param {boolean} overwrite - If true, overwrite existing files
19
23
  */
20
- function safeCopyFile(src, dest, description) {
21
- if (!fs.existsSync(dest)) {
22
- console.log(`Creating ${description}`);
24
+ function safeCopyFile(src, dest, description, overwrite = false) {
25
+ const exists = fs.existsSync(dest);
26
+ if (!exists || overwrite) {
27
+ console.log(`${exists ? 'Overwriting' : 'Creating'} ${description}`);
23
28
  const destDir = path.dirname(dest);
24
29
  if (!fs.existsSync(destDir)) {
25
30
  fs.mkdirSync(destDir, { recursive: true });
@@ -124,32 +129,50 @@ function updateExistingProject(projectPath) {
124
129
  }
125
130
 
126
131
  try {
132
+ // Backup existing vite.config.js if present
133
+ const viteConfigPath = path.join(projectPath, "vite.config.js");
134
+ if (fs.existsSync(viteConfigPath)) {
135
+ const backupPath = path.join(projectPath, "vite.config.js.backup");
136
+ fs.renameSync(viteConfigPath, backupPath);
137
+ console.log(" → Renamed vite.config.js to vite.config.js.backup");
138
+ }
139
+
127
140
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
128
141
  let updated = false;
129
142
 
130
- // Check and add missing dependencies
143
+ // Check and add/update dependencies
131
144
  if (!packageJson.dependencies) {
132
145
  packageJson.dependencies = {};
133
146
  }
134
147
 
135
148
  for (const [dep, version] of Object.entries(REQUIRED_DEPENDENCIES)) {
136
- if (!packageJson.dependencies[dep]) {
149
+ const existingVersion = packageJson.dependencies[dep];
150
+ if (!existingVersion) {
137
151
  packageJson.dependencies[dep] = version;
138
152
  console.log(` + Adding dependency: ${dep}@${version}`);
139
153
  updated = true;
154
+ } else if (existingVersion !== version) {
155
+ packageJson.dependencies[dep] = version;
156
+ console.log(` ↑ Updating dependency: ${dep} (${existingVersion} → ${version})`);
157
+ updated = true;
140
158
  }
141
159
  }
142
160
 
143
- // Check and add missing dev dependencies
161
+ // Check and add/update dev dependencies
144
162
  if (!packageJson.devDependencies) {
145
163
  packageJson.devDependencies = {};
146
164
  }
147
165
 
148
166
  for (const [dep, version] of Object.entries(REQUIRED_DEV_DEPENDENCIES)) {
149
- if (!packageJson.devDependencies[dep]) {
167
+ const existingVersion = packageJson.devDependencies[dep];
168
+ if (!existingVersion) {
150
169
  packageJson.devDependencies[dep] = version;
151
170
  console.log(` + Adding devDependency: ${dep}@${version}`);
152
171
  updated = true;
172
+ } else if (existingVersion !== version) {
173
+ packageJson.devDependencies[dep] = version;
174
+ console.log(` ↑ Updating devDependency: ${dep} (${existingVersion} → ${version})`);
175
+ updated = true;
153
176
  }
154
177
  }
155
178
 
@@ -1,12 +1,21 @@
1
1
  {
2
2
  "manifest_version": 2,
3
3
  "name": "GxP Developer Toolkit",
4
- "version": "1.2",
4
+ "version": "1.2.0",
5
5
  "description": "JavaScript proxy and component inspector for GxP plugin development",
6
+ "homepage_url": "https://github.com/gramercytech/gx-devtools",
7
+ "developer": {
8
+ "name": "Gramercy Tech",
9
+ "url": "https://gramercytech.com"
10
+ },
6
11
 
7
12
  "browser_specific_settings": {
8
13
  "gecko": {
9
- "id": "gxp-toolkit@gx-devtools.dev"
14
+ "id": "gxp-toolkit@gx-devtools.dev",
15
+ "strict_min_version": "109.0",
16
+ "data_collection_permissions": {
17
+ "required": ["none"]
18
+ }
10
19
  }
11
20
  },
12
21
 
@@ -46,7 +55,7 @@
46
55
  "default_icon": {
47
56
  "16": "icons/gx_off_16.png",
48
57
  "32": "icons/gx_off_32.png",
49
- "48": "icons/gx_off_48.png",
58
+ "64": "icons/gx_off_64.png",
50
59
  "128": "icons/gx_off_128.png"
51
60
  }
52
61
  },
@@ -54,7 +63,7 @@
54
63
  "icons": {
55
64
  "16": "icons/gx_off_16.png",
56
65
  "32": "icons/gx_off_32.png",
57
- "48": "icons/gx_off_48.png",
66
+ "48": "icons/gx_off_64.png",
58
67
  "128": "icons/gx_off_128.png"
59
68
  },
60
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gxp-dev/tools",
3
- "version": "2.0.33",
3
+ "version": "2.0.35",
4
4
  "description": "Dev tools to create platform plugins",
5
5
  "type": "commonjs",
6
6
  "publishConfig": {
@@ -0,0 +1 @@
1
+ /* This file used to pre-populate the the additional styling editor in the GxP app */
@@ -5,28 +5,16 @@
5
5
  />
6
6
  </template>
7
7
 
8
- <style scoped>
9
- #app {
10
- font-family: Avenir, Helvetica, Arial, sans-serif;
11
- -webkit-font-smoothing: antialiased;
12
- -moz-osx-font-smoothing: grayscale;
13
- }
14
- </style>
8
+
15
9
 
16
10
  <script setup>
17
11
  import { ref, shallowRef } from "vue";
18
12
  import DemoPage from "@/DemoPage.vue";
19
- import {
20
- GxPageStart,
21
- GxPageFinal,
22
- GxPageLoading
23
- } from "@gramercytech/gx-componentkit";
24
13
 
25
14
  // Initialize the GxP store
26
15
  // This import is externalized to window.useGxpStore during build for platform compatibility
27
16
  import { useGxpStore } from "@/stores/gxpPortalConfigStore";
28
17
 
29
-
30
18
 
31
19
  const gxpStore = useGxpStore();
32
20
  gxpStore.sockets?.primary.listenForStateChange((event) => {
@@ -35,4 +23,78 @@
35
23
 
36
24
 
37
25
 
38
- </script>
26
+ </script>
27
+
28
+ <style>
29
+ #app {
30
+ font-family: Avenir, Helvetica, Arial, sans-serif;
31
+ -webkit-font-smoothing: antialiased;
32
+ -moz-osx-font-smoothing: grayscale;
33
+ }
34
+
35
+ /* Primary Color */
36
+ .primary {
37
+ color: var(--primary, #000000);
38
+ }
39
+
40
+ /* Page Styles */
41
+ .page {
42
+ background-color: var(--page_background_color, #000466);
43
+ color: var(--page_text_color, #FFFFFF);
44
+ }
45
+
46
+ /* Input Field Styles */
47
+ .input-field {
48
+ background-color: var(--input_field_background_color, #03054a);
49
+ color: var(--input_field_text_color, #FFFFFF);
50
+ border-color: var(--input_field_border_color, #888C92);
51
+ }
52
+
53
+ /* Primary Button Styles */
54
+ .primary-button {
55
+ background-color: var(--primary_button_background_color, #FFFFFF);
56
+ color: var(--primary_button_text_color, #000596);
57
+ border-color: var(--primary_button_border_color, #FFFFFF);
58
+ }
59
+
60
+ /* Secondary Button Styles */
61
+ .secondary-button {
62
+ background-color: var(--secondary_button_background_color, #000466);
63
+ color: var(--secondary_button_text_color, #FFFFFF);
64
+ border-color: var(--secondary_button_border_color, #FFFFFF);
65
+ }
66
+
67
+ /* Tertiary Button Styles */
68
+ .tertiary-button {
69
+ background-color: var(--tertiary_button_background_color, #FFFFFF00);
70
+ color: var(--tertiary_button_text_color, #FFFFFF);
71
+ border-color: var(--tertiary_button_border_color, #FFFFFF00);
72
+ }
73
+
74
+ /* Spinner Styles */
75
+ .spinner {
76
+ background-color: var(--spinner_background_color, #03054A);
77
+ color: var(--spinner_color, #FFFFFF);
78
+ }
79
+
80
+ /* Modal Styles */
81
+ .modal {
82
+ background-color: var(--modal_background_color, #FFFFFF);
83
+ color: var(--modal_text_color, #222222);
84
+ }
85
+
86
+ /* Modal Primary Button Styles */
87
+ .modal-primary-button {
88
+ background-color: var(--modal_primary_button_background_color, #000596);
89
+ color: var(--modal_primary_button_text_color, #FFFFFF);
90
+ border-color: var(--modal_primary_button_border_color, #000596);
91
+ }
92
+
93
+ /* Modal Secondary Button Styles */
94
+ .modal-secondary-button {
95
+ background-color: var(--modal_secondary_button_background_color, #FFFFFF);
96
+ color: var(--modal_secondary_button_text_color, #000596);
97
+ border-color: var(--modal_secondary_button_border_color, #000596);
98
+ }
99
+
100
+ </style>
@@ -0,0 +1,93 @@
1
+ /* Theme CSS Variables */
2
+ :root {
3
+ --primary: #000000;
4
+ --page_background_color: #000466;
5
+ --page_text_color: #FFFFFF;
6
+ --input_field_background_color: #03054a;
7
+ --input_field_text_color: #FFFFFF;
8
+ --input_field_border_color: #888C92;
9
+ --primary_button_background_color: #FFFFFF;
10
+ --primary_button_text_color: #000596;
11
+ --primary_button_border_color: #FFFFFF;
12
+ --secondary_button_background_color: #000466;
13
+ --secondary_button_text_color: #FFFFFF;
14
+ --secondary_button_border_color: #FFFFFF;
15
+ --tertiary_button_background_color: #FFFFFF00;
16
+ --tertiary_button_text_color: #FFFFFF;
17
+ --tertiary_button_border_color: #FFFFFF00;
18
+ --spinner_background_color: #03054A;
19
+ --spinner_color: #FFFFFF;
20
+ --modal_background_color: #FFFFFF;
21
+ --modal_text_color: #222222;
22
+ --modal_primary_button_background_color: #000596;
23
+ --modal_primary_button_text_color: #FFFFFF;
24
+ --modal_primary_button_border_color: #000596;
25
+ --modal_secondary_button_background_color: #FFFFFF;
26
+ --modal_secondary_button_text_color: #000596;
27
+ --modal_secondary_button_border_color: #000596;
28
+ }
29
+
30
+ /* Primary Color */
31
+ .primary {
32
+ color: var(--primary, #000000);
33
+ }
34
+
35
+ /* Page Styles */
36
+ .page {
37
+ background-color: var(--page_background_color, #000466);
38
+ color: var(--page_text_color, #FFFFFF);
39
+ }
40
+
41
+ /* Input Field Styles */
42
+ .input-field {
43
+ background-color: var(--input_field_background_color, #03054a);
44
+ color: var(--input_field_text_color, #FFFFFF);
45
+ border-color: var(--input_field_border_color, #888C92);
46
+ }
47
+
48
+ /* Primary Button Styles */
49
+ .primary-button {
50
+ background-color: var(--primary_button_background_color, #FFFFFF);
51
+ color: var(--primary_button_text_color, #000596);
52
+ border-color: var(--primary_button_border_color, #FFFFFF);
53
+ }
54
+
55
+ /* Secondary Button Styles */
56
+ .secondary-button {
57
+ background-color: var(--secondary_button_background_color, #000466);
58
+ color: var(--secondary_button_text_color, #FFFFFF);
59
+ border-color: var(--secondary_button_border_color, #FFFFFF);
60
+ }
61
+
62
+ /* Tertiary Button Styles */
63
+ .tertiary-button {
64
+ background-color: var(--tertiary_button_background_color, #FFFFFF00);
65
+ color: var(--tertiary_button_text_color, #FFFFFF);
66
+ border-color: var(--tertiary_button_border_color, #FFFFFF00);
67
+ }
68
+
69
+ /* Spinner Styles */
70
+ .spinner {
71
+ background-color: var(--spinner_background_color, #03054A);
72
+ color: var(--spinner_color, #FFFFFF);
73
+ }
74
+
75
+ /* Modal Styles */
76
+ .modal {
77
+ background-color: var(--modal_background_color, #FFFFFF);
78
+ color: var(--modal_text_color, #222222);
79
+ }
80
+
81
+ /* Modal Primary Button Styles */
82
+ .modal-primary-button {
83
+ background-color: var(--modal_primary_button_background_color, #000596);
84
+ color: var(--modal_primary_button_text_color, #FFFFFF);
85
+ border-color: var(--modal_primary_button_border_color, #000596);
86
+ }
87
+
88
+ /* Modal Secondary Button Styles */
89
+ .modal-secondary-button {
90
+ background-color: var(--modal_secondary_button_background_color, #FFFFFF);
91
+ color: var(--modal_secondary_button_text_color, #000596);
92
+ border-color: var(--modal_secondary_button_border_color, #000596);
93
+ }