zentraproperty feedv1.0.0-rc.3

integration · copy-ready

Validate before you publish.

Safe defaults, bounded network behaviour and explicit failure handling for local development, CI and feed delivery.

CLI workflow

node tools/zentra-feed.mjs --help
node tools/zentra-feed.mjs validate feed.xml --json > report.json
node tools/zentra-feed.mjs audit-media feed.xml --json --concurrency 4
node tools/diff-indexes.mjs old/cities.json new/cities.json --json

curl

curl --fail --silent --show-error \
  --connect-timeout 10 --max-time 60 \
  --user "$FEED_USER:$FEED_PASSWORD" \
  --upload-file feed.xml \
  https://feeds.example.invalid/zentra.xml

node

import { readFile } from 'node:fs/promises';
const xml = await readFile('feed.xml');
const response = await fetch(process.env.FEED_URL, {
  method: 'PUT', body: xml,
  headers: { 'content-type': 'application/xml; charset=utf-8' },
  signal: AbortSignal.timeout(60_000)
});
if (!response.ok) throw new Error(`publish failed: ${response.status}`);

python

from pathlib import Path
from urllib.request import Request, urlopen
request = Request(FEED_URL, data=Path('feed.xml').read_bytes(),
                  method='PUT', headers={'Content-Type': 'application/xml; charset=utf-8'})
with urlopen(request, timeout=60) as response:
    assert 200 <= response.status < 300

php

use Illuminate\Support\Facades\Http;
$response = Http::connectTimeout(10)->timeout(60)
    ->withBody(file_get_contents($path), 'application/xml; charset=utf-8')
    ->put(config('feeds.zentra_url'));
$response->throw();

Production-size guidance

Generate XML as a UTF-8 stream, write one property at a time, calculate a content fingerprint while writing, validate from disk, then publish the immutable file. Do not construct a multi-gigabyte DOM in application memory. Bound redirects, payload size, connect timeout and total timeout at every network boundary.