← back to Sublease Agentabrams
chore: lint, refactor, v0.2.0 (session close) — CENSUS_URL de-shadow, PDF stream-finish await, NaN-broker-id + sponsor null guards
35f66503ffb436a290099fa0cdd9f5f29c5c87ba · 2026-07-21 12:18:26 -0700 · Steve
Files touched
M crawl/bb-crawl.jsM package-lock.jsonM package.jsonM scripts/build-business-plan.jsM scripts/census-batch-geocode.jsM scripts/census-fix-state.jsM server.js
Diff
commit 35f66503ffb436a290099fa0cdd9f5f29c5c87ba
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Jul 21 12:18:26 2026 -0700
chore: lint, refactor, v0.2.0 (session close) — CENSUS_URL de-shadow, PDF stream-finish await, NaN-broker-id + sponsor null guards
---
crawl/bb-crawl.js | 1 +
package-lock.json | 4 ++--
package.json | 2 +-
scripts/build-business-plan.js | 5 +++--
scripts/census-batch-geocode.js | 4 ++--
scripts/census-fix-state.js | 4 ++--
server.js | 1 +
7 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/crawl/bb-crawl.js b/crawl/bb-crawl.js
index b9fb01f..0831c13 100644
--- a/crawl/bb-crawl.js
+++ b/crawl/bb-crawl.js
@@ -89,6 +89,7 @@ function toListing(o, firm) {
async function crawlFirm(slug) {
const cfg = FIRMS[slug];
const sponsor = await base.getSponsor(slug);
+ if (!sponsor) { console.error(`bb-crawl: no sponsor row for ${slug}`); return { cost: 0, found: 0, added: 0 }; }
const runId = await base.startRun(sponsor.id);
const t0 = Date.now();
const captured = [];
diff --git a/package-lock.json b/package-lock.json
index 4cfbe22..434a198 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "sublease-agentabrams",
- "version": "0.1.0",
+ "version": "0.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sublease-agentabrams",
- "version": "0.1.0",
+ "version": "0.2.0",
"dependencies": {
"@browserbasehq/sdk": "^2.16.0",
"express": "^4.19.2",
diff --git a/package.json b/package.json
index 11d4802..f4ec746 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "sublease-agentabrams",
- "version": "0.1.0",
+ "version": "0.2.0",
"private": true,
"description": "sublease.agentabrams.com — gated commercial sublease marketplace backed by CRUnifiedDB",
"main": "server.js",
diff --git a/scripts/build-business-plan.js b/scripts/build-business-plan.js
index 42c9c4d..2dd7901 100644
--- a/scripts/build-business-plan.js
+++ b/scripts/build-business-plan.js
@@ -16,7 +16,8 @@ const INK = '#14181d', MUT = '#5b6673', ACC = '#1a5f3c', GOLD = '#b08a3e', LINE
const lenders = sponsors.filter(s => s.role === 'financing_partner');
const doc = new PDFDocument({ size: 'LETTER', margins: { top: 64, bottom: 64, left: 64, right: 64 } });
- doc.pipe(fs.createWriteStream(OUT));
+ const ws = fs.createWriteStream(OUT);
+ doc.pipe(ws);
const W = doc.page.width - 128;
const H1 = (t) => { doc.moveDown(0.6); doc.fillColor(ACC).font('Helvetica-Bold').fontSize(15).text(t); doc.moveTo(64, doc.y + 2).lineTo(64 + W, doc.y + 2).strokeColor(LINE).stroke(); doc.moveDown(0.5); };
@@ -153,7 +154,7 @@ const INK = '#14181d', MUT = '#5b6673', ACC = '#1a5f3c', GOLD = '#b08a3e', LINE
doc.fillColor(MUT).font('Helvetica-Oblique').fontSize(8.5).text('Generated from CRUnifiedDB. Counts reflect the database at generation time and grow as broker agents run.', { align: 'center' });
doc.end();
- await new Promise(r => doc.on('end', r) || setTimeout(r, 400));
+ await new Promise((resolve, reject) => { ws.on('finish', resolve); ws.on('error', reject); });
await pool.end();
console.log('PDF written →', OUT);
})();
diff --git a/scripts/census-batch-geocode.js b/scripts/census-batch-geocode.js
index 4a44c2e..0f9b9ac 100644
--- a/scripts/census-batch-geocode.js
+++ b/scripts/census-batch-geocode.js
@@ -3,7 +3,7 @@
// no rate limit). Purpose-built for bulk — the fix for what Nominatim throttled. $0.
const { Pool } = require('pg');
const pool = new Pool({ host: '/tmp', database: 'crunified' });
-const URL = 'https://geocoding.geo.census.gov/geocoder/locations/addressbatch';
+const CENSUS_URL = 'https://geocoding.geo.census.gov/geocoder/locations/addressbatch';
const csvq = (s) => '"' + String(s == null ? '' : s).replace(/"/g, "'").replace(/[\r\n]+/g, ' ') + '"';
// minimal CSV line parser (handles quoted fields)
@@ -27,7 +27,7 @@ function parseLine(line) {
fd.append('addressFile', new Blob([csv], { type: 'text/csv' }), 'addrs.csv');
console.log('uploading to Census batch geocoder…');
- const res = await fetch(URL, { method: 'POST', body: fd, signal: AbortSignal.timeout(180000) });
+ const res = await fetch(CENSUS_URL, { method: 'POST', body: fd, signal: AbortSignal.timeout(180000) });
const text = await res.text();
if (!res.ok) { console.log('census error', res.status, text.slice(0, 200)); await pool.end(); return; }
diff --git a/scripts/census-fix-state.js b/scripts/census-fix-state.js
index ce17f98..384855f 100644
--- a/scripts/census-fix-state.js
+++ b/scripts/census-fix-state.js
@@ -4,7 +4,7 @@
// still-missing lat/lng. $0, one upload.
const { Pool } = require('pg');
const pool = new Pool({ host: '/tmp', database: 'crunified' });
-const URL = 'https://geocoding.geo.census.gov/geocoder/locations/addressbatch';
+const CENSUS_URL = 'https://geocoding.geo.census.gov/geocoder/locations/addressbatch';
const csvq = (s) => '"' + String(s == null ? '' : s).replace(/"/g, "'").replace(/[\r\n]+/g, ' ') + '"';
function parseLine(line) { const out = []; let cur = '', q = false;
for (let i = 0; i < line.length; i++) { const c = line[i];
@@ -21,7 +21,7 @@ function parseLine(line) { const out = []; let cur = '', q = false;
fd.append('benchmark', 'Public_AR_Current');
fd.append('addressFile', new Blob([csv], { type: 'text/csv' }), 'addrs.csv');
console.log('uploading…');
- const res = await fetch(URL, { method: 'POST', body: fd, signal: AbortSignal.timeout(180000) });
+ const res = await fetch(CENSUS_URL, { method: 'POST', body: fd, signal: AbortSignal.timeout(180000) });
const text = await res.text();
if (!res.ok) { console.log('census error', res.status); await pool.end(); return; }
diff --git a/server.js b/server.js
index c7f031e..f0e0ac4 100644
--- a/server.js
+++ b/server.js
@@ -178,6 +178,7 @@ const clean = (s, n = 500) => String(s == null ? '' : s).slice(0, n);
app.post('/api/brokers/:id/claim', (req, res) => {
try {
const id = +req.params.id; const b = req.body || {};
+ if (!Number.isInteger(id) || id <= 0) return res.status(400).json({ error: 'invalid broker id' });
if (!b.name || !b.email) return res.status(400).json({ error: 'name and email are required' });
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(b.email)) return res.status(400).json({ error: 'valid email required' });
const rec = {
← 8301646 Individual client accounts (file-based, snapshot-safe): scry
·
back to Sublease Agentabrams
·
auto-save: 2026-07-21T13:37:45 (7 files) — public/index.html ded7ae6 →