Initial commit: JMESPath Testing Tool
- React-based web application for testing JMESPath expressions - macOS-first containerization with Apple container command - Bootstrap UI with real-time evaluation - GitHub Actions CI/CD pipeline - Docker fallback support - Comprehensive documentation and development scripts
This commit is contained in:
19
.containerignore
Normal file
19
.containerignore
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Ignore files for Apple container command builds
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
build
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
README.md
|
||||||
|
DEVELOPMENT.md
|
||||||
|
.env
|
||||||
|
.nyc_output
|
||||||
|
coverage
|
||||||
|
.coverage
|
||||||
|
**/*.test.js
|
||||||
|
**/*.spec.js
|
||||||
|
scripts/
|
||||||
|
demo.sh
|
||||||
|
.dockerignore
|
||||||
|
docker-compose.yml
|
||||||
|
Dockerfile.dev
|
||||||
12
.dockerignore
Normal file
12
.dockerignore
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
build
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
README.md
|
||||||
|
.env
|
||||||
|
.nyc_output
|
||||||
|
coverage
|
||||||
|
.coverage
|
||||||
|
**/*.test.js
|
||||||
|
**/*.spec.js
|
||||||
32
.github/copilot-instructions.md
vendored
Normal file
32
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
description: Instructions for using the JMESPath Testing Tool repository.
|
||||||
|
applyTo: "**/*.md,**/.js"
|
||||||
|
---
|
||||||
|
# AI Agent Instructions for JMESPath Testing Tool
|
||||||
|
|
||||||
|
The tool in this repository is designed to help users validate and test JMESPath expressions against JSON data. It is a React-based web application that provides an interactive interface for entering JMESPath queries and viewing the results.
|
||||||
|
|
||||||
|
The application is single page. The page is divided into three sections:
|
||||||
|
|
||||||
|
- Top section: Title and description of the tool.
|
||||||
|
- Middle section: Input area for JMESPath expressions
|
||||||
|
- Bottom left section: Input area for JSON data
|
||||||
|
- Bottom right section: Output are for JMESPath query results
|
||||||
|
|
||||||
|
The main components of the application are located in the `src` directory and target Node 24 LTS environment.
|
||||||
|
|
||||||
|
Framework to be used:
|
||||||
|
|
||||||
|
- React for building the user interface.
|
||||||
|
- JavaScript (ES6+) for scripting.
|
||||||
|
- Bootstrap for styling and layout.
|
||||||
|
|
||||||
|
## Containerization
|
||||||
|
|
||||||
|
The application should be prepared for deployment using containerization. It should extend minimal Node 24 LTS container image.
|
||||||
|
|
||||||
|
Do not assume the Docker is installed on the development machine.
|
||||||
|
|
||||||
|
The development machine is a MacOS system with Apple `container` command from @github/apple/container.
|
||||||
|
|
||||||
|
Build scripts should target MacOS with the above toolset as first class environment. Docker should be used only as secondary option.
|
||||||
98
.github/workflows/build-container.yml
vendored
Normal file
98
.github/workflows/build-container.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
name: Build Container
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
|
- 'public/**'
|
||||||
|
- 'package*.json'
|
||||||
|
- 'Dockerfile'
|
||||||
|
- 'Containerfile'
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
|
- 'public/**'
|
||||||
|
- 'package*.json'
|
||||||
|
- 'Dockerfile'
|
||||||
|
- 'Containerfile'
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: jmespath-playground
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node.js 24 LTS
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '24'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test -- --coverage --watchAll=false
|
||||||
|
|
||||||
|
- name: Build React application
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build container image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: false
|
||||||
|
tags: ${{ env.IMAGE_NAME }}:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Test container
|
||||||
|
run: |
|
||||||
|
docker run --rm -d -p 3000:3000 --name test-container ${{ env.IMAGE_NAME }}:latest
|
||||||
|
sleep 10
|
||||||
|
# Test if the container is responding
|
||||||
|
curl -f http://localhost:3000 || exit 1
|
||||||
|
docker stop test-container
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: success()
|
||||||
|
with:
|
||||||
|
name: build-output
|
||||||
|
path: build/
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
# Optional: Build with multi-platform support for production
|
||||||
|
build-multiplatform:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
needs: build
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build multi-platform image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: false
|
||||||
|
tags: ${{ env.IMAGE_NAME }}:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
24
Containerfile
Normal file
24
Containerfile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Containerfile for Apple container command
|
||||||
|
# Use Node 24 LTS as base image
|
||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy application source
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Expose port 3000
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD ["npm", "run", "serve"]
|
||||||
143
DEVELOPMENT.md
Normal file
143
DEVELOPMENT.md
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
# Development Guide
|
||||||
|
|
||||||
|
## Quick Start Commands
|
||||||
|
|
||||||
|
### macOS Development (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Start macOS-optimized development server
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build with macOS toolset (Apple container + Docker fallback)
|
||||||
|
npm run build:macos
|
||||||
|
|
||||||
|
# Container operations (macOS)
|
||||||
|
npm run container:build
|
||||||
|
npm run container:run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Traditional Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start development server (with hot reload)
|
||||||
|
npm start
|
||||||
|
|
||||||
|
# Build for production
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Serve production build locally
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
## Container Commands
|
||||||
|
|
||||||
|
### Apple Container (Primary - macOS)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build container with Apple's container command
|
||||||
|
container build -t jmespath-playground .
|
||||||
|
|
||||||
|
# Run container
|
||||||
|
container run -p 3000:3000 jmespath-playground
|
||||||
|
|
||||||
|
# Using Containerfile (Apple's format)
|
||||||
|
container build -f Containerfile -t jmespath-playground .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker (Fallback)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build Docker container
|
||||||
|
docker build -t jmespath-playground .
|
||||||
|
|
||||||
|
# Run Docker container
|
||||||
|
docker run -p 3000:3000 jmespath-playground
|
||||||
|
|
||||||
|
# Development with Docker Compose
|
||||||
|
docker-compose --profile dev up jmespath-playground-dev
|
||||||
|
|
||||||
|
# Production with Docker Compose
|
||||||
|
docker-compose up jmespath-playground
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── App.js # Main component with JMESPath logic
|
||||||
|
├── App.css # App-specific styles
|
||||||
|
├── App.test.js # Basic tests
|
||||||
|
├── index.js # React entry point
|
||||||
|
├── index.css # Global styles and Bootstrap overrides
|
||||||
|
└── setupTests.js # Test configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Features Implemented
|
||||||
|
|
||||||
|
1. **Real-time JMESPath Evaluation**: Uses the `jmespath` library to evaluate expressions as user types
|
||||||
|
2. **JSON Validation**: Parses and validates JSON input with error reporting
|
||||||
|
3. **Bootstrap UI**: Responsive layout with cards, buttons, and form controls
|
||||||
|
4. **Error Handling**: Clear error messages for both JSON and JMESPath syntax issues
|
||||||
|
5. **Sample Data**: Pre-loaded examples with "Load Sample" button
|
||||||
|
6. **JSON Formatting**: "Format JSON" button to prettify JSON input
|
||||||
|
7. **Clear Function**: "Clear All" button to reset all inputs
|
||||||
|
|
||||||
|
## Component Architecture
|
||||||
|
|
||||||
|
The main `App.js` component manages:
|
||||||
|
- State for JMESPath expression, JSON data, results, and errors
|
||||||
|
- Auto-evaluation using `useEffect` when inputs change
|
||||||
|
- Error handling for both JSON parsing and JMESPath evaluation
|
||||||
|
- UI event handlers for buttons and input changes
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
- Bootstrap 5.3.2 for responsive grid and components
|
||||||
|
- Custom CSS for enhanced UX (color coding, hover effects)
|
||||||
|
- Gradient header with professional appearance
|
||||||
|
- Color-coded input areas (yellow for JMESPath, green for JSON, blue for results)
|
||||||
|
|
||||||
|
## Browser Compatibility
|
||||||
|
|
||||||
|
Built with React 18 and targets:
|
||||||
|
- Modern evergreen browsers
|
||||||
|
- Node.js 24 LTS compatibility
|
||||||
|
- Mobile-responsive design
|
||||||
|
|
||||||
|
## CI/CD Pipeline
|
||||||
|
|
||||||
|
### GitHub Actions Workflow
|
||||||
|
|
||||||
|
The project includes automated container building via GitHub Actions:
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- Push to `main` or `develop` branches
|
||||||
|
- Changes in `src/`, `public/`, `package*.json`, or container files
|
||||||
|
- Pull requests to `main` branch
|
||||||
|
|
||||||
|
**Pipeline Steps:**
|
||||||
|
1. Checkout code and setup Node.js 24 LTS
|
||||||
|
2. Install dependencies with npm ci
|
||||||
|
3. Run test suite with coverage
|
||||||
|
4. Build React production bundle
|
||||||
|
5. Build and test Docker container
|
||||||
|
6. Upload build artifacts
|
||||||
|
7. Create multi-platform images (main branch only)
|
||||||
|
|
||||||
|
**Local Testing:**
|
||||||
|
```bash
|
||||||
|
# Test the same steps locally
|
||||||
|
npm ci
|
||||||
|
npm test -- --coverage --watchAll=false
|
||||||
|
npm run build
|
||||||
|
npm run docker:build
|
||||||
|
npm run docker:run
|
||||||
|
```
|
||||||
|
|
||||||
|
The workflow uses Docker in the GitHub Actions environment while maintaining compatibility with the project's macOS-first development approach.
|
||||||
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Use Node 24 LTS as base image
|
||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy application source
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Expose port 3000
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD ["npm", "run", "serve"]
|
||||||
20
Dockerfile.dev
Normal file
20
Dockerfile.dev
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Development Dockerfile
|
||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install all dependencies (including dev dependencies)
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy application source
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose port 3000
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Start the development server
|
||||||
|
CMD ["npm", "start"]
|
||||||
279
README.md
Normal file
279
README.md
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
# JMESPath Testing Tool
|
||||||
|
|
||||||
|
A React-based web application for testing and validating JMESPath expressions against JSON data in real-time. This interactive tool provides a user-friendly interface to experiment with JMESPath queries and see results instantly.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- 🎯 **Real-time Evaluation**: JMESPath expressions are evaluated instantly as you type
|
||||||
|
- 📝 **JSON Validation**: Built-in JSON syntax validation and error reporting
|
||||||
|
- 🎨 **Bootstrap UI**: Clean, responsive interface with Bootstrap styling
|
||||||
|
- 🔄 **Sample Data**: Pre-loaded examples to get started quickly
|
||||||
|
- 📱 **Responsive Design**: Works on desktop, tablet, and mobile devices
|
||||||
|
- 🐳 **Container Ready**: Containerized for easy deployment (macOS + Docker)
|
||||||
|
- ✅ **Error Handling**: Clear error messages for both JSON and JMESPath syntax issues
|
||||||
|
- 🚀 **CI/CD Ready**: GitHub Actions workflow for automated container builds
|
||||||
|
|
||||||
|
## Application Layout
|
||||||
|
|
||||||
|
The application is divided into three main sections:
|
||||||
|
|
||||||
|
1. **Top Section**: Title and description of the tool
|
||||||
|
2. **Middle Section**: Input area for JMESPath expressions
|
||||||
|
3. **Bottom Sections**:
|
||||||
|
- **Left**: JSON data input area
|
||||||
|
- **Right**: Query results output area
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js 24 LTS or higher
|
||||||
|
- npm or yarn package manager
|
||||||
|
- **macOS recommended** (optimized for Apple's container toolset)
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
1. **Clone the repository**:
|
||||||
|
```bash
|
||||||
|
git clone <repository-url>
|
||||||
|
cd jmespath-playground
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Install dependencies**:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start the development server** (macOS optimized):
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or traditional:
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Open your browser** and navigate to `http://localhost:3000`
|
||||||
|
|
||||||
|
### Container Deployment
|
||||||
|
|
||||||
|
#### macOS with Apple Container (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build using macOS-optimized script
|
||||||
|
npm run build:macos
|
||||||
|
|
||||||
|
# Or manually with Apple container command
|
||||||
|
container build -t jmespath-playground .
|
||||||
|
container run -p 3000:3000 jmespath-playground
|
||||||
|
|
||||||
|
# Using npm scripts
|
||||||
|
npm run container:build
|
||||||
|
npm run container:run
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker (Fallback Option)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build the Docker image
|
||||||
|
docker build -t jmespath-playground .
|
||||||
|
|
||||||
|
# Run the container
|
||||||
|
docker run -p 3000:3000 jmespath-playground
|
||||||
|
|
||||||
|
# Using npm scripts
|
||||||
|
npm run docker:build
|
||||||
|
npm run docker:run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. **Enter a JMESPath expression** in the top input field (e.g., `people[*].name`)
|
||||||
|
2. **Paste or type JSON data** in the bottom-left textarea
|
||||||
|
3. **View the results** in the bottom-right output area
|
||||||
|
4. **Use the toolbar buttons** to:
|
||||||
|
- Load sample data
|
||||||
|
- Format JSON
|
||||||
|
- Clear all inputs
|
||||||
|
|
||||||
|
### Example JMESPath Expressions
|
||||||
|
|
||||||
|
Try these examples with the sample data:
|
||||||
|
|
||||||
|
- `people[*].name` - Get all names
|
||||||
|
- `people[0]` - Get the first person
|
||||||
|
- `people[?age > 30]` - Filter people older than 30
|
||||||
|
- `people[*].skills[0]` - Get the first skill of each person
|
||||||
|
- `length(people)` - Count the number of people
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
In the project directory, you can run:
|
||||||
|
|
||||||
|
### Development Scripts
|
||||||
|
|
||||||
|
### `npm run dev`
|
||||||
|
|
||||||
|
Starts the development server with macOS optimizations. Checks environment and opens the app at http://localhost:3000.
|
||||||
|
|
||||||
|
### `npm start`
|
||||||
|
|
||||||
|
Runs the app in development mode using React's default development server. The page will reload when you make edits.
|
||||||
|
|
||||||
|
### `npm test`
|
||||||
|
|
||||||
|
Launches the test runner in interactive watch mode.
|
||||||
|
|
||||||
|
### Build Scripts
|
||||||
|
|
||||||
|
### `npm run build:macos`
|
||||||
|
|
||||||
|
Builds the application and creates containers using macOS-optimized build script. Prioritizes Apple's container command with Docker fallback.
|
||||||
|
|
||||||
|
### `npm run build`
|
||||||
|
|
||||||
|
Builds the app for production to the `build` folder. It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||||
|
|
||||||
|
### `npm run serve`
|
||||||
|
|
||||||
|
Serves the production build locally on port 3000.
|
||||||
|
|
||||||
|
### Container Scripts
|
||||||
|
|
||||||
|
### `npm run container:build`
|
||||||
|
|
||||||
|
Builds a container using Apple's container command (macOS).
|
||||||
|
|
||||||
|
### `npm run container:run`
|
||||||
|
|
||||||
|
Runs the container using Apple's container command.
|
||||||
|
|
||||||
|
### `npm run docker:build`
|
||||||
|
|
||||||
|
Builds a Docker container (fallback option).
|
||||||
|
|
||||||
|
### `npm run docker:run`
|
||||||
|
|
||||||
|
Runs the Docker container.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
jmespath-playground/
|
||||||
|
├── .github/
|
||||||
|
│ ├── workflows/
|
||||||
|
│ │ └── build-container.yml # CI/CD pipeline
|
||||||
|
│ └── copilot-instructions.md # AI agent instructions
|
||||||
|
├── public/
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── manifest.json
|
||||||
|
│ └── favicon.ico
|
||||||
|
├── src/
|
||||||
|
│ ├── App.js # Main application component
|
||||||
|
│ ├── App.css # App-specific styles
|
||||||
|
│ ├── App.test.js # App tests
|
||||||
|
│ ├── index.js # React entry point
|
||||||
|
│ ├── index.css # Global styles
|
||||||
|
│ ├── setupTests.js # Test configuration
|
||||||
|
│ └── reportWebVitals.js
|
||||||
|
├── scripts/
|
||||||
|
│ ├── build.sh # macOS-optimized build script
|
||||||
|
│ └── dev.sh # macOS-optimized development script
|
||||||
|
├── Containerfile # Apple container build file
|
||||||
|
├── Dockerfile # Docker container (fallback)
|
||||||
|
├── Dockerfile.dev # Development container
|
||||||
|
├── docker-compose.yml # Container orchestration
|
||||||
|
├── package.json # Dependencies and scripts
|
||||||
|
├── README.md # Comprehensive documentation
|
||||||
|
├── DEVELOPMENT.md # Developer guide
|
||||||
|
└── demo.sh # Demo script
|
||||||
|
```
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
- **React 18.2.0**: Frontend framework
|
||||||
|
- **Bootstrap 5.3.2**: CSS framework for styling
|
||||||
|
- **JMESPath 0.16.0**: JMESPath expression evaluation
|
||||||
|
- **Node.js 24 LTS**: Runtime environment
|
||||||
|
- **Apple Container**: Primary containerization (macOS)
|
||||||
|
- **Docker**: Containerization fallback
|
||||||
|
- **GitHub Actions**: Automated CI/CD pipeline
|
||||||
|
|
||||||
|
## CI/CD Pipeline
|
||||||
|
|
||||||
|
The project includes a GitHub Actions workflow that automatically:
|
||||||
|
|
||||||
|
- 🔍 **Triggers** on pushes to `main` or `develop` branches when `src/` directory changes
|
||||||
|
- 📦 **Builds** the React application with Node.js 24 LTS
|
||||||
|
- 🧪 **Runs** the test suite with coverage reporting
|
||||||
|
- 🐳 **Creates** container image using Docker (GitHub Actions environment)
|
||||||
|
- ✅ **Tests** the container by starting it and verifying HTTP response
|
||||||
|
- 🏗️ **Builds** multi-platform images (amd64/arm64) for main branch
|
||||||
|
- 📤 **Uploads** build artifacts for later use
|
||||||
|
|
||||||
|
The workflow is optimized for the GitHub Actions environment while respecting the project's macOS-first philosophy for local development.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Container Deployment (macOS Recommended)
|
||||||
|
|
||||||
|
The application is designed for macOS-first containerization:
|
||||||
|
|
||||||
|
1. **Build using macOS toolset**:
|
||||||
|
```bash
|
||||||
|
npm run build:macos
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy using Apple container command**:
|
||||||
|
```bash
|
||||||
|
container run -p 3000:3000 jmespath-playground
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Deployment (Fallback)
|
||||||
|
|
||||||
|
For environments without Apple's container toolset:
|
||||||
|
|
||||||
|
1. **Build the Docker image**:
|
||||||
|
```bash
|
||||||
|
docker build -t jmespath-playground .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy to your container platform** (Docker Swarm, Kubernetes, etc.)
|
||||||
|
|
||||||
|
### Static Hosting
|
||||||
|
|
||||||
|
You can also deploy the built application to static hosting services:
|
||||||
|
|
||||||
|
1. **Build the application**:
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy the `build` folder** to services like:
|
||||||
|
- Netlify
|
||||||
|
- Vercel
|
||||||
|
- GitHub Pages
|
||||||
|
- AWS S3 + CloudFront
|
||||||
|
- Azure Static Web Apps
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch: `git checkout -b feature/new-feature`
|
||||||
|
3. Make your changes and commit them: `git commit -m 'Add new feature'`
|
||||||
|
4. Push to the branch: `git push origin feature/new-feature`
|
||||||
|
5. Submit a pull request
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## About JMESPath
|
||||||
|
|
||||||
|
JMESPath is a query language for JSON. It allows you to declaratively specify how to extract elements from a JSON document. For more information about JMESPath syntax and capabilities, visit the [official JMESPath website](https://jmespath.org/).
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If you encounter any issues or have questions, please [open an issue](../../issues) on GitHub.
|
||||||
71
demo.sh
Executable file
71
demo.sh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# JMESPath Testing Tool - Demo Script
|
||||||
|
# Optimized for macOS with Apple container command
|
||||||
|
|
||||||
|
echo "🍎 JMESPath Testing Tool Demo"
|
||||||
|
echo "==============================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if running on macOS
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
echo "✅ Running on macOS (recommended platform)"
|
||||||
|
else
|
||||||
|
echo "⚠️ Not running on macOS. This demo is optimized for macOS."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Node.js is installed
|
||||||
|
if command -v node &> /dev/null; then
|
||||||
|
echo "✅ Node.js version: $(node --version)"
|
||||||
|
else
|
||||||
|
echo "❌ Node.js not found. Please install Node.js 24 LTS or higher."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if npm is installed
|
||||||
|
if command -v npm &> /dev/null; then
|
||||||
|
echo "✅ npm version: $(npm --version)"
|
||||||
|
else
|
||||||
|
echo "❌ npm not found. Please install npm."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check container runtimes
|
||||||
|
if command -v container &> /dev/null; then
|
||||||
|
echo "✅ Apple container command available"
|
||||||
|
else
|
||||||
|
echo "⚠️ Apple container command not found"
|
||||||
|
if command -v docker &> /dev/null; then
|
||||||
|
echo "✅ Docker available as fallback"
|
||||||
|
else
|
||||||
|
echo "⚠️ No container runtime found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📦 Installing dependencies..."
|
||||||
|
npm install
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔨 Building with macOS-optimized script..."
|
||||||
|
npm run build:macos
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🎉 Demo completed successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "To start development (macOS optimized):"
|
||||||
|
echo " npm run dev"
|
||||||
|
echo ""
|
||||||
|
echo "To start development (traditional):"
|
||||||
|
echo " npm start"
|
||||||
|
echo ""
|
||||||
|
echo "To serve the production build:"
|
||||||
|
echo " npm run serve"
|
||||||
|
echo ""
|
||||||
|
echo "To run with containers:"
|
||||||
|
if command -v container &> /dev/null; then
|
||||||
|
echo " npm run container:run # Apple container (recommended)"
|
||||||
|
fi
|
||||||
|
if command -v docker &> /dev/null; then
|
||||||
|
echo " npm run docker:run # Docker (fallback)"
|
||||||
|
fi
|
||||||
25
docker-compose.yml
Normal file
25
docker-compose.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
jmespath-playground:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# Development service
|
||||||
|
jmespath-playground-dev:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
|
ports:
|
||||||
|
- "3001:3000"
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
- /app/node_modules
|
||||||
|
environment:
|
||||||
|
- CHOKIDAR_USEPOLLING=true
|
||||||
|
profiles:
|
||||||
|
- dev
|
||||||
18011
package-lock.json
generated
Normal file
18011
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
62
package.json
Normal file
62
package.json
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"name": "jmespath-playground",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A React-based web application for testing JMESPath expressions against JSON data",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject",
|
||||||
|
"serve": "serve -s build -l 3000",
|
||||||
|
"dev": "./scripts/dev.sh",
|
||||||
|
"build:macos": "./scripts/build.sh",
|
||||||
|
"container:build": "container build -t jmespath-playground .",
|
||||||
|
"container:run": "container run -p 3000:3000 jmespath-playground",
|
||||||
|
"docker:build": "docker build -t jmespath-playground .",
|
||||||
|
"docker:run": "docker run -p 3000:3000 jmespath-playground"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=24.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@testing-library/jest-dom": "^6.1.4",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
|
"@testing-library/user-event": "^14.5.1",
|
||||||
|
"bootstrap": "^5.3.2",
|
||||||
|
"jmespath": "^0.16.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-scripts": "^5.0.1",
|
||||||
|
"serve": "^14.2.1",
|
||||||
|
"web-vitals": "^3.5.0"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": [
|
||||||
|
"react-app",
|
||||||
|
"react-app/jest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 1 chrome version",
|
||||||
|
"last 1 firefox version",
|
||||||
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"jmespath",
|
||||||
|
"json",
|
||||||
|
"query",
|
||||||
|
"testing",
|
||||||
|
"react",
|
||||||
|
"macos"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 207 B |
17
public/index.html
Normal file
17
public/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="description" content="JMESPath Testing Tool - Validate and test JMESPath expressions against JSON data" />
|
||||||
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
<title>JMESPath Testing Tool</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
15
public/manifest.json
Normal file
15
public/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"short_name": "JMESPath Tool",
|
||||||
|
"name": "JMESPath Testing Tool",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
57
scripts/build.sh
Executable file
57
scripts/build.sh
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# JMESPath Testing Tool - Build Script
|
||||||
|
# Targets macOS with Apple container command as first-class environment
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🍎 JMESPath Testing Tool - macOS Build Script"
|
||||||
|
echo "============================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Node.js version
|
||||||
|
if command -v node &> /dev/null; then
|
||||||
|
NODE_VERSION=$(node --version | sed 's/v//')
|
||||||
|
MAJOR_VERSION=$(echo $NODE_VERSION | cut -d. -f1)
|
||||||
|
if [ "$MAJOR_VERSION" -ge 24 ]; then
|
||||||
|
echo "✅ Node.js $NODE_VERSION (compatible with v24+ requirement)"
|
||||||
|
else
|
||||||
|
echo "❌ Node.js $NODE_VERSION found, but v24+ is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "❌ Node.js not found. Please install Node.js 24 LTS or higher."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the React application
|
||||||
|
echo "📦 Installing dependencies..."
|
||||||
|
npm install
|
||||||
|
|
||||||
|
echo "🔨 Building production bundle..."
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Container build - prioritize Apple container command
|
||||||
|
if command -v container &> /dev/null; then
|
||||||
|
echo "🍎 Building container with Apple container command..."
|
||||||
|
container build -t jmespath-playground .
|
||||||
|
else
|
||||||
|
# Fallback to Docker if available
|
||||||
|
if command -v docker &> /dev/null; then
|
||||||
|
echo "🐳 Apple container command not found, falling back to Docker..."
|
||||||
|
docker build -t jmespath-playground .
|
||||||
|
else
|
||||||
|
echo "⚠️ No container runtime found. Skipping container build."
|
||||||
|
echo " Install Apple container command or Docker to build containers."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Build completed successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "To run the application:"
|
||||||
|
echo " npm run serve # Serve production build locally"
|
||||||
|
if command -v container &> /dev/null; then
|
||||||
|
echo " container run -p 3000:3000 jmespath-playground # Run with Apple container"
|
||||||
|
elif command -v docker &> /dev/null; then
|
||||||
|
echo " docker run -p 3000:3000 jmespath-playground # Run with Docker"
|
||||||
|
fi
|
||||||
38
scripts/dev.sh
Executable file
38
scripts/dev.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# JMESPath Testing Tool - Development Script
|
||||||
|
# Optimized for macOS development environment
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🍎 JMESPath Testing Tool - macOS Development"
|
||||||
|
echo "==========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check environment
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
echo "✅ Running on macOS"
|
||||||
|
else
|
||||||
|
echo "⚠️ This script is optimized for macOS but will attempt to run anyway."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Node.js
|
||||||
|
if command -v node &> /dev/null; then
|
||||||
|
echo "✅ Node.js version: $(node --version)"
|
||||||
|
else
|
||||||
|
echo "❌ Node.js not found. Please install Node.js 24 LTS."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install dependencies if needed
|
||||||
|
if [ ! -d "node_modules" ]; then
|
||||||
|
echo "📦 Installing dependencies..."
|
||||||
|
npm install
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start development server
|
||||||
|
echo "🚀 Starting development server..."
|
||||||
|
echo " The app will open at http://localhost:3000"
|
||||||
|
echo " Press Ctrl+C to stop the server"
|
||||||
|
echo ""
|
||||||
|
npm start
|
||||||
69
src/App.css
Normal file
69
src/App.css
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
.App {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-logo {
|
||||||
|
height: 40vmin;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-header {
|
||||||
|
background-color: #282c34;
|
||||||
|
padding: 20px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-link {
|
||||||
|
color: #61dafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes App-logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom card styling */
|
||||||
|
.card {
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-bottom: 2px solid #dee2e6;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button hover effects */
|
||||||
|
.btn {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive adjustments */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.header-section {
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-4 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
240
src/App.js
Normal file
240
src/App.js
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import jmespath from 'jmespath';
|
||||||
|
import './App.css';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const [jmespathExpression, setJmespathExpression] = useState('people[0].name');
|
||||||
|
const [jsonData, setJsonData] = useState(`{
|
||||||
|
"people": [
|
||||||
|
{
|
||||||
|
"name": "John Doe",
|
||||||
|
"age": 30,
|
||||||
|
"city": "New York"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jane Smith",
|
||||||
|
"age": 25,
|
||||||
|
"city": "Los Angeles"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2
|
||||||
|
}`);
|
||||||
|
const [result, setResult] = useState('');
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
const [jsonError, setJsonError] = useState('');
|
||||||
|
|
||||||
|
const evaluateExpression = () => {
|
||||||
|
try {
|
||||||
|
// Clear previous errors
|
||||||
|
setError('');
|
||||||
|
setJsonError('');
|
||||||
|
|
||||||
|
// Validate and parse JSON
|
||||||
|
let parsedData;
|
||||||
|
try {
|
||||||
|
parsedData = JSON.parse(jsonData);
|
||||||
|
} catch (jsonErr) {
|
||||||
|
setJsonError(`Invalid JSON: ${jsonErr.message}`);
|
||||||
|
setResult('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate JMESPath expression
|
||||||
|
const queryResult = jmespath.search(parsedData, jmespathExpression);
|
||||||
|
|
||||||
|
// Format the result
|
||||||
|
if (queryResult === null || queryResult === undefined) {
|
||||||
|
setResult('null');
|
||||||
|
} else {
|
||||||
|
setResult(JSON.stringify(queryResult, null, 2));
|
||||||
|
}
|
||||||
|
} catch (jmesErr) {
|
||||||
|
setError(`JMESPath Error: ${jmesErr.message}`);
|
||||||
|
setResult('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Auto-evaluate when inputs change
|
||||||
|
useEffect(() => {
|
||||||
|
if (jmespathExpression && jsonData) {
|
||||||
|
evaluateExpression();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [jmespathExpression, jsonData]);
|
||||||
|
|
||||||
|
const handleJmespathChange = (e) => {
|
||||||
|
setJmespathExpression(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleJsonChange = (e) => {
|
||||||
|
setJsonData(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatJson = () => {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(jsonData);
|
||||||
|
setJsonData(JSON.stringify(parsed, null, 2));
|
||||||
|
} catch (err) {
|
||||||
|
// If JSON is invalid, don't format
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearAll = () => {
|
||||||
|
setJmespathExpression('');
|
||||||
|
setJsonData('');
|
||||||
|
setResult('');
|
||||||
|
setError('');
|
||||||
|
setJsonError('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadSample = () => {
|
||||||
|
setJmespathExpression('people[*].name');
|
||||||
|
setJsonData(`{
|
||||||
|
"people": [
|
||||||
|
{
|
||||||
|
"name": "Alice Johnson",
|
||||||
|
"age": 28,
|
||||||
|
"city": "Chicago",
|
||||||
|
"skills": ["JavaScript", "React", "Node.js"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bob Wilson",
|
||||||
|
"age": 35,
|
||||||
|
"city": "Seattle",
|
||||||
|
"skills": ["Python", "Django", "PostgreSQL"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Carol Davis",
|
||||||
|
"age": 32,
|
||||||
|
"city": "Austin",
|
||||||
|
"skills": ["Java", "Spring", "MySQL"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 3,
|
||||||
|
"department": "Engineering"
|
||||||
|
}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container-fluid">
|
||||||
|
{/* Header Section */}
|
||||||
|
<div className="header-section">
|
||||||
|
<div className="container">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 text-center">
|
||||||
|
<h1 className="display-4 mb-3">JMESPath Testing Tool</h1>
|
||||||
|
<p className="lead">
|
||||||
|
Validate and test JMESPath expressions against JSON data in real-time.
|
||||||
|
Enter your JMESPath query and JSON data below to see the results instantly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="container-fluid content-section">
|
||||||
|
<div className="row h-100">
|
||||||
|
{/* JMESPath Expression Input - Middle Section */}
|
||||||
|
<div className="col-12 mb-3">
|
||||||
|
<div className="card">
|
||||||
|
<div className="card-header d-flex justify-content-between align-items-center">
|
||||||
|
<h5 className="mb-0">
|
||||||
|
<i className="bi bi-search me-2"></i>
|
||||||
|
JMESPath Expression
|
||||||
|
</h5>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="btn btn-outline-primary btn-sm me-2"
|
||||||
|
onClick={loadSample}
|
||||||
|
title="Load sample data"
|
||||||
|
>
|
||||||
|
Load Sample
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-outline-danger btn-sm"
|
||||||
|
onClick={clearAll}
|
||||||
|
title="Clear all inputs"
|
||||||
|
>
|
||||||
|
Clear All
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className={`form-control jmespath-input ${error ? 'error' : ''}`}
|
||||||
|
value={jmespathExpression}
|
||||||
|
onChange={handleJmespathChange}
|
||||||
|
placeholder="Enter JMESPath expression (e.g., people[*].name)"
|
||||||
|
/>
|
||||||
|
{error && (
|
||||||
|
<div className="alert alert-danger mt-2 mb-0">
|
||||||
|
<small>{error}</small>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom Row - JSON Input and Results */}
|
||||||
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="card h-100">
|
||||||
|
<div className="card-header d-flex justify-content-between align-items-center">
|
||||||
|
<h5 className="mb-0">
|
||||||
|
<i className="bi bi-file-code me-2"></i>
|
||||||
|
JSON Data
|
||||||
|
</h5>
|
||||||
|
<button
|
||||||
|
className="btn btn-outline-secondary btn-sm"
|
||||||
|
onClick={formatJson}
|
||||||
|
title="Format JSON"
|
||||||
|
>
|
||||||
|
Format JSON
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="card-body input-section">
|
||||||
|
<div className="textarea-container">
|
||||||
|
<textarea
|
||||||
|
className={`form-control json-input ${jsonError ? 'error' : ''}`}
|
||||||
|
value={jsonData}
|
||||||
|
onChange={handleJsonChange}
|
||||||
|
placeholder="Enter JSON data here..."
|
||||||
|
/>
|
||||||
|
{jsonError && (
|
||||||
|
<div className="alert alert-danger mt-2 mb-0">
|
||||||
|
<small>{jsonError}</small>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Results Output - Bottom Right */}
|
||||||
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="card h-100">
|
||||||
|
<div className="card-header">
|
||||||
|
<h5 className="mb-0">
|
||||||
|
<i className="bi bi-arrow-right-circle me-2"></i>
|
||||||
|
Query Result
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div className="card-body output-section">
|
||||||
|
<div className="textarea-container">
|
||||||
|
<textarea
|
||||||
|
className={`form-control result-output ${result && !error && !jsonError ? 'success' : ''}`}
|
||||||
|
value={result}
|
||||||
|
readOnly
|
||||||
|
placeholder="Results will appear here..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
22
src/App.test.js
Normal file
22
src/App.test.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
test('renders JMESPath Testing Tool title', () => {
|
||||||
|
render(<App />);
|
||||||
|
const titleElement = screen.getByText(/JMESPath Testing Tool/i);
|
||||||
|
expect(titleElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('renders input areas', () => {
|
||||||
|
render(<App />);
|
||||||
|
const jmespathInput = screen.getByPlaceholderText(/Enter JMESPath expression/i);
|
||||||
|
const jsonInput = screen.getByPlaceholderText(/Enter JSON data here/i);
|
||||||
|
expect(jmespathInput).toBeInTheDocument();
|
||||||
|
expect(jsonInput).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('renders result area', () => {
|
||||||
|
render(<App />);
|
||||||
|
const resultArea = screen.getByPlaceholderText(/Results will appear here/i);
|
||||||
|
expect(resultArea).toBeInTheDocument();
|
||||||
|
});
|
||||||
83
src/index.css
Normal file
83
src/index.css
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
|
monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-section {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textarea-container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
resize: vertical;
|
||||||
|
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-section .form-control {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-section .form-control {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 200px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background-color: #f8d7da !important;
|
||||||
|
border-color: #f5c6cb !important;
|
||||||
|
color: #721c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
background-color: #d4edda !important;
|
||||||
|
border-color: #c3e6cb !important;
|
||||||
|
color: #155724;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 2rem 0;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jmespath-input {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
border-color: #ffeaa7;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-input {
|
||||||
|
background-color: #e8f5e8;
|
||||||
|
border-color: #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-output {
|
||||||
|
background-color: #e7f3ff;
|
||||||
|
border-color: #b3d7ff;
|
||||||
|
}
|
||||||
18
src/index.js
Normal file
18
src/index.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
|
import './index.css';
|
||||||
|
import App from './App';
|
||||||
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
|
reportWebVitals();
|
||||||
13
src/reportWebVitals.js
Normal file
13
src/reportWebVitals.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const reportWebVitals = onPerfEntry => {
|
||||||
|
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||||
|
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||||
|
getCLS(onPerfEntry);
|
||||||
|
getFID(onPerfEntry);
|
||||||
|
getFCP(onPerfEntry);
|
||||||
|
getLCP(onPerfEntry);
|
||||||
|
getTTFB(onPerfEntry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reportWebVitals;
|
||||||
5
src/setupTests.js
Normal file
5
src/setupTests.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
|
// allows you to do things like:
|
||||||
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
Reference in New Issue
Block a user