@gxp-dev/tools 2.0.11 → 2.0.13
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 +42 -0
- package/bin/lib/commands/extract-config.js +186 -0
- package/bin/lib/commands/index.js +2 -0
- package/bin/lib/commands/init.js +446 -180
- package/bin/lib/tui/App.tsx +158 -41
- package/bin/lib/tui/components/CommandInput.tsx +100 -95
- package/bin/lib/tui/components/LogPanel.tsx +30 -17
- package/bin/lib/tui/components/TabBar.tsx +1 -1
- package/bin/lib/utils/ai-scaffold.js +877 -0
- package/bin/lib/utils/extract-config.js +468 -0
- package/bin/lib/utils/files.js +43 -2
- package/bin/lib/utils/index.js +4 -0
- package/bin/lib/utils/prompts.js +352 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +134 -40
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/components/CommandInput.d.ts.map +1 -1
- package/dist/tui/components/CommandInput.js +87 -89
- package/dist/tui/components/CommandInput.js.map +1 -1
- package/dist/tui/components/LogPanel.d.ts +4 -2
- package/dist/tui/components/LogPanel.d.ts.map +1 -1
- package/dist/tui/components/LogPanel.js +25 -15
- package/dist/tui/components/LogPanel.js.map +1 -1
- package/dist/tui/components/TabBar.js +1 -1
- package/dist/tui/components/TabBar.js.map +1 -1
- package/mcp/gxp-api-server.js +524 -0
- package/package.json +4 -2
- package/runtime/stores/gxpPortalConfigStore.js +9 -0
- package/template/.claude/agents/gxp-developer.md +335 -0
- package/template/.claude/settings.json +9 -0
- package/template/AGENTS.md +125 -0
- package/template/GEMINI.md +80 -0
- package/template/app-manifest.json +1 -0
package/bin/lib/cli.js
CHANGED
|
@@ -22,6 +22,7 @@ const {
|
|
|
22
22
|
extensionChromeCommand,
|
|
23
23
|
extensionBuildCommand,
|
|
24
24
|
extensionInstallCommand,
|
|
25
|
+
extractConfigCommand,
|
|
25
26
|
} = require("./commands");
|
|
26
27
|
|
|
27
28
|
// Load global configuration
|
|
@@ -39,6 +40,22 @@ yargs
|
|
|
39
40
|
describe: "Project name (for new projects)",
|
|
40
41
|
type: "string",
|
|
41
42
|
},
|
|
43
|
+
description: {
|
|
44
|
+
describe: "Project description",
|
|
45
|
+
type: "string",
|
|
46
|
+
alias: "d",
|
|
47
|
+
},
|
|
48
|
+
build: {
|
|
49
|
+
describe: "AI build prompt - describe what to build for auto-scaffolding",
|
|
50
|
+
type: "string",
|
|
51
|
+
alias: "b",
|
|
52
|
+
},
|
|
53
|
+
provider: {
|
|
54
|
+
describe: "AI provider for scaffolding (claude, codex, gemini)",
|
|
55
|
+
type: "string",
|
|
56
|
+
alias: "p",
|
|
57
|
+
choices: ["claude", "codex", "gemini"],
|
|
58
|
+
},
|
|
42
59
|
},
|
|
43
60
|
initCommand
|
|
44
61
|
)
|
|
@@ -245,6 +262,31 @@ yargs
|
|
|
245
262
|
},
|
|
246
263
|
assetsCommand
|
|
247
264
|
)
|
|
265
|
+
.command(
|
|
266
|
+
"extract-config",
|
|
267
|
+
"Extract GxP configuration from source files to app-manifest.json",
|
|
268
|
+
{
|
|
269
|
+
"dry-run": {
|
|
270
|
+
describe: "Show what would be extracted without making changes",
|
|
271
|
+
type: "boolean",
|
|
272
|
+
default: false,
|
|
273
|
+
alias: "d",
|
|
274
|
+
},
|
|
275
|
+
overwrite: {
|
|
276
|
+
describe: "Overwrite existing values in manifest",
|
|
277
|
+
type: "boolean",
|
|
278
|
+
default: false,
|
|
279
|
+
alias: "o",
|
|
280
|
+
},
|
|
281
|
+
verbose: {
|
|
282
|
+
describe: "Show detailed output",
|
|
283
|
+
type: "boolean",
|
|
284
|
+
default: false,
|
|
285
|
+
alias: "v",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
extractConfigCommand
|
|
289
|
+
)
|
|
248
290
|
.demandCommand(1, "Please provide a valid command")
|
|
249
291
|
.help("h")
|
|
250
292
|
.alias("h", "help")
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract Config Command
|
|
3
|
+
*
|
|
4
|
+
* Scans source files for GxP store usage and directives,
|
|
5
|
+
* then generates/updates app-manifest.json with extracted configuration.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const {
|
|
11
|
+
findProjectRoot,
|
|
12
|
+
extractConfigFromSource,
|
|
13
|
+
mergeConfig,
|
|
14
|
+
generateSummary,
|
|
15
|
+
} = require("../utils");
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Main extract-config command handler
|
|
19
|
+
* @param {Object} argv - Yargs arguments
|
|
20
|
+
*/
|
|
21
|
+
async function extractConfigCommand(argv) {
|
|
22
|
+
const projectPath = findProjectRoot();
|
|
23
|
+
const srcDir = path.join(projectPath, "src");
|
|
24
|
+
const manifestPath = path.join(projectPath, "app-manifest.json");
|
|
25
|
+
|
|
26
|
+
const dryRun = argv.dryRun || argv["dry-run"] || false;
|
|
27
|
+
const overwrite = argv.overwrite || false;
|
|
28
|
+
const verbose = argv.verbose || false;
|
|
29
|
+
|
|
30
|
+
console.log("🔍 Scanning source files for GxP configuration...");
|
|
31
|
+
console.log(` Project: ${projectPath}`);
|
|
32
|
+
console.log(` Source: ${srcDir}`);
|
|
33
|
+
console.log("");
|
|
34
|
+
|
|
35
|
+
// Check if src directory exists
|
|
36
|
+
if (!fs.existsSync(srcDir)) {
|
|
37
|
+
console.error("❌ Source directory not found: src/");
|
|
38
|
+
console.log(" Make sure you are in a GxP project directory.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Extract configuration from source files
|
|
43
|
+
const extractedConfig = extractConfigFromSource(srcDir);
|
|
44
|
+
|
|
45
|
+
// Show summary of what was found
|
|
46
|
+
const summary = generateSummary(extractedConfig);
|
|
47
|
+
console.log(summary);
|
|
48
|
+
|
|
49
|
+
// Check if anything was extracted
|
|
50
|
+
const totalItems =
|
|
51
|
+
Object.keys(extractedConfig.strings).length +
|
|
52
|
+
Object.keys(extractedConfig.settings).length +
|
|
53
|
+
Object.keys(extractedConfig.assets).length +
|
|
54
|
+
Object.keys(extractedConfig.triggerState).length +
|
|
55
|
+
extractedConfig.dependencies.length;
|
|
56
|
+
|
|
57
|
+
if (totalItems === 0) {
|
|
58
|
+
console.log("ℹ️ No GxP configuration found in source files.");
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log("💡 Tips:");
|
|
61
|
+
console.log(" - Use store.getString('key', 'default') in your components");
|
|
62
|
+
console.log(" - Use gxp-string directive: <span gxp-string=\"key\">default</span>");
|
|
63
|
+
console.log(" - Use gxp-src directive: <img gxp-src=\"key\" src=\"/default.jpg\" />");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (dryRun) {
|
|
68
|
+
console.log("🔸 Dry run mode - no changes will be made.");
|
|
69
|
+
console.log("");
|
|
70
|
+
console.log("To apply changes, run without --dry-run flag:");
|
|
71
|
+
console.log(" gxdev extract-config");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Load existing manifest or create new one
|
|
76
|
+
let existingManifest = {};
|
|
77
|
+
if (fs.existsSync(manifestPath)) {
|
|
78
|
+
try {
|
|
79
|
+
existingManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
80
|
+
if (verbose) {
|
|
81
|
+
console.log("📄 Found existing app-manifest.json");
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.warn("⚠ Could not parse existing app-manifest.json, creating new one");
|
|
85
|
+
existingManifest = getDefaultManifest();
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
console.log("📄 Creating new app-manifest.json");
|
|
89
|
+
existingManifest = getDefaultManifest();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Merge extracted config into manifest
|
|
93
|
+
const mergedManifest = mergeConfig(existingManifest, extractedConfig, {
|
|
94
|
+
overwrite,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Write updated manifest
|
|
98
|
+
try {
|
|
99
|
+
fs.writeFileSync(manifestPath, JSON.stringify(mergedManifest, null, "\t"));
|
|
100
|
+
console.log("✅ Updated app-manifest.json");
|
|
101
|
+
|
|
102
|
+
if (verbose) {
|
|
103
|
+
console.log("");
|
|
104
|
+
console.log("📋 Changes applied:");
|
|
105
|
+
logChanges(existingManifest, mergedManifest, extractedConfig);
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error("❌ Error writing app-manifest.json:", error.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get default manifest structure
|
|
114
|
+
* @returns {Object} Default manifest
|
|
115
|
+
*/
|
|
116
|
+
function getDefaultManifest() {
|
|
117
|
+
return {
|
|
118
|
+
name: "GxToolkit",
|
|
119
|
+
version: "1.0.0",
|
|
120
|
+
description: "GxToolkit Plugin",
|
|
121
|
+
manifest_version: 3,
|
|
122
|
+
asset_dir: "/src/assets/",
|
|
123
|
+
configurationFile: "configuration.json",
|
|
124
|
+
appInstructionsFile: "app-instructions.md",
|
|
125
|
+
defaultStylingFile: "default-styling.css",
|
|
126
|
+
settings: {},
|
|
127
|
+
strings: {
|
|
128
|
+
default: {},
|
|
129
|
+
},
|
|
130
|
+
assets: {},
|
|
131
|
+
triggerState: {},
|
|
132
|
+
dependencies: [],
|
|
133
|
+
permissions: [],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Log what changes were made
|
|
139
|
+
* @param {Object} oldManifest - Original manifest
|
|
140
|
+
* @param {Object} newManifest - Updated manifest
|
|
141
|
+
* @param {Object} extracted - Extracted configuration
|
|
142
|
+
*/
|
|
143
|
+
function logChanges(oldManifest, newManifest, extracted) {
|
|
144
|
+
const oldStrings = oldManifest.strings?.default || {};
|
|
145
|
+
const newStrings = newManifest.strings?.default || {};
|
|
146
|
+
|
|
147
|
+
// Count new additions
|
|
148
|
+
let addedStrings = 0;
|
|
149
|
+
let addedSettings = 0;
|
|
150
|
+
let addedAssets = 0;
|
|
151
|
+
let addedState = 0;
|
|
152
|
+
let addedDeps = 0;
|
|
153
|
+
|
|
154
|
+
for (const key of Object.keys(extracted.strings)) {
|
|
155
|
+
if (!oldStrings[key]) addedStrings++;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const key of Object.keys(extracted.settings)) {
|
|
159
|
+
if (oldManifest.settings?.[key] === undefined) addedSettings++;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const key of Object.keys(extracted.assets)) {
|
|
163
|
+
if (!oldManifest.assets?.[key]) addedAssets++;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
for (const key of Object.keys(extracted.triggerState)) {
|
|
167
|
+
if (oldManifest.triggerState?.[key] === undefined) addedState++;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const dep of extracted.dependencies) {
|
|
171
|
+
const exists = (oldManifest.dependencies || []).some(
|
|
172
|
+
(d) => d.identifier === dep.identifier
|
|
173
|
+
);
|
|
174
|
+
if (!exists) addedDeps++;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (addedStrings > 0) console.log(` + ${addedStrings} new string(s)`);
|
|
178
|
+
if (addedSettings > 0) console.log(` + ${addedSettings} new setting(s)`);
|
|
179
|
+
if (addedAssets > 0) console.log(` + ${addedAssets} new asset(s)`);
|
|
180
|
+
if (addedState > 0) console.log(` + ${addedState} new state value(s)`);
|
|
181
|
+
if (addedDeps > 0) console.log(` + ${addedDeps} new dependency(ies)`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = {
|
|
185
|
+
extractConfigCommand,
|
|
186
|
+
};
|
|
@@ -18,6 +18,7 @@ const {
|
|
|
18
18
|
extensionBuildCommand,
|
|
19
19
|
extensionInstallCommand,
|
|
20
20
|
} = require("./extensions");
|
|
21
|
+
const { extractConfigCommand } = require("./extract-config");
|
|
21
22
|
|
|
22
23
|
module.exports = {
|
|
23
24
|
initCommand,
|
|
@@ -32,4 +33,5 @@ module.exports = {
|
|
|
32
33
|
extensionChromeCommand,
|
|
33
34
|
extensionBuildCommand,
|
|
34
35
|
extensionInstallCommand,
|
|
36
|
+
extractConfigCommand,
|
|
35
37
|
};
|