-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathserver.js
More file actions
194 lines (166 loc) · 5.98 KB
/
server.js
File metadata and controls
194 lines (166 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import express from 'express';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { exec } from 'child_process';
import { promisify } from 'util';
// Resolve __dirname and __filename for ESM
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const port = process.env.PORT || 8080;
const inContainer = process.env.CONTAINER;
const inAzure = process.env.WEBSITE_RESOURCE_GROUP;
console.log('inContainer', inContainer);
console.log('inAzure', inAzure);
console.log('__dirname', __dirname);
// Load data from JSON files
const customers = JSON.parse(fs.readFileSync(path.join(__dirname, 'public/data/customers.json'), 'utf-8'));
const states = JSON.parse(fs.readFileSync(path.join(__dirname, 'public/data/states.json'), 'utf-8'));
// Middleware for parsing request bodies
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// CORS middleware
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header(
'Access-Control-Allow-Headers',
'Origin, Authorization, X-Requested-With, X-XSRF-TOKEN, X-InlineCount, Content-Type, Accept'
);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
next();
});
// Serve static files if not running in a container
if (!inContainer) {
app.use(express.static(path.join(__dirname, 'dist/angular-jumpstart/browser')));
console.log(`Static files served from ${path.join(__dirname, 'dist/angular-jumpstart/browser')}`);
}
// Helper function to safely fetch a customer by ID
const getCustomerById = (id) => customers.find((customer) => customer.id === id);
// Routes
app.get('/api/customers/page', (req, res) => {
const skip = parseInt(req.query.skip, 10) || 0;
const top = parseInt(req.query.top, 10) || 10;
const pagedCustomers = customers.slice(skip, skip + top);
res.setHeader('X-InlineCount', customers.length);
res.json(pagedCustomers);
});
app.get('/api/customers', (req, res) => res.json(customers));
app.get('/api/customers/:id', (req, res) => {
const customerId = parseInt(req.params.id, 10);
const customer = getCustomerById(customerId);
res.json(customer || {});
});
app.post('/api/customers', (req, res) => {
const newCustomer = req.body;
newCustomer.id = Math.max(...customers.map((cust) => cust.id), 0) + 1;
newCustomer.gender = newCustomer.id % 2 === 0 ? 'female' : 'male';
customers.push(newCustomer);
res.json(newCustomer);
});
app.put('/api/customers/:id', (req, res) => {
const customerId = parseInt(req.params.id, 10);
const updatedCustomer = req.body;
const stateMatch = states.find((state) => state.abbreviation === updatedCustomer.state?.abbreviation);
if (stateMatch) {
updatedCustomer.state.name = stateMatch.name;
}
const index = customers.findIndex((cust) => cust.id === customerId);
if (index !== -1) {
customers[index] = updatedCustomer;
res.json({ status: true });
} else {
res.json({ status: false });
}
});
app.delete('/api/customers/:id', (req, res) => {
const customerId = parseInt(req.params.id, 10);
const index = customers.findIndex((cust) => cust.id === customerId);
if (index !== -1) {
customers.splice(index, 1);
res.json({ status: true });
} else {
res.json({ status: false });
}
});
app.get('/api/orders/:id', (req, res) => {
const customerId = parseInt(req.params.id, 10);
const orders = customers.find((cust) => cust.customerId === customerId)?.orders || [];
res.json(orders);
});
app.get('/api/states', (req, res) => res.json(states));
app.post('/api/auth/login', (req, res) => res.json(true)); // Simulate login
app.post('/api/auth/logout', (req, res) => res.json(true)); // Simulate logout
// Catch-all route for HTML5 history
if (!inContainer) {
app.use((req, res) => {
res.sendFile(path.join(__dirname, 'dist/angular-jumpstart/browser/index.html'));
});
}
// Helper function to check if port is in use
const checkPortInUse = (port) => {
return new Promise((resolve) => {
const execAsync = promisify(exec);
execAsync(`lsof -i :${port}`)
.then((result) => {
// Port is in use if lsof returns results
resolve(result.stdout.trim().length > 0);
})
.catch(() => {
// lsof command failed, assume port is free
resolve(false);
});
});
};
// Helper function to kill processes on port
const killPortProcesses = (port) => {
return new Promise((resolve) => {
const execAsync = promisify(exec);
execAsync(`lsof -t -i :${port}`)
.then((result) => {
const pids = result.stdout.trim().split('\n').filter(pid => pid);
if (pids.length > 0) {
console.log(`Found existing processes on port ${port}: ${pids.join(', ')}`);
return execAsync(`kill ${pids.join(' ')}`);
}
})
.then(() => {
console.log(`Cleared port ${port}`);
resolve();
})
.catch(() => {
// Kill command failed, continue anyway
resolve();
});
});
};
// Start the server with port cleanup
const startServer = async () => {
const portInUse = await checkPortInUse(port);
if (portInUse) {
console.log(`Port ${port} is already in use. Attempting to clear it...`);
await killPortProcesses(port);
// Wait a moment for the port to be freed
await new Promise(resolve => setTimeout(resolve, 1000));
}
app.listen(port, () => {
console.log(`Express server running on http://localhost:${port}`);
}).on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`Port ${port} is still in use. Please manually stop other processes or use a different port.`);
process.exit(1);
} else {
console.error('Server error:', err);
process.exit(1);
}
});
};
startServer();
// Open the browser (only if not in a container or Azure)
if (!inContainer && !inAzure) {
(async () => {
const { default: open } = await import('open');
open(`http://localhost:${port}`);
})();
}