Rename npm scripts to environment-prefixed names (dev:/prod:/devtoprod:/prodto:dev:/infra:).

Align package.json scripts and their references across scripts/, infra/, and db/ SQL with the dev-first workflow naming scheme.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Danila Khodjaef
2026-07-07 12:37:21 +03:00
co-authored by Cursor
parent a2263ca186
commit 96285737f5
16 changed files with 73 additions and 75 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
-- Virtual Art Gallery — canonical PostgreSQL schema
-- Applied by: npm run migrate (server/migrate.js)
-- Applied by: npm run dev:migrate (server/migrate.js)
-- Incremental ALTER migrations in db/migrate-*.sql run after this on existing databases.
CREATE TABLE IF NOT EXISTS historical_eras (
+1 -1
View File
@@ -27,7 +27,7 @@
--
-- AFTER SUCCESS:
-- On dev PC (normal PowerShell, repo root):
-- npm run migrate
-- npm run dev:migrate
-- npm run dev:web
-- Open http://devgallery.mysuperlab.netcraze.pro
--
+6 -6
View File
@@ -36,10 +36,10 @@ If deploy fails with **`manifest unknown`**, the image is not in Gitea yet — c
```powershell
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
docker login gitea.mysuperlab.netcraze.pro
npm run docker:publish
npm run prod:docker:publish
```
Push only (already built): `npm run docker:publish:push-only`
Push only (already built): `npm run prod:docker:push-only`
Image: `gitea.mysuperlab.netcraze.pro/danilka/gallery-web:latest`
@@ -84,7 +84,7 @@ Enable SMB share **`Gallery`** → `/mnt/BasePool/Applications/Gallery` (for ima
```powershell
net use \\192.168.10.122\Gallery /user:YOUR_TRUENAS_USER
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
npm run images:sync-to-prod
npm run devtoprod:images
```
UNC destination: `\\192.168.10.122\Gallery\data\images`
@@ -132,7 +132,7 @@ On TrueNAS shell: `bash infra/docker/truenas-verify.sh`
After code changes on dev PC:
```powershell
npm run docker:publish
npm run prod:docker:publish
```
Restart **gallery-web** on TrueNAS (or rely on `pull_policy: always`).
@@ -141,11 +141,11 @@ Restart **gallery-web** on TrueNAS (or rely on `pull_policy: always`).
| Issue | Fix |
|-------|-----|
| **`manifest unknown`** | Run `npm run docker:publish` first; or offline `truenas-load-image.sh` |
| **`manifest unknown`** | Run `npm run prod:docker:publish` first; or offline `truenas-load-image.sh` |
| **502 / 504 public URL** | Keenetic → `192.168.10.122:5173`, protocol **`http`**; verify LAN curl above |
| Container cannot reach Postgres | `DB_HOST=192.168.10.122`; `extra_hosts` in compose |
| Empty timeline | `DB_NAME=gallery_prod`; run pgAdmin split if still on legacy `Gallery` |
| Missing images | `npm run images:sync-to-prod`; check volume mount and `chown 1001:1001` |
| Missing images | `npm run devtoprod:images`; check volume mount and `chown 1001:1001` |
| Pull 401 | Gitea registry credentials on TrueNAS; `read:package` token |
| Push fails on dev PC | Gitea `ROOT_URL` HTTPS fix; use Admin PowerShell for LAN push |
+2 -2
View File
@@ -1,10 +1,10 @@
# Paste into TrueNAS: Apps → Custom App → Install via Docker Compose
#
# BEFORE deploy:
# 1. npm run docker:publish on dev PC (image must exist in Gitea)
# 1. npm run prod:docker:publish on dev PC (image must exist in Gitea)
# 2. Replace YOUR_POSTGRES_PASSWORD below
# 3. Gitea pull credentials on TrueNAS (read:package token)
# 4. mkdir + chown image dir; npm run images:sync-to-prod
# 4. mkdir + chown image dir; npm run devtoprod:images
# 5. Keenetic: gallery.mysuperlab.netcraze.pro → 192.168.10.122:5173, protocol http
#
# See infra/docker/DEPLOY-truenas.md and Documentation/environments.md
+1 -1
View File
@@ -1,7 +1,7 @@
# Sync production image files from TrueNAS to dev repo.
#
# Usage:
# npm run images:sync-from-prod
# npm run prodto:dev:images
# .\infra\scripts\sync-images-from-prod.ps1
param(
+1 -1
View File
@@ -1,7 +1,7 @@
# Sync dev image files to TrueNAS production volume.
#
# Usage (from repo root):
# npm run images:sync-to-prod
# npm run devtoprod:images
# Copies data/images/ → \\192.168.10.122\Gallery\data\images
# Map the share first if needed: net use \\192.168.10.122\Gallery /user:YOUR_TRUENAS_USER
+39 -41
View File
@@ -4,50 +4,48 @@
"description": "",
"main": "index.js",
"scripts": {
"migrate": "node server/migrate.js",
"migrate:thumbnails": "node -e \"require('./server/db').query(require('fs').readFileSync('./db/migrate-thumbnails.sql','utf8')).then(()=>{console.log('OK');process.exit(0);}).catch(e=>{console.error(e);process.exit(1);})\"",
"seed": "node scripts/seed-wikipedia.js",
"fetch-images": "node scripts/fetch-missing-images.js",
"search-missing-paintings": "node scripts/fetch-missing-images.js",
"fetch-artist-images": "node scripts/fetch-artist-images.js",
"fetch-artist-bios": "node scripts/fetch-artist-bios.js",
"sync-image-paths": "node scripts/sync-image-paths.js",
"regenerate-thumbnails": "node scripts/regenerate-thumbnails.js",
"regenerate-portrait-thumbs": "node scripts/regenerate-portrait-thumbs.js",
"audit-painting-images": "node scripts/audit-painting-images.js",
"expand-catalog": "node scripts/expand-paintings.js",
"update-influences": "node scripts/update-influences.js",
"migrate:influence-sources": "node scripts/migrate-influence-sources.js",
"migrate:checkup-flags": "node scripts/migrate-checkup-flags.js",
"migrate:artist-checkup-flags": "node scripts/migrate-artist-checkup-flags.js",
"migrate:painting-annotations": "node scripts/migrate-painting-annotations.js",
"migrate:artist-palette": "node scripts/migrate-artist-palette.js",
"import-painter-palette": "node scripts/import-painter-palette.js",
"analyze-painter-palette": "node scripts/analyze-painter-palette.js",
"export-paintings": "node scripts/export-paintings-csv.js",
"update-painting-annotations": "node scripts/update-painting-annotations.js",
"find-duplicates": "node scripts/find-duplicate-paintings.js",
"audit-influence-duplicates": "node scripts/audit-influence-duplicates.js",
"discover-influences": "node scripts/update-influences.js --discover-only",
"build": "npm run build --prefix client",
"start": "node server/index.js",
"start:prod": "npm run build && node server/index.js",
"server": "node server/index.js",
"dev:web": "node scripts/dev-web.js",
"dev:server": "nodemon server/index.js",
"dev:client": "npm run dev --prefix client",
"docker:publish": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/docker/build-push-lan.ps1",
"docker:publish:push-only": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/docker/build-push-lan.ps1 -SkipBuild",
"db:split-databases": "node scripts/split-dev-prod-databases.js",
"db:sync-from-prod": "node scripts/sync-prod-to-dev.js",
"db:backup": "node scripts/backup-db-data.js",
"db:backup:prod": "node scripts/backup-db-data.js --prod",
"db:restore": "node scripts/restore-db-data.js",
"db:restore:prod": "node scripts/restore-db-data.js --prod",
"images:sync-to-prod": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/scripts/sync-images-to-prod.ps1",
"images:sync-from-prod": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/scripts/sync-images-from-prod.ps1",
"dev": "node server/index.js",
"setup": "node server/migrate.js && node scripts/seed-wikipedia.js"
"dev:start": "node server/index.js",
"dev:migrate": "node server/migrate.js",
"dev:setup": "node server/migrate.js && node scripts/seed-wikipedia.js",
"dev:seed": "node scripts/seed-wikipedia.js",
"dev:fetch-images": "node scripts/fetch-missing-images.js",
"dev:search-missing-paintings": "node scripts/fetch-missing-images.js",
"dev:fetch-artist-images": "node scripts/fetch-artist-images.js",
"dev:fetch-artist-bios": "node scripts/fetch-artist-bios.js",
"dev:sync-image-paths": "node scripts/sync-image-paths.js",
"dev:regenerate-thumbnails": "node scripts/regenerate-thumbnails.js",
"dev:regenerate-portrait-thumbs": "node scripts/regenerate-portrait-thumbs.js",
"dev:audit-painting-images": "node scripts/audit-painting-images.js",
"dev:expand-catalog": "node scripts/expand-paintings.js",
"dev:update-influences": "node scripts/update-influences.js",
"dev:discover-influences": "node scripts/update-influences.js --discover-only",
"dev:migrate:thumbnails": "node -e \"require('./server/db').query(require('fs').readFileSync('./db/migrate-thumbnails.sql','utf8')).then(()=>{console.log('OK');process.exit(0);}).catch(e=>{console.error(e);process.exit(1);})\"",
"dev:migrate:influence-sources": "node scripts/migrate-influence-sources.js",
"dev:migrate:checkup-flags": "node scripts/migrate-checkup-flags.js",
"dev:migrate:artist-checkup-flags": "node scripts/migrate-artist-checkup-flags.js",
"dev:migrate:painting-annotations": "node scripts/migrate-painting-annotations.js",
"dev:migrate:artist-palette": "node scripts/migrate-artist-palette.js",
"dev:import-painter-palette": "node scripts/import-painter-palette.js",
"dev:analyze-painter-palette": "node scripts/analyze-painter-palette.js",
"dev:export-paintings": "node scripts/export-paintings-csv.js",
"dev:update-painting-annotations": "node scripts/update-painting-annotations.js",
"dev:find-duplicates": "node scripts/find-duplicate-paintings.js",
"dev:audit-influence-duplicates": "node scripts/audit-influence-duplicates.js",
"dev:db:backup": "node scripts/backup-db-data.js",
"dev:db:restore": "node scripts/restore-db-data.js",
"prod:build": "npm run build --prefix client",
"prod:start": "npm run prod:build && node server/index.js",
"prod:docker:publish": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/docker/build-push-lan.ps1",
"prod:docker:push-only": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/docker/build-push-lan.ps1 -SkipBuild",
"prod:db:backup": "node scripts/backup-db-data.js --prod",
"devtoprod:db:restore": "node scripts/restore-db-data.js --prod",
"devtoprod:images": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/scripts/sync-images-to-prod.ps1",
"prodto:dev:db": "node scripts/sync-prod-to-dev.js",
"prodto:dev:images": "powershell -NoProfile -ExecutionPolicy Bypass -File infra/scripts/sync-images-from-prod.ps1",
"infra:db:split-dev-prod": "node scripts/split-dev-prod-databases.js"
},
"keywords": [],
"author": "",
+1 -1
View File
@@ -21,7 +21,7 @@ if (fromProd) {
} else {
assertDevDatabase(config.database);
if (config.database.endsWith('_prod')) {
console.error('Refusing backup of production database without --prod. Use: npm run db:backup:prod');
console.error('Refusing backup of production database without --prod. Use: npm run prod:db:backup');
process.exit(1);
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
/**
* Download artist portrait images from Wikipedia (and fallbacks) into data/images/portraits/.
* Run: npm run fetch-artist-images
* Run: npm run dev:fetch-artist-images
* Flags: --force (re-fetch even when portrait_path is set), --limit=N
*/
require('dotenv').config();
+6 -6
View File
@@ -4,11 +4,11 @@
* - Insert artist/movement influence sources from Influencedby, Teachers, Influencedon, Pupils
*
* Usage:
* npm run migrate:artist-palette
* npm run import-painter-palette # metadata + influences
* npm run import-painter-palette -- --dry-run
* npm run import-painter-palette -- --metadata-only
* npm run import-painter-palette -- --influences-only
* npm run dev:migrate:artist-palette
* npm run dev:import-painter-palette # metadata + influences
* npm run dev:import-painter-palette -- --dry-run
* npm run dev:import-painter-palette -- --metadata-only
* npm run dev:import-painter-palette -- --influences-only
*/
require('dotenv').config();
const pool = require('../server/db');
@@ -47,7 +47,7 @@ async function main() {
) AS ok
`);
if (!tableCheck.rows[0]?.ok) {
console.error('Run npm run migrate:artist-palette first.');
console.error('Run npm run dev:migrate:artist-palette first.');
process.exit(1);
}
+2 -2
View File
@@ -1,8 +1,8 @@
/**
* Restore a data-only backup (INSERT dumps from npm run db:backup) into a database.
* Restore a data-only backup (INSERT dumps from npm run dev:db:backup) into a database.
*
* Dev: node scripts/restore-db-data.js --file db/DataBackup/gallery_dev_data_....txt
* Prod: npm run db:restore:prod -- --file db/DataBackup/gallery_dev_data_....txt
* Prod: npm run devtoprod:db:restore -- --file db/DataBackup/gallery_dev_data_....txt
*/
const fs = require('fs');
const path = require('path');
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Curated eras, movements, and artist metadata for npm run seed.
* Curated eras, movements, and artist metadata for npm run dev:seed.
* Flagship paintings are resolved from art-influences-data.js and famous-paintings-data.js.
*/
const FAMOUS = require('./famous-paintings-data');
+5 -5
View File
@@ -1,6 +1,6 @@
/**
* Seed historical eras, art movements, artists, periods, and flagship paintings.
* Run: npm run seed
* Run: npm run dev:seed
* Flags: --force (re-seed), --fetch-images (download portraits and paintings from Wikipedia)
*/
require('dotenv').config();
@@ -180,12 +180,12 @@ async function main() {
console.log(` Portraits downloaded: ${stats.portraitsFetched}`);
console.log(` Painting images: ${stats.imagesFetched}`);
} else {
console.log(' Run with --fetch-images to download artwork files, or npm run fetch-images later.');
console.log(' Run with --fetch-images to download artwork files, or npm run dev:fetch-images later.');
}
console.log('\nNext steps:');
console.log(' npm run fetch-artist-bios');
console.log(' npm run expand-catalog');
console.log(' npm run update-influences');
console.log(' npm run dev:fetch-artist-bios');
console.log(' npm run dev:expand-catalog');
console.log(' npm run dev:update-influences');
}
main()
+4 -4
View File
@@ -2,7 +2,7 @@
* One-time split of legacy Gallery → gallery_prod + gallery_dev on TrueNAS PostgreSQL.
*
* Usage:
* PGPASSWORD=... PGHOST=192.168.10.122 PGUSER=postgres npm run db:split-databases
* PGPASSWORD=... PGHOST=192.168.10.122 PGUSER=postgres npm run infra:db:split-dev-prod
*
* Options:
* --copy pg_dump legacy → gallery_prod instead of rename
@@ -116,12 +116,12 @@ async function main() {
} else {
console.warn(`No legacy database (${LEGACY_DB_NAMES.join(' / ')}) or "${PROD_DB_NAME}" found`);
await createDatabaseIfMissing(admin, PROD_DB_NAME);
console.log('Run npm run migrate against gallery_prod to apply schema');
console.log('Run npm run dev:migrate against gallery_prod to apply schema');
}
if (!skipDev) {
await cloneDevFromProd(admin);
console.log(`Next on dev PC: set .env DB_NAME=${DEV_DB_NAME}, then npm run migrate`);
console.log(`Next on dev PC: set .env DB_NAME=${DEV_DB_NAME}, then npm run dev:migrate`);
}
await admin.end();
@@ -134,7 +134,7 @@ main().catch((error) => {
'Permission denied — the gallery user cannot rename databases.\n'
+ 'Use pgAdmin on the dev PC (recommended):\n'
+ ' Open db/split-dev-prod-pgadmin.sql → connect as postgres → run each STEP (F5)\n'
+ 'Or: PGUSER=postgres PGPASSWORD=... npm run db:split-databases\n'
+ 'Or: PGUSER=postgres PGPASSWORD=... npm run infra:db:split-dev-prod\n'
+ 'Or: psql -h 192.168.10.122 -U postgres -d postgres -f db/split-dev-prod.sql',
);
}
+1 -1
View File
@@ -1,6 +1,6 @@
/**
* Align painting image_path / thumbnail_path with files on disk and import missing rows.
* Run: npm run sync-image-paths
* Run: npm run dev:sync-image-paths
* Flags: --dry-run (report only, no DB writes)
*/
require('dotenv').config();
+1 -1
View File
@@ -135,7 +135,7 @@ async function main() {
) AS ok
`);
if (!tableCheck.rows[0]?.ok) {
console.error('Run npm run migrate:influence-sources before update-influences.');
console.error('Run npm run dev:migrate:influence-sources before update-influences.');
process.exit(1);
}