diff --git a/README.md b/README.md index a8de8cd..520e919 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,39 @@ ### Usage #### `npm start` -Starts the reference docs preview server. +Starts the Redocly reference docs preview server. + +#### `npm start:swagger` +Starts a local server to preview Swagger UI (requires building first). #### `npm run build` -Bundles the definition to the dist folder. +Builds both Redocly documentation and Swagger UI to the dist folder. + +#### `npm run build:redocly` +Builds only the Redocly documentation. + +#### `npm run build:swagger` +Builds only the Swagger UI. #### `npm test` Validates the definition. +## Documentation Formats + +This repository generates two types of API documentation: + +### Redocly (Main Documentation) +- **Location:** `dist/index.html` +- **Live:** https://greenbuttonalliance.github.io/openapi-starter/ +- **Purpose:** Beautiful, readable API documentation +- **Features:** Clean layout, Green Button theming, comprehensive examples + +### Swagger UI (Interactive Explorer) +- **Location:** `dist/swagger/index.html` +- **Live:** https://greenbuttonalliance.github.io/openapi-starter/swagger/ +- **Purpose:** Interactive API testing and exploration +- **Features:** "Try it out" functionality, request/response testing, OAuth flow + ## Contribution Guide Below is a sample contribution guide. The tools diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 0f7ff9d..deed1cf 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -9,6 +9,9 @@ info: to exchange energy usage information using Atom-formatted XML feeds. + **Interactive API Explorer:** Try out the API using [Swagger UI](./swagger/) + + All resources are returned as Atom feeds (collections) or Atom entries (individual resources) using the `application/atom+xml` content type. The ESPI data elements are embedded within the Atom `` element diff --git a/package-lock.json b/package-lock.json index 9c3722d..2188baa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,9 @@ "version": "1.0.0", "dependencies": { "@redocly/cli": "^2.16.0" + }, + "devDependencies": { + "swagger-ui-dist": "^5.31.0" } }, "node_modules/@babel/code-frame": { @@ -545,6 +548,14 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "license": "MIT" }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2136,6 +2147,16 @@ "node": ">=8" } }, + "node_modules/swagger-ui-dist": { + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.31.0.tgz", + "integrity": "sha512-zSUTIck02fSga6rc0RZP3b7J7wgHXwLea8ZjgLA3Vgnb8QeOl3Wou2/j5QkzSGeoz6HusP/coYuJl33aQxQZpg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, "node_modules/swagger2openapi": { "version": "7.0.8", "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", diff --git a/package.json b/package.json index 4141e23..bf85cee 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,14 @@ "private": true, "scripts": { "start": "redocly preview-docs", - "build": "redocly build-docs openapi/openapi.yaml -o dist/index.html", - "bundle": "redocly bundle openapi/openapi.yaml -o dist/bundle.yaml", + "start:swagger": "npx http-server dist -p 8081", + "build": "npm run build:redocly && npm run build:swagger", + "build:redocly": "redocly build-docs openapi/openapi.yaml -o dist/index.html", + "build:swagger": "npm run bundle && node scripts/build-swagger.js", + "bundle": "redocly bundle openapi/openapi.yaml -o dist/openapi.json", "test": "redocly lint" + }, + "devDependencies": { + "swagger-ui-dist": "^5.31.0" } } diff --git a/scripts/build-swagger.js b/scripts/build-swagger.js new file mode 100755 index 0000000..ab16305 --- /dev/null +++ b/scripts/build-swagger.js @@ -0,0 +1,132 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); + +// Create dist/swagger directory +const swaggerDir = path.join(__dirname, '..', 'dist', 'swagger'); +if (!fs.existsSync(swaggerDir)) { + fs.mkdirSync(swaggerDir, { recursive: true }); +} + +// Copy Swagger UI assets +const swaggerUiPath = path.join(__dirname, '..', 'node_modules', 'swagger-ui-dist'); +const files = fs.readdirSync(swaggerUiPath); + +files.forEach(file => { + if (file.endsWith('.js') || file.endsWith('.css') || file.endsWith('.map') || file.endsWith('.png')) { + fs.copyFileSync( + path.join(swaggerUiPath, file), + path.join(swaggerDir, file) + ); + } +}); + +// Copy bundled OpenAPI spec +fs.copyFileSync( + path.join(__dirname, '..', 'dist', 'openapi.json'), + path.join(swaggerDir, 'openapi.json') +); + +// Create custom Swagger UI HTML with Green Button branding +const html = ` + + + + Green Button ESPI API - Swagger UI + + + + + +
+ 📖 View Documentation (Redocly) +
+
+ + + + +`; + +fs.writeFileSync(path.join(swaggerDir, 'index.html'), html); + +console.log('✅ Swagger UI built successfully at dist/swagger/'); +console.log(' - Redocly docs: dist/index.html'); +console.log(' - Swagger UI: dist/swagger/index.html');