← back to Wallco Ai
migrate: ensure user_removed column on spoon_all_designs (was missing on prod)
ade6dc46cf4308d15f501383376236aa373ad83e · 2026-05-13 13:36:39 -0700 · SteveStudio2
Idempotent startup migrator. Fixes the /api/design/:id/remove endpoint
that was UPDATE-failing on prod with 'column does not exist'.
Plus partial index on user_removed=TRUE rows for fast filter on
load (only the small soft-removed subset matters).
Files touched
M data/designs.jsonM server.js
Diff
commit ade6dc46cf4308d15f501383376236aa373ad83e
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 13:36:39 2026 -0700
migrate: ensure user_removed column on spoon_all_designs (was missing on prod)
Idempotent startup migrator. Fixes the /api/design/:id/remove endpoint
that was UPDATE-failing on prod with 'column does not exist'.
Plus partial index on user_removed=TRUE rows for fast filter on
load (only the small soft-removed subset matters).
---
data/designs.json | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
server.js | 14 ++++
2 files changed, 212 insertions(+)
diff --git a/data/designs.json b/data/designs.json
index 85f0b40..ffaf3db 100644
--- a/data/designs.json
+++ b/data/designs.json
@@ -80337,5 +80337,203 @@
"user_scale_good": null,
"user_stars": null,
"room_mockups": []
+ },
+ {
+ "id": 3881,
+ "kind": "seamless_tile",
+ "category": "stoned-animals",
+ "dominant_hex": "#738f64",
+ "saturation": 0.177,
+ "title": "Sage Trip No.3881",
+ "handle": "wallco-3881",
+ "image_url": "/designs/img/1778704501649_400447908.png",
+ "filename": "1778704501649_400447908.png",
+ "generator": "wallco.ai",
+ "seed": 400447908,
+ "is_published": false,
+ "created_at": "2026-05-13T20:35:09.896674+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3882,
+ "kind": "seamless_tile",
+ "category": "drunk-animals",
+ "dominant_hex": "#ab7656",
+ "saturation": 0.336,
+ "title": "Amber Tableau No.3882",
+ "handle": "wallco-3882",
+ "image_url": "/designs/img/1778704501650_457218544.png",
+ "filename": "1778704501650_457218544.png",
+ "generator": "wallco.ai",
+ "seed": 457218544,
+ "is_published": false,
+ "created_at": "2026-05-13T20:35:13.209734+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3883,
+ "kind": "seamless_tile",
+ "category": "damask",
+ "dominant_hex": "#2b2623",
+ "saturation": 0.103,
+ "title": "Amber Atelier No.3883",
+ "handle": "wallco-3883",
+ "image_url": "/designs/img/1778704558724_228687751.png",
+ "filename": "1778704558724_228687751.png",
+ "generator": "wallco.ai",
+ "seed": 228687751,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:06.912724+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3884,
+ "kind": "seamless_tile",
+ "category": "damask",
+ "dominant_hex": "#2b2623",
+ "saturation": 0.103,
+ "title": "Amber Salon No.3884",
+ "handle": "wallco-3884",
+ "image_url": "/designs/img/var_3883_hue+60_1778704567019.png",
+ "filename": "var_3883_hue+60_1778704567019.png",
+ "generator": "wallco.ai",
+ "seed": 0,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:09.188787+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3885,
+ "kind": "seamless_tile",
+ "category": "damask",
+ "dominant_hex": "#2b2623",
+ "saturation": 0.103,
+ "title": "Amber Baroque No.3885",
+ "handle": "wallco-3885",
+ "image_url": "/designs/img/var_3883_hue+120_1778704569192.png",
+ "filename": "var_3883_hue+120_1778704569192.png",
+ "generator": "wallco.ai",
+ "seed": 0,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:11.336137+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3886,
+ "kind": "seamless_tile",
+ "category": "damask",
+ "dominant_hex": "#2b2623",
+ "saturation": 0.103,
+ "title": "Amber Damask No.3886",
+ "handle": "wallco-3886",
+ "image_url": "/designs/img/var_3883_hue+180_1778704571342.png",
+ "filename": "var_3883_hue+180_1778704571342.png",
+ "generator": "wallco.ai",
+ "seed": 0,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:13.507045+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3887,
+ "kind": "seamless_tile",
+ "category": "damask",
+ "dominant_hex": "#2b2623",
+ "saturation": 0.103,
+ "title": "Amber Heirloom No.3887",
+ "handle": "wallco-3887",
+ "image_url": "/designs/img/var_3883_hue-60_1778704573510.png",
+ "filename": "var_3883_hue-60_1778704573510.png",
+ "generator": "wallco.ai",
+ "seed": 0,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:15.639058+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3888,
+ "kind": "seamless_tile",
+ "category": "damask",
+ "dominant_hex": "#2b2623",
+ "saturation": 0.103,
+ "title": "Amber Atelier No.3888",
+ "handle": "wallco-3888",
+ "image_url": "/designs/img/var_3883_mono_1778704575643.png",
+ "filename": "var_3883_mono_1778704575643.png",
+ "generator": "wallco.ai",
+ "seed": 0,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:17.799552+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3889,
+ "kind": "seamless_tile",
+ "category": "drunk-animals",
+ "dominant_hex": "#28202a",
+ "saturation": 0.135,
+ "title": "Mauve Folly No.3889",
+ "handle": "wallco-3889",
+ "image_url": "/designs/img/1778704581951_740816092.png",
+ "filename": "1778704581951_740816092.png",
+ "generator": "wallco.ai",
+ "seed": 740816092,
+ "is_published": false,
+ "created_at": "2026-05-13T20:36:30.370153+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
}
]
\ No newline at end of file
diff --git a/server.js b/server.js
index 44e413b..10e9208 100644
--- a/server.js
+++ b/server.js
@@ -1333,6 +1333,20 @@ function ensureTradeUserTables() {
}
ensureTradeUserTables();
+// ── Ensure user_removed column on spoon_all_designs ─────────────────
+// The /api/design/:id/remove endpoint writes user_removed=TRUE to this
+// column. On prod, the column was missing — UPDATE returned "column does
+// not exist" and the soft-remove silently failed. Add it idempotently.
+function ensureUserRemovedColumn() {
+ try {
+ psqlQuery(`ALTER TABLE spoon_all_designs ADD COLUMN IF NOT EXISTS user_removed BOOLEAN NOT NULL DEFAULT FALSE;`);
+ psqlQuery(`CREATE INDEX IF NOT EXISTS spoon_all_designs_user_removed_idx ON spoon_all_designs(user_removed) WHERE user_removed = TRUE;`);
+ } catch (e) {
+ console.error('[migrate] ensureUserRemovedColumn:', e.message);
+ }
+}
+ensureUserRemovedColumn();
+
// Audit-log — every user + admin action lands here. Append-only. Steve's call:
// trade users see only their own at /me/activity; admin sees everything at /admin/activity.
function ensureAuditLogTable() {
← bf6d6f9 admin-gate: add ADMIN_TOKEN query/header path so admin UI re
·
back to Wallco Ai
·
furnish: per-item Google Images / 1stdibs / Pinterest / Etsy 6afffe7 →