File size: 3,613 Bytes
377e476
 
d5530f7
377e476
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5530f7
 
377e476
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5530f7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env node
import { execFileSync } from 'node:child_process';
import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';

const REPO = 'bep40/semantic-image-field';
const CLONE = '/tmp/space';
const STABLE_BUNDLE = 'assets/index.js';
const STABLE_STYLE = 'assets/app.css';
const MIRROR = ['products.json', 'promos.json'];
const COMMITTABLE = ['index.html', 'public/catalogue', 'dist/catalogue', 'dist/assets', 'dist/share', 'public/share'];

const ok = m => console.log(`[refresh] ${m}`);

function run(command, args, { cwd = CLONE } = {}) {
  return execFileSync(command, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 64 * 1024 * 1024 });
}
function shell(script, cwd = CLONE) { return run('bash', ['-lc', script], { cwd }); }
function git(...args) {
  return run('git', ['-c', `http.extraheader=Authorization: Bearer ${process.env.HF_TOKEN}`, ...args]);
}

function main() {
  if (!process.env.HF_TOKEN) throw new Error('HF_TOKEN required');
  rmSync(CLONE, { recursive: true, force: true });
  run('mkdir', ['-p', CLONE]);
  run('git', ['clone', '-q', `--filter=blob:none`, '--no-checkout', `https://huggingface.co/spaces/${REPO}`], { cwd: '/' });
  git('checkout', '-q', '-B', 'main', 'main');
  ok('cloned');

  shell('set -euo pipefail; npm install --silent --no-audit --no-fund');
  ok('dependencies installed');
  shell('set -euo pipefail; node scripts/sync-catalogue.mjs');
  for (const file of MIRROR) {
    const count = JSON.parse(readFileSync(`public/catalogue/${file}`, 'utf8')).length;
    ok(`public/catalogue/${file}: ${count} entries`);
  }
  shell('set -euo pipefail; npm run build');
  ok('built');
  for (const file of MIRROR) {
    const served = `dist/catalogue/${file}`;
    const source = JSON.parse(readFileSync(`public/catalogue/${file}`, 'utf8')).length;
    const built = JSON.parse(readFileSync(served, 'utf8')).length;
    if (source !== built) throw new Error(`${served} has ${built} but mirror has ${source}`);
    ok(`served mirror verified: ${file} (${built} entries)`);
  }
  const htmlPath = `${CLONE}/index.html`;
  let html = readFileSync(htmlPath, 'utf8');
  if (/\.\/dist\/assets\/index\.js\b/.test(html) && /\.\/dist\/assets\/app\.css\b/.test(html)) {
    ok('index.html already references stable bundle');
  } else {
    let next = html.replace(/(\.\/dist\/assets\/)index-[A-Za-z0-9_-]+\.js\b/g, `$1${STABLE_BUNDLE.slice('assets/'.length)}`);
    next = next.replace(/(\.\/dist\/assets\/)index-[A-Za-z0-9_-]+\.css\b/g, `$1${STABLE_STYLE.slice('assets/'.length)}`);
    if (next === html) throw new Error('index.html names bundle in unexpected way');
    writeFileSync(htmlPath, next);
    ok('index.html repointed to ' + STABLE_BUNDLE);
  }
  for (const asset of [STABLE_BUNDLE, STABLE_STYLE]) {
    if (!existsSync(`${CLONE}/dist/${asset}`)) throw new Error(`dist/${asset} missing`);
  }
  const commit = shell(`set -euo pipefail;
    git config user.name "semantic-image-field refresh";
    git config user.email "refresh@hf.space";
    git add -- ${COMMITTABLE.map(p => `'${p}'`).join(' ')};
    if git diff --cached --quiet; then echo NOCHANGE; else git commit -q -m "chore: rebuild with semantic search fix"; echo COMMITTED; fi`).trim();
  if (commit.includes('COMMITTED')) {
    git('push', '-q', 'origin', 'main');
    ok('pushed — the static Space will rebuild');
  } else {
    ok(`no change needed (HEAD ${shell('git rev-parse --short HEAD').trim()})`);
  }
  console.log('REFRESH_OK');
}
try { main(); }
catch (e) { console.error('REFRESH_FAILED:', e.message, e.stderr || ''); process.exitCode = 1; }