Initial web

This commit is contained in:
Caesar2011
2026-05-17 19:55:53 +02:00
parent 6e3499812e
commit 20ed6ee9fb
58 changed files with 8541 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
/** @type {import('node-pg-migrate').MigrationBuilder} */
exports.up = (pgm) => {
pgm.sql(`CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE`);
pgm.createTable('signals', {
real_time: { type: 'timestamptz', notNull: true },
game_tick: { type: 'bigint', notNull: true },
combinator: { type: 'text', notNull: true },
item_key: { type: 'text', notNull: true },
green: { type: 'integer', notNull: true, default: 0 },
red: { type: 'integer', notNull: true, default: 0 },
logistic: { type: 'integer' },
}, { ifNotExists: true });
pgm.sql(`SELECT create_hypertable('signals', 'real_time', if_not_exists => true)`);
pgm.sql(`CREATE INDEX IF NOT EXISTS signals_combinator_item_key_real_time_idx ON signals (combinator, item_key, real_time DESC)`);
pgm.sql(`CREATE INDEX IF NOT EXISTS signals_game_tick_idx ON signals (game_tick DESC)`);
pgm.sql(`SELECT add_retention_policy('signals', INTERVAL '30 days', if_not_exists => true)`);
pgm.createTable('tick_timing', {
real_time: { type: 'timestamptz', notNull: true },
game_tick: { type: 'bigint', notNull: true },
combinator: { type: 'text', notNull: true },
}, { ifNotExists: true });
pgm.sql(`SELECT create_hypertable('tick_timing', 'real_time', if_not_exists => true)`);
pgm.sql(`CREATE INDEX IF NOT EXISTS tick_timing_combinator_real_time_idx ON tick_timing (combinator, real_time DESC)`);
pgm.sql(`SELECT add_retention_policy('tick_timing', INTERVAL '30 days', if_not_exists => true)`);
pgm.createTable('charts', {
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
title: { type: 'text', notNull: true },
pos_x: { type: 'integer', notNull: true, default: 0 },
pos_y: { type: 'integer', notNull: true, default: 0 },
width: { type: 'integer', notNull: true, default: 2 },
height: { type: 'integer', notNull: true, default: 4 },
signal_type: { type: 'text', notNull: true, default: 'both' },
chart_type: { type: 'text', notNull: true, default: 'signals' },
viz_type: { type: 'text', notNull: true, default: 'line' },
filter_combinators: { type: 'text[]' },
filter_items: { type: 'text[]' },
filter_items_exclude: { type: 'text[]' },
filter_items_regex: { type: 'boolean', notNull: true, default: false },
y_min: { type: 'real' },
y_max: { type: 'real' },
series_limit: { type: 'integer', notNull: true, default: 20 },
order_by: { type: 'text', notNull: true, default: 'time' },
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
}, { ifNotExists: true });
// Use DO blocks so constraints are idempotent on existing DBs
pgm.sql(`DO $$ BEGIN
ALTER TABLE charts ADD CONSTRAINT charts_signal_type_check CHECK (signal_type IN ('green','red','both'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.sql(`DO $$ BEGIN
ALTER TABLE charts ADD CONSTRAINT charts_chart_type_check CHECK (chart_type IN ('signals','ups'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.sql(`DO $$ BEGIN
ALTER TABLE charts ADD CONSTRAINT charts_viz_type_check CHECK (viz_type IN ('line','stacked','table'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.sql(`DO $$ BEGIN
ALTER TABLE charts ADD CONSTRAINT charts_order_by_check CHECK (order_by IN ('time','value_asc','value_desc','abs_desc','delta_asc','delta_desc'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.createTable('alerts', {
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
item_key: { type: 'text', notNull: true },
item_key_is_regex: { type: 'boolean', notNull: true, default: false },
combinator: { type: 'text' },
signal_type: { type: 'text', notNull: true, default: 'green' },
condition: { type: 'text', notNull: true },
threshold: { type: 'integer', notNull: true },
active: { type: 'boolean', notNull: true, default: true },
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
}, { ifNotExists: true });
pgm.sql(`DO $$ BEGIN
ALTER TABLE alerts ADD CONSTRAINT alerts_signal_type_check CHECK (signal_type IN ('green','red'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.sql(`DO $$ BEGIN
ALTER TABLE alerts ADD CONSTRAINT alerts_condition_check CHECK (condition IN ('above','below'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.createTable('settings', {
key: { type: 'text', primaryKey: true },
value: { type: 'text', notNull: true },
}, { ifNotExists: true });
};
exports.down = () => Promise.resolve();

View File

@@ -0,0 +1,18 @@
/** @type {import('node-pg-migrate').MigrationBuilder} */
exports.up = (pgm) => {
pgm.sql(`ALTER TABLE charts ADD COLUMN IF NOT EXISTS y_scale TEXT NOT NULL DEFAULT 'linear'`);
pgm.sql(`DO $$ BEGIN
ALTER TABLE charts ADD CONSTRAINT charts_y_scale_check CHECK (y_scale IN ('linear','log'));
EXCEPTION WHEN duplicate_object THEN NULL; END $$`);
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_order_by_check`);
pgm.sql(`ALTER TABLE charts ADD CONSTRAINT charts_order_by_check CHECK (order_by IN ('time','value_asc','value_desc','abs_desc','delta_asc','delta_desc'))`);
};
exports.down = (pgm) => {
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_order_by_check`);
pgm.sql(`ALTER TABLE charts ADD CONSTRAINT charts_order_by_check CHECK (order_by IN ('time','value_asc','value_desc','abs_desc'))`);
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_y_scale_check`);
pgm.sql(`ALTER TABLE charts DROP COLUMN IF EXISTS y_scale`);
};

View File

@@ -0,0 +1,19 @@
/** @type {import('node-pg-migrate').MigrationBuilder} */
exports.up = (pgm) => {
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_viz_type_check`);
pgm.sql(`ALTER TABLE charts ADD CONSTRAINT charts_viz_type_check CHECK (viz_type IN ('line','table'))`);
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_chart_type_check`);
pgm.sql(`ALTER TABLE charts ADD CONSTRAINT charts_chart_type_check CHECK (chart_type IN ('signals','ups','divider'))`);
// Migrate any existing stacked charts to line
pgm.sql(`UPDATE charts SET viz_type = 'line' WHERE viz_type = 'stacked'`);
};
exports.down = (pgm) => {
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_viz_type_check`);
pgm.sql(`ALTER TABLE charts ADD CONSTRAINT charts_viz_type_check CHECK (viz_type IN ('line','stacked','table'))`);
pgm.sql(`ALTER TABLE charts DROP CONSTRAINT IF EXISTS charts_chart_type_check`);
pgm.sql(`ALTER TABLE charts ADD CONSTRAINT charts_chart_type_check CHECK (chart_type IN ('signals','ups'))`);
};