Files
geo/scripts/seed-demo.ts
T
Ruslan Bakiev 489f6dbf81
Build and deploy Docker image / build (push) Successful in 1m27s
Connect demo geo catalog graph
2026-06-07 14:09:31 +07:00

285 lines
6.8 KiB
TypeScript

import { aql } from 'arangojs'
import { ensureGraph, getDb } from '../dist/db.js'
type GeoNode = {
_key: string
node_type: string
name: string
latitude: number
longitude: number
country: string
country_code: string
transport_types?: string[]
product_uuid?: string
product_name?: string
supplier_uuid?: string
supplier_name?: string
price_per_unit?: string
currency?: string
quantity?: string
unit?: string
synced_at: string
}
type DemoHub = GeoNode & {
_key: string
latitude: number
longitude: number
}
type DemoProduct = {
uuid: string
name: string
unit: string
}
type DemoSupplier = {
uuid: string
name: string
latitude: number
longitude: number
country: string
country_code: string
hubKey: string
}
async function upsertNode(doc: GeoNode) {
const { _key, ...patch } = doc
await getDb().query(aql`
UPSERT { _key: ${_key} }
INSERT ${doc}
UPDATE ${patch}
IN ${getDb().collection('nodes')}
`)
}
async function upsertEdge(doc: Record<string, unknown>) {
const key = String(doc._key)
const { _key, ...patch } = doc
await getDb().query(aql`
UPSERT { _key: ${key} }
INSERT ${doc}
UPDATE ${patch}
IN ${getDb().collection('edges')}
`)
}
await ensureGraph()
const now = new Date().toISOString()
const products: DemoProduct[] = [
{
uuid: '55555555-1111-4111-8111-111111111111',
name: 'Copper cathode',
unit: 'ton',
},
{
uuid: '55555555-1111-4111-8111-222222222222',
name: 'Aluminum ingot',
unit: 'ton',
},
{
uuid: '55555555-1111-4111-8111-333333333333',
name: 'Wheat',
unit: 'ton',
},
]
const hubs: DemoHub[] = [
{
_key: 'logistics-demo-hub-1',
node_type: 'logistics',
name: 'Demo Almaty Hub',
latitude: 43.238949,
longitude: 76.889709,
country: 'Kazakhstan',
country_code: 'KZ',
transport_types: ['AUTO', 'RAIL'],
synced_at: now,
},
{
_key: 'logistics-demo-hub-2',
node_type: 'logistics',
name: 'Demo Moscow Hub',
latitude: 55.755826,
longitude: 37.6173,
country: 'Russia',
country_code: 'RU',
transport_types: ['AUTO', 'RAIL'],
synced_at: now,
},
{
_key: 'logistics-demo-hub-3',
node_type: 'logistics',
name: 'Demo Urumqi Hub',
latitude: 43.825592,
longitude: 87.616848,
country: 'China',
country_code: 'CN',
transport_types: ['AUTO', 'RAIL'],
synced_at: now,
},
]
const suppliers: DemoSupplier[] = [
{
uuid: '66666666-2222-4111-8111-111111111111',
name: 'Demo Supplier Almaty',
latitude: 43.25667,
longitude: 76.92861,
country: 'Kazakhstan',
country_code: 'KZ',
hubKey: 'logistics-demo-hub-1',
},
{
uuid: '66666666-2222-4111-8111-222222222222',
name: 'Demo Supplier Urumqi',
latitude: 43.825592,
longitude: 87.616848,
country: 'China',
country_code: 'CN',
hubKey: 'logistics-demo-hub-3',
},
{
uuid: '66666666-2222-4111-8111-333333333333',
name: 'Demo Supplier Moscow',
latitude: 55.755826,
longitude: 37.6173,
country: 'Russia',
country_code: 'RU',
hubKey: 'logistics-demo-hub-2',
},
]
function quoteUuid(index: number) {
return `77777777-3333-4${String(index).padStart(3, '0')}-8${String(index).padStart(3, '0')}-777777${String(index).padStart(6, '0')}`
}
function hubByKey(key: string) {
const hub = hubs.find(item => item._key === key)
if (!hub) throw new Error(`Unknown demo hub: ${key}`)
return hub
}
const supplierNodes: GeoNode[] = suppliers.map(supplier => ({
_key: supplier.uuid,
node_type: 'supplier',
name: supplier.name,
latitude: supplier.latitude,
longitude: supplier.longitude,
country: supplier.country,
country_code: supplier.country_code,
synced_at: now,
}))
const offers: GeoNode[] = Array.from({ length: 24 }, (_, index) => {
const product = products[index % products.length]
const supplier = suppliers[Math.floor(index / products.length) % suppliers.length]
const localIndex = Math.floor(index / suppliers.length)
const latitudeOffset = ((localIndex % 3) - 1) * 0.08
const longitudeOffset = (Math.floor(localIndex / 3) - 1) * 0.1
return {
_key: quoteUuid(index),
node_type: 'offer',
name: `${supplier.name} ${product.name}`,
latitude: supplier.latitude + latitudeOffset,
longitude: supplier.longitude + longitudeOffset,
country: supplier.country,
country_code: supplier.country_code,
product_uuid: product.uuid,
product_name: product.name,
supplier_uuid: supplier.uuid,
supplier_name: supplier.name,
price_per_unit: String(900 + (index % 8) * 55),
currency: 'USD',
quantity: String(500 + index * 25),
unit: product.unit,
synced_at: now,
}
})
for (const node of [...hubs, ...offers, ...supplierNodes]) {
await upsertNode(node)
}
const hubLinks = [
{
from: 'logistics-demo-hub-1',
to: 'logistics-demo-hub-2',
distanceKm: 3950,
travelTimeSeconds: 864000,
transportType: 'rail',
},
{
from: 'logistics-demo-hub-2',
to: 'logistics-demo-hub-1',
distanceKm: 3950,
travelTimeSeconds: 864000,
transportType: 'rail',
},
{
from: 'logistics-demo-hub-1',
to: 'logistics-demo-hub-3',
distanceKm: 1050,
travelTimeSeconds: 172800,
transportType: 'auto',
},
{
from: 'logistics-demo-hub-3',
to: 'logistics-demo-hub-1',
distanceKm: 1050,
travelTimeSeconds: 172800,
transportType: 'auto',
},
{
from: 'logistics-demo-hub-3',
to: 'logistics-demo-hub-2',
distanceKm: 4650,
travelTimeSeconds: 950400,
transportType: 'rail',
},
{
from: 'logistics-demo-hub-2',
to: 'logistics-demo-hub-3',
distanceKm: 4650,
travelTimeSeconds: 950400,
transportType: 'rail',
},
]
for (const [index, link] of hubLinks.entries()) {
const toHub = hubByKey(link.to)
await upsertEdge({
_key: `geo-demo-hub-edge-${index + 1}`,
_from: `nodes/${link.from}`,
_to: `nodes/${link.to}`,
to_uuid: link.to,
to_name: toHub.name,
to_latitude: toHub.latitude,
to_longitude: toHub.longitude,
distance_km: link.distanceKm,
travel_time_seconds: link.travelTimeSeconds,
transport_type: link.transportType,
})
}
for (const [index, offer] of offers.entries()) {
const supplier = suppliers[Math.floor(index / products.length) % suppliers.length]
await upsertEdge({
_key: `geo-demo-offer-edge-${index + 1}`,
_from: `nodes/${supplier.hubKey}`,
_to: `nodes/${offer._key}`,
to_uuid: offer._key,
to_name: offer.name,
to_latitude: offer.latitude,
to_longitude: offer.longitude,
distance_km: Math.max(1, Math.round(Math.hypot((offer.latitude - supplier.latitude) * 111, (offer.longitude - supplier.longitude) * 75))),
travel_time_seconds: 3600 + index * 120,
transport_type: 'offer',
})
}
console.log(`Seeded geo demo data: hubs ${hubs.length}, offers ${offers.length}, suppliers ${suppliers.length}, edges ${hubLinks.length + offers.length}`)