[object Object]

← 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

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 →