Skip to content

Commit b873121

Browse files
committed
fix: devcontainer seed timing, port conflict, and Codespaces mixed content
- Wait for Atlas Local replica set primary election (isWritablePrimary) instead of ping before seeding; up to 60 retries × 2s - Remove duplicate server/client start from startup.sh — postAttachCommand already handles those, double-start caused port 5050 conflict - Add Vite proxy for /record → http://localhost:5050 so browser fetches go same-origin (fixes HTTPS mixed-content blocking in Codespaces) - Replace all hardcoded http://localhost:5050/record URLs in React components with relative /record paths
1 parent 4744a8b commit b873121

5 files changed

Lines changed: 25 additions & 41 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
// this will open 3 bash sessions, each one running the specified command
3535
"postAttachCommand": {
36-
"server": "cd mern/server && npm start",
36+
"server": "cd mern/server && node ./seed.js && npm start",
3737
"client": "cd mern/client && npm run dev -- --host 0.0.0.0",
3838
"portSetup": "sleep 5 && .devcontainer/portSetup.sh"
3939
},

.devcontainer/startup.sh

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,45 +18,28 @@ EOF
1818
}
1919

2020
wait_for_mongodb() {
21-
local max_tries=30
21+
local max_tries=60
2222
local try=1
2323

24-
until node --input-type=module -e "import { MongoClient } from 'mongodb'; const c = new MongoClient(process.env.ATLAS_URI); await c.connect(); await c.db('admin').command({ ping: 1 }); await c.close();" >/dev/null 2>&1; do
24+
# Atlas Local uses a replica set — wait until a writable primary is elected,
25+
# not just until mongod responds to ping (which happens before primary election).
26+
until node --input-type=module -e "
27+
import { MongoClient } from 'mongodb';
28+
const c = new MongoClient(process.env.ATLAS_URI);
29+
await c.connect();
30+
const h = await c.db('admin').command({ hello: 1 });
31+
await c.close();
32+
if (!h.isWritablePrimary) throw new Error('no primary yet');
33+
" >/dev/null 2>&1; do
2534
if (( try >= max_tries )); then
26-
echo "MongoDB did not become ready in time."
35+
echo "MongoDB primary did not become ready in time."
2736
return 1
2837
fi
29-
echo "Waiting for MongoDB... ($try/$max_tries)"
38+
echo "Waiting for MongoDB primary... ($try/$max_tries)"
3039
try=$((try + 1))
3140
sleep 2
3241
done
33-
}
34-
35-
seed_database() {
36-
(
37-
cd "$SERVER_DIR"
38-
node --env-file=config.env seed.js > /tmp/mern-seed.log 2>&1
39-
)
40-
41-
echo "Seed completed (log: /tmp/mern-seed.log)."
42-
}
43-
44-
verify_seed_data() {
45-
local count
46-
47-
count=$(
48-
cd "$SERVER_DIR" &&
49-
node --env-file=config.env --input-type=module -e "import { MongoClient } from 'mongodb'; const c = new MongoClient(process.env.ATLAS_URI); await c.connect(); const n = await c.db('employees').collection('records').countDocuments(); console.log(n); await c.close();"
50-
)
51-
52-
echo "Seed verification: employees.records has $count documents."
53-
54-
if [[ "$count" -le 0 ]]; then
55-
echo "Seed verification failed: no documents found in employees.records."
56-
echo "Seed log tail:"
57-
tail -n 50 /tmp/mern-seed.log || true
58-
return 1
59-
fi
42+
echo "MongoDB primary is ready."
6043
}
6144

6245
start_server_if_needed() {
@@ -87,9 +70,5 @@ start_client_if_needed() {
8770

8871
ensure_config
8972
wait_for_mongodb
90-
seed_database
91-
verify_seed_data
92-
start_server_if_needed
93-
start_client_if_needed
9473

9574
echo "Codespaces startup complete."

mern/client/src/components/Record.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function Record() {
2626
if(!id) return;
2727
setIsNew(false);
2828
const response = await fetch(
29-
`http://localhost:5050/record/${params.id.toString()}`
29+
`/record/${params.id.toString()}`
3030
);
3131
if (!response.ok) {
3232
const message = `An error has occurred: ${response.statusText}`;
@@ -60,7 +60,7 @@ export default function Record() {
6060
let response;
6161
if (isNew) {
6262
// if we are adding a new record we will POST to /record.
63-
response = await fetch("http://localhost:5050/record", {
63+
response = await fetch("/record", {
6464
method: "POST",
6565
headers: {
6666
"Content-Type": "application/json",
@@ -69,7 +69,7 @@ export default function Record() {
6969
});
7070
} else {
7171
// if we are updating a record we will PATCH to /record/:id.
72-
response = await fetch(`http://localhost:5050/record/${params.id}`, {
72+
response = await fetch(`/record/${params.id}`, {
7373
method: "PATCH",
7474
headers: {
7575
"Content-Type": "application/json",

mern/client/src/components/RecordList.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export default function RecordList() {
5050
// This method fetches the records from the database.
5151
useEffect(() => {
5252
async function getRecords() {
53-
const response = await fetch(`http://localhost:5050/record/`);
53+
const response = await fetch(`/record/`);
5454
if (!response.ok) {
5555
const message = `An error occurred: ${response.statusText}`;
5656
console.error(message);
@@ -65,7 +65,7 @@ export default function RecordList() {
6565

6666
// This method will delete a record
6767
async function deleteRecord(id) {
68-
await fetch(`http://localhost:5050/record/${id}`, {
68+
await fetch(`/record/${id}`, {
6969
method: "DELETE",
7070
});
7171
const newRecords = records.filter((el) => el._id !== id);

mern/client/vite.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@ import react from '@vitejs/plugin-react'
44
// https://vitejs.dev/config/
55
export default defineConfig({
66
plugins: [react()],
7+
server: {
8+
proxy: {
9+
'/record': 'http://localhost:5050',
10+
},
11+
},
712
})

0 commit comments

Comments
 (0)