@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.
@@ -0,0 +1,335 @@
1
+ ---
2
+ name: gxp-developer
3
+ description: GxP plugin development specialist. Use for building Vue components, working with the GxP store, handling API calls, and WebSocket events. Automatically invoked for GxP-related development tasks.
4
+ tools: Read, Write, Edit, Bash, Glob, Grep
5
+ model: sonnet
6
+ ---
7
+
8
+ # GxP Plugin Developer Agent
9
+
10
+ You are an expert GxP plugin developer. You help build Vue 3 components for the GxP kiosk platform.
11
+
12
+ ## Architecture Overview
13
+
14
+ GxP plugins run inside a **container environment** provided by the `gxdev` development server:
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────┐
18
+ │ PortalContainer.vue (runtime - DO NOT EDIT) │
19
+ │ ├── DevToolsModal │
20
+ │ ├── Layout (Public/Private/System) │
21
+ │ │ └── Plugin.vue ← YOUR CODE GOES HERE │
22
+ │ └── Mock Router │
23
+ └─────────────────────────────────────────────────┘
24
+ ```
25
+
26
+ **Key Principle**: Users ONLY edit files in `src/` directory. The runtime container handles:
27
+ - Layout switching (Public, Private, System)
28
+ - Dev tools modal (Ctrl+Shift+D)
29
+ - Mock router for navigation
30
+ - Store initialization and WebSocket connections
31
+
32
+ ## Project Structure
33
+
34
+ ```
35
+ project/
36
+ ├── src/
37
+ │ ├── Plugin.vue # MAIN ENTRY POINT - Start here
38
+ │ ├── components/ # Reusable components
39
+ │ ├── views/ # Page-level components
40
+ │ ├── stores/
41
+ │ │ └── index.js # Re-exports useGxpStore
42
+ │ └── assets/ # Static assets
43
+ ├── theme-layouts/ # Layout customization (optional)
44
+ ├── app-manifest.json # Configuration (strings, assets, settings)
45
+ ├── socket-events/ # WebSocket event templates for testing
46
+ └── .env # Environment configuration
47
+ ```
48
+
49
+ ## The GxP Store (gxpPortalConfigStore)
50
+
51
+ The store is the central hub for all platform data. Import it in any component:
52
+
53
+ ```javascript
54
+ import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
55
+ // OR from local re-export:
56
+ import { useGxpStore } from '@/stores/index.js';
57
+
58
+ const store = useGxpStore();
59
+ ```
60
+
61
+ ### Store Sections
62
+
63
+ | Section | Purpose | Source |
64
+ |---------|---------|--------|
65
+ | `pluginVars` | Plugin settings/configuration | `app-manifest.json` → settings |
66
+ | `stringsList` | Translatable UI strings | `app-manifest.json` → strings.default |
67
+ | `assetList` | Asset URLs (images, etc.) | `app-manifest.json` → assets |
68
+ | `triggerState` | Dynamic runtime state | `app-manifest.json` → triggerState |
69
+ | `dependencyList` | External data dependencies | `app-manifest.json` → dependencies |
70
+ | `permissionFlags` | Feature permissions | `app-manifest.json` → permissions |
71
+
72
+ ### Getter Methods
73
+
74
+ ```javascript
75
+ // Get values with fallbacks
76
+ store.getString('welcome_title', 'Default Title');
77
+ store.getSetting('primary_color', '#FFD600');
78
+ store.getAsset('hero_image', '/fallback.jpg');
79
+ store.getState('current_step', 0);
80
+ store.hasPermission('admin');
81
+ ```
82
+
83
+ ### Update Methods
84
+
85
+ ```javascript
86
+ // Update store values programmatically
87
+ store.updateString('welcome_title', 'New Title');
88
+ store.updateSetting('primary_color', '#FF0000');
89
+ store.updateAsset('hero_image', '/new-image.jpg');
90
+ store.updateState('current_step', 2);
91
+ ```
92
+
93
+ ## API Calls - ALWAYS USE THE STORE
94
+
95
+ **CRITICAL**: Never use axios or fetch directly. Always use the store's API methods which handle:
96
+ - Authentication (Bearer token injection)
97
+ - Base URL configuration based on environment
98
+ - Proxy handling for CORS in development
99
+ - Error handling and logging
100
+
101
+ ```javascript
102
+ const store = useGxpStore();
103
+
104
+ // GET request
105
+ const data = await store.apiGet('/api/v1/attendees', { event_id: 123 });
106
+
107
+ // POST request
108
+ const result = await store.apiPost('/api/v1/check-ins', {
109
+ attendee_id: 456,
110
+ station_id: 'kiosk-1'
111
+ });
112
+
113
+ // PUT request
114
+ await store.apiPut('/api/v1/attendees/456', { status: 'checked_in' });
115
+
116
+ // PATCH request
117
+ await store.apiPatch('/api/v1/attendees/456', { badge_printed: true });
118
+
119
+ // DELETE request
120
+ await store.apiDelete('/api/v1/check-ins/789');
121
+ ```
122
+
123
+ ### API Environment Configuration
124
+
125
+ The store reads `VITE_API_ENV` from `.env`:
126
+
127
+ | Environment | API Base URL |
128
+ |-------------|--------------|
129
+ | `mock` | Local mock server (default) |
130
+ | `local` | https://dashboard.eventfinity.test |
131
+ | `develop` | https://api.zenith-develop.env.eventfinity.app |
132
+ | `staging` | https://api.efz-staging.env.eventfinity.app |
133
+ | `production` | https://api.gramercy.cloud |
134
+
135
+ ## WebSocket Events
136
+
137
+ WebSockets are pre-configured through the store. Listen for real-time events:
138
+
139
+ ```javascript
140
+ const store = useGxpStore();
141
+
142
+ // Listen on primary socket
143
+ store.listenSocket('primary', 'EventName', (data) => {
144
+ console.log('Event received:', data);
145
+ });
146
+
147
+ // Emit to primary socket
148
+ store.emitSocket('primary', 'client-event', { message: 'Hello' });
149
+
150
+ // For dependency-based sockets (configured in app-manifest.json)
151
+ store.useSocketListener('dependency_identifier', 'updated', (data) => {
152
+ console.log('Dependency updated:', data);
153
+ });
154
+ ```
155
+
156
+ ### Dependency Socket Configuration
157
+
158
+ In `app-manifest.json`:
159
+
160
+ ```json
161
+ {
162
+ "dependencies": [
163
+ {
164
+ "identifier": "ai_session",
165
+ "model": "AiInterface",
166
+ "events": {
167
+ "created": "AiSessionMessageCreated",
168
+ "updated": "AiSessionMessageUpdated"
169
+ }
170
+ }
171
+ ]
172
+ }
173
+ ```
174
+
175
+ Then listen:
176
+
177
+ ```javascript
178
+ store.sockets.ai_session?.created?.listen((data) => {
179
+ console.log('AI message created:', data);
180
+ });
181
+ ```
182
+
183
+ ## Vue Directives for Dynamic Content
184
+
185
+ ### gxp-string - Text Replacement
186
+
187
+ ```html
188
+ <!-- Replace from stringsList -->
189
+ <h1 gxp-string="welcome_title">Default Title</h1>
190
+
191
+ <!-- Replace from pluginVars (settings) -->
192
+ <span gxp-string="company_name" gxp-settings>Company</span>
193
+
194
+ <!-- Replace from assetList -->
195
+ <span gxp-string="logo_url" gxp-assets>/default/logo.png</span>
196
+
197
+ <!-- Replace from triggerState -->
198
+ <span gxp-string="current_status" gxp-state>idle</span>
199
+ ```
200
+
201
+ ### gxp-src - Image Source Replacement
202
+
203
+ ```html
204
+ <!-- Replace src from assetList (default) -->
205
+ <img gxp-src="hero_image" src="/placeholder.jpg" alt="Hero">
206
+
207
+ <!-- Replace src from triggerState -->
208
+ <img gxp-src="dynamic_image" gxp-state src="/placeholder.jpg">
209
+ ```
210
+
211
+ ## Component Template
212
+
213
+ When creating new components, use this pattern:
214
+
215
+ ```vue
216
+ <template>
217
+ <div class="my-component">
218
+ <h1 gxp-string="component_title">Default Title</h1>
219
+ <img gxp-src="component_image" src="/placeholder.jpg" alt="">
220
+
221
+ <GxButton @click="handleAction" variant="primary">
222
+ <span gxp-string="action_button">Click Me</span>
223
+ </GxButton>
224
+
225
+ <GxSpinner v-if="loading" />
226
+ </div>
227
+ </template>
228
+
229
+ <script setup>
230
+ import { ref, onMounted } from 'vue';
231
+ import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
232
+ import { GxButton, GxSpinner } from '@gramercytech/gx-componentkit';
233
+
234
+ const store = useGxpStore();
235
+ const loading = ref(false);
236
+ const data = ref(null);
237
+
238
+ async function handleAction() {
239
+ loading.value = true;
240
+ try {
241
+ data.value = await store.apiGet('/api/v1/endpoint');
242
+ } catch (error) {
243
+ console.error('API Error:', error);
244
+ } finally {
245
+ loading.value = false;
246
+ }
247
+ }
248
+
249
+ onMounted(() => {
250
+ // Listen for real-time updates
251
+ store.listenSocket('primary', 'DataUpdated', (eventData) => {
252
+ data.value = eventData;
253
+ });
254
+ });
255
+ </script>
256
+
257
+ <style scoped>
258
+ .my-component {
259
+ padding: 20px;
260
+ }
261
+ </style>
262
+ ```
263
+
264
+ ## GxP Component Kit
265
+
266
+ Use these pre-built components from `@gramercytech/gx-componentkit`:
267
+
268
+ - `GxButton` - Styled buttons (variants: primary, secondary, outline)
269
+ - `GxCard` - Card containers
270
+ - `GxInput` - Form inputs with validation
271
+ - `GxModal` - Modal dialogs
272
+ - `GxSpinner` - Loading indicators
273
+ - `GxAlert` - Notifications
274
+ - `GxBadge` - Status badges
275
+ - `GxAvatar` - User avatars
276
+ - `GxProgress` - Progress bars
277
+ - `GxTabs` - Tab navigation
278
+
279
+ ## app-manifest.json
280
+
281
+ This is the main configuration file. Changes hot-reload during development:
282
+
283
+ ```json
284
+ {
285
+ "name": "my-plugin",
286
+ "description": "My GxP Plugin",
287
+ "settings": {
288
+ "primary_color": "#FFD600",
289
+ "idle_timeout": 30
290
+ },
291
+ "strings": {
292
+ "default": {
293
+ "welcome_title": "Welcome",
294
+ "action_button": "Get Started"
295
+ }
296
+ },
297
+ "assets": {
298
+ "hero_image": "/dev-assets/images/hero.jpg",
299
+ "logo": "/dev-assets/images/logo.png"
300
+ },
301
+ "dependencies": [],
302
+ "permissions": []
303
+ }
304
+ ```
305
+
306
+ ## Best Practices
307
+
308
+ 1. **Always use the store for API calls** - Never use axios/fetch directly
309
+ 2. **Use gxp-string for all user-facing text** - Enables translation and admin customization
310
+ 3. **Use gxp-src for all images** - Enables asset management
311
+ 4. **Keep components in src/components/** - Maintain clean structure
312
+ 5. **Test with socket events** - Use `gxdev socket send --event EventName`
313
+ 6. **Check multiple layouts** - Use Dev Tools (Ctrl+Shift+D) to switch layouts
314
+
315
+ ## Development Commands
316
+
317
+ ```bash
318
+ # Start development server
319
+ npm run dev # HTTPS with Socket.IO
320
+ npm run dev-http # HTTP only
321
+
322
+ # Test socket events
323
+ gxdev socket list # List available events
324
+ gxdev socket send --event Name # Send test event
325
+
326
+ # Build for production
327
+ gxdev build # Creates dist/ with .gxpapp package
328
+ ```
329
+
330
+ ## Debugging
331
+
332
+ - Open Dev Tools: `Ctrl+Shift+D` or click gear icon
333
+ - Console API: `window.gxDevTools.store()` to access store
334
+ - Check API env: Look for `[GxP Store] API Environment:` in console
335
+ - Socket debugging: Events logged with `Socket event received:` prefix
@@ -0,0 +1,9 @@
1
+ {
2
+ "mcpServers": {
3
+ "gxp-api": {
4
+ "command": "gxp-api-server",
5
+ "args": [],
6
+ "env": {}
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,125 @@
1
+ # GxP Plugin Development Guidelines
2
+
3
+ This is a GxP plugin project for the GxP kiosk platform. Follow these guidelines when working with this codebase.
4
+
5
+ ## Project Architecture
6
+
7
+ This plugin runs inside a container environment provided by the `gxdev` development server. You should ONLY modify files in the `src/` directory. The runtime container (PortalContainer.vue) handles layouts, dev tools, routing, and store initialization.
8
+
9
+ ```
10
+ src/
11
+ ├── Plugin.vue # MAIN ENTRY POINT - Your app starts here
12
+ ├── components/ # Reusable Vue components
13
+ ├── views/ # Page-level components
14
+ ├── stores/index.js # Re-exports useGxpStore
15
+ └── assets/ # Static assets
16
+ ```
17
+
18
+ ## Core Principle: Use the GxP Store for Everything
19
+
20
+ The `gxpPortalConfigStore` is the central hub. Import it in any component:
21
+
22
+ ```javascript
23
+ import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
24
+ const store = useGxpStore();
25
+ ```
26
+
27
+ ## API Calls - ALWAYS Use Store Methods
28
+
29
+ NEVER use axios or fetch directly. The store handles authentication, base URLs, and CORS:
30
+
31
+ ```javascript
32
+ // Correct - use store methods
33
+ const data = await store.apiGet('/api/v1/endpoint', { param: 'value' });
34
+ await store.apiPost('/api/v1/endpoint', { data: 'value' });
35
+ await store.apiPut('/api/v1/endpoint/123', { data: 'value' });
36
+ await store.apiPatch('/api/v1/endpoint/123', { data: 'value' });
37
+ await store.apiDelete('/api/v1/endpoint/123');
38
+
39
+ // WRONG - never do this
40
+ // const response = await axios.get(...); // NO!
41
+ // const response = await fetch(...); // NO!
42
+ ```
43
+
44
+ ## Store Data Access
45
+
46
+ ```javascript
47
+ // Get values with fallbacks
48
+ store.getString('key', 'default'); // From stringsList
49
+ store.getSetting('key', 'default'); // From pluginVars
50
+ store.getAsset('key', '/fallback.jpg'); // From assetList
51
+ store.getState('key', null); // From triggerState
52
+ store.hasPermission('admin'); // Check permissions
53
+
54
+ // Update values
55
+ store.updateString('key', 'value');
56
+ store.updateSetting('key', 'value');
57
+ store.updateAsset('key', 'url');
58
+ store.updateState('key', 'value');
59
+ ```
60
+
61
+ ## WebSocket Events
62
+
63
+ Listen for real-time events through the store:
64
+
65
+ ```javascript
66
+ // Listen on primary socket
67
+ store.listenSocket('primary', 'EventName', (data) => {
68
+ console.log('Received:', data);
69
+ });
70
+
71
+ // Emit events
72
+ store.emitSocket('primary', 'client-event', { data: 'value' });
73
+
74
+ // For dependency-based sockets
75
+ store.useSocketListener('dependency_id', 'updated', callback);
76
+ ```
77
+
78
+ ## Vue Directives for Dynamic Content
79
+
80
+ Use these directives instead of hardcoding text and images:
81
+
82
+ ```html
83
+ <!-- Text from strings -->
84
+ <h1 gxp-string="welcome_title">Fallback Title</h1>
85
+
86
+ <!-- Text from settings -->
87
+ <span gxp-string="company_name" gxp-settings>Company</span>
88
+
89
+ <!-- Images from assets -->
90
+ <img gxp-src="hero_image" src="/placeholder.jpg" alt="Hero">
91
+ ```
92
+
93
+ ## Component Kit
94
+
95
+ Import UI components from `@gramercytech/gx-componentkit`:
96
+
97
+ ```javascript
98
+ import { GxButton, GxCard, GxInput, GxModal, GxSpinner } from '@gramercytech/gx-componentkit';
99
+ ```
100
+
101
+ Available: GxButton, GxCard, GxInput, GxModal, GxSpinner, GxAlert, GxBadge, GxAvatar, GxProgress, GxTabs, GxAccordion
102
+
103
+ ## Configuration
104
+
105
+ Edit `app-manifest.json` for strings, assets, and settings. Changes hot-reload during development.
106
+
107
+ ## Testing
108
+
109
+ - Socket events: `gxdev socket send --event EventName`
110
+ - Dev Tools: Press Ctrl+Shift+D
111
+ - Console: `window.gxDevTools.store()` to inspect store
112
+
113
+ ## API Environments
114
+
115
+ Set `VITE_API_ENV` in `.env`:
116
+ - `mock` - Local mock server (default)
117
+ - `develop` - https://api.zenith-develop.env.eventfinity.app
118
+ - `staging` - https://api.efz-staging.env.eventfinity.app
119
+ - `production` - https://api.gramercy.cloud
120
+
121
+ ## API Documentation
122
+
123
+ - OpenAPI Spec: https://api.zenith-develop.env.eventfinity.app/api-specs/openapi.json
124
+ - AsyncAPI Spec: https://api.zenith-develop.env.eventfinity.app/api-specs/asyncapi.json
125
+ - Webhooks: https://api.zenith-develop.env.eventfinity.app/api-specs/webhooks.json
@@ -0,0 +1,80 @@
1
+ # GxP Plugin Development Context
2
+
3
+ This is a GxP plugin project for the GxP kiosk platform built with Vue 3.
4
+
5
+ ## Architecture
6
+
7
+ The plugin runs inside a container provided by the `gxdev` server. Only edit files in `src/`:
8
+
9
+ - `src/Plugin.vue` - Main entry point
10
+ - `src/components/` - Reusable components
11
+ - `src/views/` - Page components
12
+ - `app-manifest.json` - Configuration (strings, assets, settings)
13
+
14
+ ## Critical Rule: Use GxP Store for API Calls
15
+
16
+ NEVER use axios or fetch directly. Always use the store's API methods:
17
+
18
+ ```javascript
19
+ import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
20
+ const store = useGxpStore();
21
+
22
+ // API methods (handles auth, CORS, base URL automatically)
23
+ await store.apiGet('/api/v1/endpoint', { params });
24
+ await store.apiPost('/api/v1/endpoint', data);
25
+ await store.apiPut('/api/v1/endpoint/id', data);
26
+ await store.apiPatch('/api/v1/endpoint/id', data);
27
+ await store.apiDelete('/api/v1/endpoint/id');
28
+ ```
29
+
30
+ ## Store Data Access
31
+
32
+ ```javascript
33
+ // Getters
34
+ store.getString('key', 'default'); // UI strings
35
+ store.getSetting('key', 'default'); // Settings
36
+ store.getAsset('key', '/fallback.jpg'); // Asset URLs
37
+ store.getState('key', null); // Runtime state
38
+
39
+ // Setters
40
+ store.updateString('key', 'value');
41
+ store.updateSetting('key', 'value');
42
+ store.updateAsset('key', 'url');
43
+ store.updateState('key', 'value');
44
+ ```
45
+
46
+ ## WebSocket Events
47
+
48
+ ```javascript
49
+ // Listen for events
50
+ store.listenSocket('primary', 'EventName', (data) => {
51
+ console.log('Event received:', data);
52
+ });
53
+
54
+ // Emit events
55
+ store.emitSocket('primary', 'event-name', data);
56
+ ```
57
+
58
+ ## Vue Directives
59
+
60
+ ```html
61
+ <!-- Dynamic text from strings -->
62
+ <h1 gxp-string="welcome_title">Default</h1>
63
+
64
+ <!-- Dynamic images from assets -->
65
+ <img gxp-src="hero_image" src="/placeholder.jpg">
66
+ ```
67
+
68
+ ## Component Kit
69
+
70
+ Use `@gramercytech/gx-componentkit` for UI:
71
+ GxButton, GxCard, GxInput, GxModal, GxSpinner, GxAlert, GxBadge, GxProgress, GxTabs
72
+
73
+ ## Configuration
74
+
75
+ Edit `app-manifest.json` for strings, assets, settings. Hot-reloads in dev.
76
+
77
+ ## API Specs
78
+
79
+ - OpenAPI: https://api.zenith-develop.env.eventfinity.app/api-specs/openapi.json
80
+ - AsyncAPI: https://api.zenith-develop.env.eventfinity.app/api-specs/asyncapi.json
@@ -4,6 +4,7 @@
4
4
  "description": "GxToolkit Plugin",
5
5
  "manifest_version": 3,
6
6
  "asset_dir": "/src/assets/",
7
+ "configurationFile": "configuration.json",
7
8
  "appInstructionsFile": "app-instructions.md",
8
9
  "defaultStylingFile": "default-styling.css",
9
10
  "settings": {