Skip to content

Commit 37c2688

Browse files
committed
ES modules
1 parent cf54121 commit 37c2688

20 files changed

+297
-53
lines changed

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
{
22
"name": "api-explorer",
33
"version": "1.1.3",
4+
"type": "module",
45
"private": true,
56
"types": [
67
"jest"
78
],
89
"scripts": {
910
"dev": "vite & tsx --tsconfig tsconfig.server.json server/app.ts",
10-
"build": "run-p build-only",
11+
"build": "run-p build-only build-server",
1112
"build-server": "tsc --project tsconfig.server.json",
13+
"build-production": "npm run build",
14+
"test-production": "./scripts/build-and-test-production.sh",
15+
"start": "node dist-server/server/app.js",
1216
"preview": "vite preview",
1317
"test": "vitest",
1418
"build-only": "vite build",
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#!/bin/bash
2+
3+
# Production Build and Test Script for API Explorer II
4+
# This script builds both frontend and backend, then tests as if on a production server
5+
6+
set -e # Exit on error
7+
8+
# Colors for output
9+
RED='\033[0;31m'
10+
GREEN='\033[0;32m'
11+
YELLOW='\033[1;33m'
12+
BLUE='\033[0;34m'
13+
NC='\033[0m' # No Color
14+
15+
echo -e "${BLUE}========================================${NC}"
16+
echo -e "${BLUE}API Explorer II - Production Build Test${NC}"
17+
echo -e "${BLUE}========================================${NC}"
18+
echo ""
19+
20+
# Function to print colored output
21+
print_status() {
22+
echo -e "${GREEN}[✓]${NC} $1"
23+
}
24+
25+
print_error() {
26+
echo -e "${RED}[✗]${NC} $1"
27+
}
28+
29+
print_info() {
30+
echo -e "${YELLOW}[i]${NC} $1"
31+
}
32+
33+
# Check if we're in the right directory
34+
if [ ! -f "package.json" ]; then
35+
print_error "package.json not found. Please run this script from the API-Explorer-II directory."
36+
exit 1
37+
fi
38+
39+
print_info "Starting production build and test process..."
40+
echo ""
41+
42+
# Step 1: Clean previous builds
43+
echo -e "${BLUE}Step 1: Cleaning previous builds${NC}"
44+
if [ -d "dist" ]; then
45+
rm -rf dist
46+
print_status "Removed old frontend build (dist/)"
47+
fi
48+
49+
if [ -d "dist-server" ]; then
50+
rm -rf dist-server
51+
print_status "Removed old backend build (dist-server/)"
52+
fi
53+
echo ""
54+
55+
# Step 2: Check environment variables
56+
echo -e "${BLUE}Step 2: Checking environment configuration${NC}"
57+
if [ -f ".env" ]; then
58+
print_status "Found .env file"
59+
else
60+
print_error ".env file not found"
61+
print_info "Copy .env.example to .env and configure it"
62+
exit 1
63+
fi
64+
65+
# Check critical environment variables
66+
if grep -q "VITE_OBP_API_HOST" .env; then
67+
print_status "VITE_OBP_API_HOST is configured"
68+
else
69+
print_error "VITE_OBP_API_HOST not found in .env"
70+
exit 1
71+
fi
72+
echo ""
73+
74+
# Step 3: Install dependencies
75+
echo -e "${BLUE}Step 3: Installing dependencies${NC}"
76+
print_info "Running npm ci (clean install)..."
77+
npm ci --quiet
78+
print_status "Dependencies installed"
79+
echo ""
80+
81+
# Step 4: Build frontend
82+
echo -e "${BLUE}Step 4: Building frontend (Vite)${NC}"
83+
print_info "Running: npm run build-only"
84+
npm run build-only
85+
if [ -d "dist" ]; then
86+
DIST_SIZE=$(du -sh dist | cut -f1)
87+
print_status "Frontend built successfully (size: $DIST_SIZE)"
88+
else
89+
print_error "Frontend build failed - dist/ directory not created"
90+
exit 1
91+
fi
92+
echo ""
93+
94+
# Step 5: Build backend
95+
echo -e "${BLUE}Step 5: Building backend (TypeScript ES Modules)${NC}"
96+
print_info "Running: npm run build-server"
97+
npm run build-server
98+
if [ -d "dist-server" ]; then
99+
print_status "Backend built successfully"
100+
else
101+
print_error "Backend build failed - dist-server/ directory not created"
102+
exit 1
103+
fi
104+
105+
# Check if main app file exists
106+
if [ -f "dist-server/server/app.js" ]; then
107+
print_status "Server entry point found: dist-server/server/app.js"
108+
else
109+
print_error "Server entry point not found: dist-server/server/app.js"
110+
exit 1
111+
fi
112+
echo ""
113+
114+
# Step 6: Verify ES Module format
115+
echo -e "${BLUE}Step 6: Verifying ES Module format${NC}"
116+
if head -50 dist-server/server/app.js | grep -E "^import " | head -1 > /dev/null; then
117+
print_status "Backend is using ES modules (import statements found)"
118+
else
119+
print_error "Backend is not using ES modules - CommonJS detected"
120+
exit 1
121+
fi
122+
123+
if grep -q '"type": "module"' package.json; then
124+
print_status "package.json has type: module"
125+
else
126+
print_error 'package.json missing "type": "module"'
127+
exit 1
128+
fi
129+
echo ""
130+
131+
# Step 7: Check for Redis
132+
echo -e "${BLUE}Step 7: Checking dependencies${NC}"
133+
print_info "Checking if Redis is running..."
134+
if redis-cli ping > /dev/null 2>&1; then
135+
print_status "Redis is running"
136+
else
137+
print_error "Redis is not running"
138+
print_info "Start Redis with: redis-server"
139+
print_info "Or using Docker: docker run -d -p 6379:6379 redis"
140+
fi
141+
echo ""
142+
143+
# Step 8: Test server startup
144+
echo -e "${BLUE}Step 8: Testing server startup${NC}"
145+
print_info "Starting server for 5 seconds to test..."
146+
147+
# Start server in background
148+
timeout 5 node dist-server/server/app.js > /tmp/api-explorer-test.log 2>&1 || true
149+
150+
# Check the log
151+
if grep -q "Backend is running" /tmp/api-explorer-test.log; then
152+
print_status "Server started successfully"
153+
154+
# Show key startup info
155+
if grep -q "OAuth2Service: Initialization successful" /tmp/api-explorer-test.log; then
156+
print_status "OAuth2 service initialized"
157+
fi
158+
159+
if grep -q "Connected to Redis" /tmp/api-explorer-test.log; then
160+
print_status "Redis connection established"
161+
fi
162+
else
163+
print_error "Server failed to start"
164+
print_info "Check logs at /tmp/api-explorer-test.log"
165+
cat /tmp/api-explorer-test.log
166+
exit 1
167+
fi
168+
echo ""
169+
170+
# Step 9: Show build summary
171+
echo -e "${BLUE}========================================${NC}"
172+
echo -e "${GREEN}Build Summary${NC}"
173+
echo -e "${BLUE}========================================${NC}"
174+
echo ""
175+
echo "Frontend build:"
176+
echo " Location: $(pwd)/dist"
177+
echo " Size: $DIST_SIZE"
178+
echo " Files: $(find dist -type f | wc -l)"
179+
echo ""
180+
echo "Backend build:"
181+
echo " Location: $(pwd)/dist-server"
182+
echo " Entry: dist-server/server/app.js"
183+
echo " Module type: ES Modules"
184+
echo ""
185+
echo "To run in production:"
186+
echo -e " ${YELLOW}node dist-server/server/app.js${NC}"
187+
echo ""
188+
echo "Frontend files can be served by the backend or a web server:"
189+
echo -e " ${YELLOW}The backend serves frontend from dist/ automatically${NC}"
190+
echo ""
191+
192+
# Step 10: Production readiness checklist
193+
echo -e "${BLUE}========================================${NC}"
194+
echo -e "${YELLOW}Production Readiness Checklist${NC}"
195+
echo -e "${BLUE}========================================${NC}"
196+
echo ""
197+
echo "✓ Frontend built and optimized"
198+
echo "✓ Backend compiled to ES modules"
199+
echo "✓ Server starts without errors"
200+
echo "✓ Dependencies installed"
201+
echo ""
202+
echo "Before deploying to production:"
203+
echo " 1. Configure production .env file"
204+
echo " 2. Ensure Redis is running and accessible"
205+
echo " 3. Set NODE_ENV=production"
206+
echo " 4. Configure OBP API host and credentials"
207+
echo " 5. Set up OAuth2/OIDC client credentials"
208+
echo " 6. Configure process manager (PM2, systemd, etc.)"
209+
echo " 7. Set up reverse proxy (nginx, Apache, etc.)"
210+
echo ""
211+
212+
print_status "Production build test completed successfully!"
213+
echo ""
214+
215+
# Cleanup
216+
rm -f /tmp/api-explorer-test.log

server/app.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,31 @@ import 'dotenv/config'
3030
import session from 'express-session'
3131
import RedisStore from 'connect-redis'
3232
import { createClient } from 'redis'
33-
import express, { Application } from 'express'
33+
import express from 'express'
34+
import type { Application } from 'express'
3435
import { useExpressServer, useContainer } from 'routing-controllers'
3536
import { Container } from 'typedi'
3637
import path from 'path'
3738
import { execSync } from 'child_process'
38-
import { OAuth2Service } from './services/OAuth2Service'
39-
40-
// __dirname is available in CommonJS
41-
// const __dirname is automatically available
39+
import { OAuth2Service } from './services/OAuth2Service.js'
40+
import { fileURLToPath } from 'url'
41+
import { dirname } from 'path'
42+
43+
// Import controllers
44+
import { OpeyController } from './controllers/OpeyIIController.js'
45+
import { OBPController } from './controllers/RequestController.js'
46+
import { StatusController } from './controllers/StatusController.js'
47+
import { UserController } from './controllers/UserController.js'
48+
import { OAuth2CallbackController } from './controllers/OAuth2CallbackController.js'
49+
import { OAuth2ConnectController } from './controllers/OAuth2ConnectController.js'
50+
51+
// Import middlewares
52+
import OAuth2AuthorizationMiddleware from './middlewares/OAuth2AuthorizationMiddleware.js'
53+
import OAuth2CallbackMiddleware from './middlewares/OAuth2CallbackMiddleware.js'
54+
55+
// ES module equivalent of __dirname
56+
const __filename = fileURLToPath(import.meta.url)
57+
const __dirname = dirname(__filename)
4258

4359
const port = 8085
4460
const app: Application = express()
@@ -151,8 +167,15 @@ let instance: any
151167

152168
const server = useExpressServer(app, {
153169
routePrefix: routePrefix,
154-
controllers: [path.join(__dirname + '/controllers/*.*s')],
155-
middlewares: [path.join(__dirname + '/middlewares/*.*s')]
170+
controllers: [
171+
OpeyController,
172+
OBPController,
173+
StatusController,
174+
UserController,
175+
OAuth2CallbackController,
176+
OAuth2ConnectController
177+
],
178+
middlewares: [OAuth2AuthorizationMiddleware, OAuth2CallbackMiddleware]
156179
})
157180

158181
instance = server.listen(port)

server/controllers/OAuth2CallbackController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
*/
2727

2828
import { Controller, Req, Res, Get, UseBefore } from 'routing-controllers'
29-
import { Request, Response } from 'express'
29+
import type { Request, Response } from 'express'
3030
import { Service } from 'typedi'
31-
import OAuth2CallbackMiddleware from '../middlewares/OAuth2CallbackMiddleware'
31+
import OAuth2CallbackMiddleware from '../middlewares/OAuth2CallbackMiddleware.js'
3232

3333
/**
3434
* OAuth2 Callback Controller

server/controllers/OAuth2ConnectController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
*/
2727

2828
import { Controller, Req, Res, Get, UseBefore } from 'routing-controllers'
29-
import { Request, Response } from 'express'
29+
import type { Request, Response } from 'express'
3030
import { Service } from 'typedi'
31-
import OAuth2AuthorizationMiddleware from '../middlewares/OAuth2AuthorizationMiddleware'
31+
import OAuth2AuthorizationMiddleware from '../middlewares/OAuth2AuthorizationMiddleware.js'
3232

3333
/**
3434
* OAuth2 Connect Controller

server/controllers/OpeyIIController.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { Controller, Session, Req, Res, Post, Get } from 'routing-controllers'
2-
import { Request, Response } from 'express'
2+
import type { Request, Response } from 'express'
33
import { Readable } from 'node:stream'
44
import { ReadableStream as WebReadableStream } from 'stream/web'
55
import { Service, Container } from 'typedi'
6-
import OBPClientService from '../services/OBPClientService'
7-
import OpeyClientService from '../services/OpeyClientService'
8-
import OBPConsentsService from '../services/OBPConsentsService'
6+
import OBPClientService from '../services/OBPClientService.js'
7+
import OpeyClientService from '../services/OpeyClientService.js'
8+
import OBPConsentsService from '../services/OBPConsentsService.js'
99

10-
import { UserInput, OpeyConfig } from '../schema/OpeySchema'
10+
import { UserInput, OpeyConfig } from '../schema/OpeySchema.js'
1111
import {
1212
APIApi,
1313
Configuration,

server/controllers/RequestController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
*/
2727

2828
import { Controller, Session, Req, Res, Get, Delete, Post, Put } from 'routing-controllers'
29-
import { Request, Response } from 'express'
30-
import OBPClientService from '../services/OBPClientService'
29+
import type { Request, Response } from 'express'
30+
import OBPClientService from '../services/OBPClientService.js'
3131
import { Service, Container } from 'typedi'
3232

3333
@Service()

server/controllers/StatusController.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@
2626
*/
2727

2828
import { Controller, Session, Req, Res, Get } from 'routing-controllers'
29-
import { Request, Response } from 'express'
30-
import OBPClientService from '../services/OBPClientService'
29+
import type { Request, Response } from 'express'
30+
import OBPClientService from '../services/OBPClientService.js'
3131

3232
import { Service, Container } from 'typedi'
3333
import { OAuthConfig } from 'obp-typescript'
34-
import { commitId } from '../app'
34+
import { commitId } from '../app.js'
3535
import {
3636
RESOURCE_DOCS_API_VERSION,
3737
MESSAGE_DOCS_API_VERSION,
3838
API_VERSIONS_LIST_API_VERSION
39-
} from '../../src/shared-constants'
39+
} from '../../src/shared-constants.js'
4040

4141
@Service()
4242
@Controller('/status')

server/controllers/UserController.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
*/
2727

2828
import { Controller, Session, Req, Res, Get } from 'routing-controllers'
29-
import { Request, Response } from 'express'
30-
import OBPClientService from '../services/OBPClientService'
29+
import type { Request, Response } from 'express'
30+
import OBPClientService from '../services/OBPClientService.js'
3131
import { Service, Container } from 'typedi'
32-
import { OAuth2Service } from '../services/OAuth2Service'
33-
import { DEFAULT_OBP_API_VERSION } from '../../src/shared-constants'
32+
import { OAuth2Service } from '../services/OAuth2Service.js'
33+
import { DEFAULT_OBP_API_VERSION } from '../../src/shared-constants.js'
3434

3535
@Service()
3636
@Controller('/user')

server/middlewares/OAuth2AuthorizationMiddleware.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
*/
2727

2828
import { ExpressMiddlewareInterface } from 'routing-controllers'
29-
import { Request, Response } from 'express'
29+
import type { Request, Response } from 'express'
3030
import { Service, Container } from 'typedi'
31-
import { OAuth2Service } from '../services/OAuth2Service'
32-
import { PKCEUtils } from '../utils/pkce'
31+
import { OAuth2Service } from '../services/OAuth2Service.js'
32+
import { PKCEUtils } from '../utils/pkce.js'
3333

3434
/**
3535
* OAuth2 Authorization Middleware

0 commit comments

Comments
 (0)