chore(payload): regenerate types and schema, harden sequence reset
- Regenerate payload-types and the drizzle schema for the new collections and fields (promotion nominations, leadership transfers, the accessory asset type, the Ornith model settings) and register the new migrations. - Fix the reset-sequences SQL function to skip empty tables, and update the prod sync script to match.
This commit is contained in:
parent
35150e73ac
commit
d9253e6725
6 changed files with 556 additions and 23 deletions
|
|
@ -1,8 +1,9 @@
|
|||
SELECT
|
||||
'SELECT SETVAL(' ||
|
||||
quote_literal(quote_ident(sequence_namespace.nspname) || '.' || quote_ident(class_sequence.relname)) ||
|
||||
', COALESCE(MAX(' ||quote_ident(pg_attribute.attname)|| '), 1) ) FROM ' ||
|
||||
quote_ident(table_namespace.nspname)|| '.'||quote_ident(class_table.relname)|| ';'
|
||||
', COALESCE(MAX(' || quote_ident(pg_attribute.attname) || '), 1), ' ||
|
||||
'MAX(' || quote_ident(pg_attribute.attname) || ') IS NOT NULL) FROM ' ||
|
||||
quote_ident(table_namespace.nspname) || '.' || quote_ident(class_table.relname) || ';'
|
||||
FROM pg_depend
|
||||
INNER JOIN pg_class AS class_sequence
|
||||
ON class_sequence.oid = pg_depend.objid
|
||||
|
|
|
|||
|
|
@ -317,13 +317,34 @@ restore_ai_instructions() {
|
|||
|| warn "Failed to reload ${AI_INSTRUCTIONS_IMAGES_TABLE} (non-fatal)"
|
||||
fi
|
||||
|
||||
PGPASSWORD="$TARGET_DB_PASS" psql \
|
||||
ok "AI Compose prompts preserved (no regeneration needed on next boot)"
|
||||
}
|
||||
|
||||
reset_sequences() {
|
||||
info "Resetting sequences..."
|
||||
|
||||
local has_function
|
||||
has_function=$(PGPASSWORD="$TARGET_DB_PASS" psql \
|
||||
-h "$TARGET_DB_HOST" -p "$TARGET_DB_PORT" -U "$TARGET_DB_USER" \
|
||||
-d "$TARGET_DB_NAME" \
|
||||
-c "SELECT setval(pg_get_serial_sequence('${AI_INSTRUCTIONS_TABLE}', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM ${AI_INSTRUCTIONS_TABLE}), 1), 1));" >/dev/null 2>&1 \
|
||||
|| true
|
||||
-tAc "SELECT to_regclass('maintenance.reset_owned_sequences(text)') IS NOT NULL;" 2>/dev/null)
|
||||
|
||||
ok "AI Compose prompts preserved (no regeneration needed on next boot)"
|
||||
if [[ "$has_function" != "t" ]]; then
|
||||
warn "maintenance.reset_owned_sequences not available (migrations skipped or not applied); skipping sequence reset"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! PGPASSWORD="$TARGET_DB_PASS" psql \
|
||||
-h "$TARGET_DB_HOST" \
|
||||
-p "$TARGET_DB_PORT" \
|
||||
-U "$TARGET_DB_USER" \
|
||||
-d "$TARGET_DB_NAME" \
|
||||
-v ON_ERROR_STOP=1 \
|
||||
-c "SELECT * FROM maintenance.reset_owned_sequences('public');"; then
|
||||
die "Failed to reset sequences"
|
||||
fi
|
||||
|
||||
ok "Sequences reset"
|
||||
}
|
||||
|
||||
sync_database() {
|
||||
|
|
@ -395,15 +416,8 @@ sync_database() {
|
|||
fi
|
||||
fi
|
||||
|
||||
info "Resetting sequences..."
|
||||
PGPASSWORD="$TARGET_DB_PASS" psql \
|
||||
-h "$TARGET_DB_HOST" \
|
||||
-p "$TARGET_DB_PORT" \
|
||||
-U "$TARGET_DB_USER" \
|
||||
-d "$TARGET_DB_NAME" \
|
||||
-c "SELECT setval(pg_get_serial_sequence(t.table_name, c.column_name), (SELECT COALESCE(MAX(c.column_name::text::bigint), 1) FROM information_schema.columns c JOIN information_schema.tables t ON c.table_name = t.table_name WHERE c.column_name = 'id')) FROM information_schema.columns c JOIN information_schema.tables t ON c.table_name = t.table_name WHERE c.column_name = 'id' AND c.column_default LIKE 'nextval%' AND t.table_schema = 'public';" 2>/dev/null || true
|
||||
|
||||
restore_ai_instructions
|
||||
reset_sequences
|
||||
|
||||
ok "Database sync complete: ${TARGET_DB_NAME}"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||
|
||||
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
CREATE SCHEMA IF NOT EXISTS maintenance;
|
||||
|
||||
CREATE OR REPLACE FUNCTION maintenance.reset_owned_sequences(
|
||||
target_schema text DEFAULT 'public'
|
||||
)
|
||||
RETURNS TABLE (
|
||||
sequence_name text,
|
||||
table_name text,
|
||||
column_name text,
|
||||
previous_value bigint,
|
||||
new_value bigint,
|
||||
is_called boolean
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
sequence_record record;
|
||||
max_value bigint;
|
||||
prior_value bigint;
|
||||
should_be_called boolean;
|
||||
BEGIN
|
||||
FOR sequence_record IN
|
||||
SELECT
|
||||
sequence_namespace.nspname AS sequence_schema,
|
||||
class_sequence.relname AS sequence_name,
|
||||
table_namespace.nspname AS table_schema,
|
||||
class_table.relname AS table_name,
|
||||
pg_attribute.attname AS column_name
|
||||
FROM pg_depend
|
||||
INNER JOIN pg_class AS class_sequence
|
||||
ON class_sequence.oid = pg_depend.objid
|
||||
AND class_sequence.relkind = 'S'
|
||||
INNER JOIN pg_class AS class_table
|
||||
ON class_table.oid = pg_depend.refobjid
|
||||
INNER JOIN pg_attribute
|
||||
ON pg_attribute.attrelid = class_table.oid
|
||||
AND pg_depend.refobjsubid = pg_attribute.attnum
|
||||
INNER JOIN pg_namespace AS table_namespace
|
||||
ON table_namespace.oid = class_table.relnamespace
|
||||
INNER JOIN pg_namespace AS sequence_namespace
|
||||
ON sequence_namespace.oid = class_sequence.relnamespace
|
||||
WHERE table_namespace.nspname = target_schema
|
||||
AND pg_depend.deptype IN ('a', 'i')
|
||||
ORDER BY sequence_namespace.nspname, class_sequence.relname
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'SELECT COALESCE(MAX(%I), 1), MAX(%I) IS NOT NULL FROM %I.%I',
|
||||
sequence_record.column_name,
|
||||
sequence_record.column_name,
|
||||
sequence_record.table_schema,
|
||||
sequence_record.table_name
|
||||
)
|
||||
INTO max_value, should_be_called;
|
||||
|
||||
EXECUTE format(
|
||||
'SELECT last_value FROM %I.%I',
|
||||
sequence_record.sequence_schema,
|
||||
sequence_record.sequence_name
|
||||
)
|
||||
INTO prior_value;
|
||||
|
||||
EXECUTE format(
|
||||
'SELECT setval(%L, %s, %L)',
|
||||
format('%I.%I', sequence_record.sequence_schema, sequence_record.sequence_name),
|
||||
max_value,
|
||||
should_be_called
|
||||
);
|
||||
|
||||
sequence_name := format('%I.%I', sequence_record.sequence_schema, sequence_record.sequence_name);
|
||||
table_name := format('%I.%I', sequence_record.table_schema, sequence_record.table_name);
|
||||
column_name := sequence_record.column_name;
|
||||
previous_value := prior_value;
|
||||
new_value := max_value;
|
||||
is_called := should_be_called;
|
||||
|
||||
RETURN NEXT;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
`)
|
||||
}
|
||||
|
||||
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
DROP FUNCTION IF EXISTS maintenance.reset_owned_sequences(text);
|
||||
`)
|
||||
}
|
||||
|
|
@ -97,6 +97,10 @@ import * as migration_20260928_021138_change_ai_model from './20260928_021138_ch
|
|||
import * as migration_20260930_162200_add_documentation_wiki_category from './20260930_162200_add_documentation_wiki_category';
|
||||
import * as migration_20260930_230747_add_tech_categories from './20260930_230747_add_tech_categories';
|
||||
import * as migration_20261001_000320_add_tech_tree_position from './20261001_000320_add_tech_tree_position';
|
||||
import * as migration_20261001_000400_add_reset_owned_sequences_function from './20261001_000400_add_reset_owned_sequences_function';
|
||||
import * as migration_20261002_031917_add_promotion_nominations_and_leadership_transfers from './20261002_031917_add_promotion_nominations_and_leadership_transfers';
|
||||
import * as migration_20261002_180000_add_asset_type_accessory from './20261002_180000_add_asset_type_accessory';
|
||||
import * as migration_20261003_060154_change_ai_model_to_ornith from './20261003_060154_change_ai_model_to_ornith';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
|
|
@ -592,6 +596,26 @@ export const migrations = [
|
|||
{
|
||||
up: migration_20261001_000320_add_tech_tree_position.up,
|
||||
down: migration_20261001_000320_add_tech_tree_position.down,
|
||||
name: '20261001_000320_add_tech_tree_position'
|
||||
name: '20261001_000320_add_tech_tree_position',
|
||||
},
|
||||
{
|
||||
up: migration_20261001_000400_add_reset_owned_sequences_function.up,
|
||||
down: migration_20261001_000400_add_reset_owned_sequences_function.down,
|
||||
name: '20261001_000400_add_reset_owned_sequences_function',
|
||||
},
|
||||
{
|
||||
up: migration_20261002_031917_add_promotion_nominations_and_leadership_transfers.up,
|
||||
down: migration_20261002_031917_add_promotion_nominations_and_leadership_transfers.down,
|
||||
name: '20261002_031917_add_promotion_nominations_and_leadership_transfers'
|
||||
},
|
||||
{
|
||||
up: migration_20261002_180000_add_asset_type_accessory.up,
|
||||
down: migration_20261002_180000_add_asset_type_accessory.down,
|
||||
name: '20261002_180000_add_asset_type_accessory'
|
||||
},
|
||||
{
|
||||
up: migration_20261003_060154_change_ai_model_to_ornith.up,
|
||||
down: migration_20261003_060154_change_ai_model_to_ornith.down,
|
||||
name: '20261003_060154_change_ai_model_to_ornith'
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ export const enum_game_event_logs_target_collection = pgEnum(
|
|||
"custom-radio-tests",
|
||||
"custom-radio-test-scores",
|
||||
"ribbon-submissions",
|
||||
"promotion-nominations",
|
||||
"leadership-transfers",
|
||||
],
|
||||
);
|
||||
export const enum_users_roles = pgEnum("enum_users_roles", [
|
||||
|
|
@ -575,6 +577,23 @@ export const enum_ribbon_submissions_recipient_scope = pgEnum(
|
|||
"enum_ribbon_submissions_recipient_scope",
|
||||
["same_command", "whitelist", "anyone"],
|
||||
);
|
||||
export const enum_promotion_nominations_status = pgEnum("enum_promotion_nominations_status", [
|
||||
"pending",
|
||||
"awaiting_superuser",
|
||||
"approved",
|
||||
"rejected",
|
||||
"cancelled",
|
||||
]);
|
||||
export const enum_promotion_nominations_leader_decision = pgEnum(
|
||||
"enum_promotion_nominations_leader_decision",
|
||||
["pending", "endorsed", "rejected", "not_required"],
|
||||
);
|
||||
export const enum_leadership_transfers_status = pgEnum("enum_leadership_transfers_status", [
|
||||
"pending",
|
||||
"approved",
|
||||
"denied",
|
||||
"cancelled",
|
||||
]);
|
||||
export const enum_missions_factions_involved_threat_level = pgEnum(
|
||||
"enum_missions_factions_involved_threat_level",
|
||||
["ally", "friendly", "neutral", "hostile"],
|
||||
|
|
@ -1031,7 +1050,7 @@ export const enum_plugin_ai_instructions_field_type = pgEnum(
|
|||
["text", "textarea", "upload", "richText"],
|
||||
);
|
||||
export const enum_plugin_ai_instructions_model_id = pgEnum("enum_plugin_ai_instructions_model_id", [
|
||||
"unsloth/gemma-4-26B-A4B-it-qat-GGUF",
|
||||
"unsloth/Ornith-1.0-9B-GGUF",
|
||||
]);
|
||||
export const enum_shims_shims_targeting_roles = pgEnum("enum_shims_shims_targeting_roles", [
|
||||
"guest",
|
||||
|
|
@ -2741,6 +2760,104 @@ export const ribbon_submissions = pgTable(
|
|||
],
|
||||
);
|
||||
|
||||
export const promotion_nominations = pgTable(
|
||||
"promotion_nominations",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
nominee: integer("nominee_id")
|
||||
.notNull()
|
||||
.references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
nominator: integer("nominator_id")
|
||||
.notNull()
|
||||
.references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
accolades: varchar("accolades").notNull(),
|
||||
status: enum_promotion_nominations_status("status").notNull().default("pending"),
|
||||
leaderDecision:
|
||||
enum_promotion_nominations_leader_decision("leader_decision").default("pending"),
|
||||
leaderDecisionBy: integer("leader_decision_by_id").references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
leaderDecidedAt: timestamp("leader_decided_at", {
|
||||
mode: "string",
|
||||
withTimezone: true,
|
||||
precision: 3,
|
||||
}),
|
||||
leaderNote: varchar("leader_note"),
|
||||
reviewNote: varchar("review_note"),
|
||||
reviewedBy: integer("reviewed_by_id").references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
reviewedAt: timestamp("reviewed_at", { mode: "string", withTimezone: true, precision: 3 }),
|
||||
updatedAt: timestamp("updated_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
},
|
||||
(columns) => [
|
||||
index("promotion_nominations_nominee_idx").on(columns.nominee),
|
||||
index("promotion_nominations_nominator_idx").on(columns.nominator),
|
||||
index("promotion_nominations_leader_decision_by_idx").on(columns.leaderDecisionBy),
|
||||
index("promotion_nominations_reviewed_by_idx").on(columns.reviewedBy),
|
||||
index("promotion_nominations_updated_at_idx").on(columns.updatedAt),
|
||||
index("promotion_nominations_created_at_idx").on(columns.createdAt),
|
||||
],
|
||||
);
|
||||
|
||||
export const leadership_transfers = pgTable(
|
||||
"leadership_transfers",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
initiator: integer("initiator_id")
|
||||
.notNull()
|
||||
.references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
subject: integer("subject_id")
|
||||
.notNull()
|
||||
.references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
fromAssignment: integer("from_assignment_id")
|
||||
.notNull()
|
||||
.references(() => assignments.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
toAssignment: integer("to_assignment_id")
|
||||
.notNull()
|
||||
.references(() => assignments.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
reason: varchar("reason"),
|
||||
status: enum_leadership_transfers_status("status").notNull().default("pending"),
|
||||
reviewNote: varchar("review_note"),
|
||||
reviewedBy: integer("reviewed_by_id").references(() => users.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
resolvedAt: timestamp("resolved_at", { mode: "string", withTimezone: true, precision: 3 }),
|
||||
updatedAt: timestamp("updated_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
},
|
||||
(columns) => [
|
||||
index("leadership_transfers_initiator_idx").on(columns.initiator),
|
||||
index("leadership_transfers_subject_idx").on(columns.subject),
|
||||
index("leadership_transfers_from_assignment_idx").on(columns.fromAssignment),
|
||||
index("leadership_transfers_to_assignment_idx").on(columns.toAssignment),
|
||||
index("leadership_transfers_reviewed_by_idx").on(columns.reviewedBy),
|
||||
index("leadership_transfers_updated_at_idx").on(columns.updatedAt),
|
||||
index("leadership_transfers_created_at_idx").on(columns.createdAt),
|
||||
],
|
||||
);
|
||||
|
||||
export const missions_mission_roles_provided_roles = pgTable(
|
||||
"missions_mission_roles_provided_roles",
|
||||
{
|
||||
|
|
@ -6752,8 +6869,8 @@ export const plugin_ai_instructions = pgTable(
|
|||
layout: varchar("layout").default(
|
||||
'[paragraph] - Write a concise introduction (2-3 sentences) that outlines the main topic.\n[horizontalrule] - Insert a horizontal rule to separate the introduction from the main content.\n[list] - Create a list with 3-5 items. Each list item should contain:\n a. [heading] - A brief, descriptive heading (up to 5 words)\n b. [paragraph] - A short explanation or elaboration (1-2 sentences)\n[horizontalrule] - Insert another horizontal rule to separate the main content from the conclusion.\n[paragraph] - Compose a brief conclusion (2-3 sentences) summarizing the key points.\n[quote] - Include a relevant quote from a famous person, directly related to the topic. Format: "Quote text." - Author Name',
|
||||
),
|
||||
"gemma-4-settings_model": varchar("gemma_4_settings_model").default(
|
||||
"unsloth/gemma-4-26B-A4B-it-qat-GGUF",
|
||||
"ornith-9b-settings_model": varchar("ornith_9b_settings_model").default(
|
||||
"unsloth/Ornith-1.0-9B-GGUF",
|
||||
),
|
||||
updatedAt: timestamp("updated_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
|
|
@ -6864,6 +6981,14 @@ export const payload_mcp_api_keys = pgTable(
|
|||
ribbonSubmissions_create: boolean("ribbon_submissions_create").default(false),
|
||||
ribbonSubmissions_update: boolean("ribbon_submissions_update").default(false),
|
||||
ribbonSubmissions_delete: boolean("ribbon_submissions_delete").default(false),
|
||||
promotionNominations_find: boolean("promotion_nominations_find").default(false),
|
||||
promotionNominations_create: boolean("promotion_nominations_create").default(false),
|
||||
promotionNominations_update: boolean("promotion_nominations_update").default(false),
|
||||
promotionNominations_delete: boolean("promotion_nominations_delete").default(false),
|
||||
leadershipTransfers_find: boolean("leadership_transfers_find").default(false),
|
||||
leadershipTransfers_create: boolean("leadership_transfers_create").default(false),
|
||||
leadershipTransfers_update: boolean("leadership_transfers_update").default(false),
|
||||
leadershipTransfers_delete: boolean("leadership_transfers_delete").default(false),
|
||||
missions_find: boolean("missions_find").default(false),
|
||||
missions_create: boolean("missions_create").default(false),
|
||||
missions_update: boolean("missions_update").default(false),
|
||||
|
|
@ -7158,6 +7283,8 @@ export const payload_locked_documents_rels = pgTable(
|
|||
"user-notificationsID": integer("user_notifications_id"),
|
||||
evaluationsID: integer("evaluations_id"),
|
||||
"ribbon-submissionsID": integer("ribbon_submissions_id"),
|
||||
"promotion-nominationsID": integer("promotion_nominations_id"),
|
||||
"leadership-transfersID": integer("leadership_transfers_id"),
|
||||
missionsID: integer("missions_id"),
|
||||
"mission-attendancesID": integer("mission_attendances_id"),
|
||||
"mission-role-signupsID": integer("mission_role_signups_id"),
|
||||
|
|
@ -7253,6 +7380,12 @@ export const payload_locked_documents_rels = pgTable(
|
|||
index("payload_locked_documents_rels_ribbon_submissions_id_idx").on(
|
||||
columns["ribbon-submissionsID"],
|
||||
),
|
||||
index("payload_locked_documents_rels_promotion_nominations_id_idx").on(
|
||||
columns["promotion-nominationsID"],
|
||||
),
|
||||
index("payload_locked_documents_rels_leadership_transfers_id_idx").on(
|
||||
columns["leadership-transfersID"],
|
||||
),
|
||||
index("payload_locked_documents_rels_missions_id_idx").on(columns.missionsID),
|
||||
index("payload_locked_documents_rels_mission_attendances_id_idx").on(
|
||||
columns["mission-attendancesID"],
|
||||
|
|
@ -7462,6 +7595,16 @@ export const payload_locked_documents_rels = pgTable(
|
|||
foreignColumns: [ribbon_submissions.id],
|
||||
name: "payload_locked_documents_rels_ribbon_submissions_fk",
|
||||
}).onDelete("cascade"),
|
||||
foreignKey({
|
||||
columns: [columns["promotion-nominationsID"]],
|
||||
foreignColumns: [promotion_nominations.id],
|
||||
name: "payload_locked_documents_rels_promotion_nominations_fk",
|
||||
}).onDelete("cascade"),
|
||||
foreignKey({
|
||||
columns: [columns["leadership-transfersID"]],
|
||||
foreignColumns: [leadership_transfers.id],
|
||||
name: "payload_locked_documents_rels_leadership_transfers_fk",
|
||||
}).onDelete("cascade"),
|
||||
foreignKey({
|
||||
columns: [columns["missionsID"]],
|
||||
foreignColumns: [missions.id],
|
||||
|
|
@ -7851,6 +7994,9 @@ export const game_rules = pgTable(
|
|||
currencySingular: varchar("currency_singular"),
|
||||
currencyPlural: varchar("currency_plural"),
|
||||
currencyDenomination: varchar("currency_denomination"),
|
||||
infantryAssignment: integer("infantry_assignment_id").references(() => assignments.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
proximityThreshold: numeric("proximity_threshold", { mode: "number" }).default(1000),
|
||||
gameTickIntervalMinutes: numeric("game_tick_interval_minutes", { mode: "number" }).default(10),
|
||||
lockerGridWidth: numeric("locker_grid_width", { mode: "number" }).default(10),
|
||||
|
|
@ -7883,6 +8029,7 @@ export const game_rules = pgTable(
|
|||
(columns) => [
|
||||
index("game_rules_main_currency_idx").on(columns.mainCurrency),
|
||||
index("game_rules_currency_symbol_idx").on(columns.currencySymbol),
|
||||
index("game_rules_infantry_assignment_idx").on(columns.infantryAssignment),
|
||||
],
|
||||
);
|
||||
|
||||
|
|
@ -8640,6 +8787,55 @@ export const relations_ribbon_submissions = relations(ribbon_submissions, ({ one
|
|||
relationName: "grantorTypes",
|
||||
}),
|
||||
}));
|
||||
export const relations_promotion_nominations = relations(promotion_nominations, ({ one }) => ({
|
||||
nominee: one(users, {
|
||||
fields: [promotion_nominations.nominee],
|
||||
references: [users.id],
|
||||
relationName: "nominee",
|
||||
}),
|
||||
nominator: one(users, {
|
||||
fields: [promotion_nominations.nominator],
|
||||
references: [users.id],
|
||||
relationName: "nominator",
|
||||
}),
|
||||
leaderDecisionBy: one(users, {
|
||||
fields: [promotion_nominations.leaderDecisionBy],
|
||||
references: [users.id],
|
||||
relationName: "leaderDecisionBy",
|
||||
}),
|
||||
reviewedBy: one(users, {
|
||||
fields: [promotion_nominations.reviewedBy],
|
||||
references: [users.id],
|
||||
relationName: "reviewedBy",
|
||||
}),
|
||||
}));
|
||||
export const relations_leadership_transfers = relations(leadership_transfers, ({ one }) => ({
|
||||
initiator: one(users, {
|
||||
fields: [leadership_transfers.initiator],
|
||||
references: [users.id],
|
||||
relationName: "initiator",
|
||||
}),
|
||||
subject: one(users, {
|
||||
fields: [leadership_transfers.subject],
|
||||
references: [users.id],
|
||||
relationName: "subject",
|
||||
}),
|
||||
fromAssignment: one(assignments, {
|
||||
fields: [leadership_transfers.fromAssignment],
|
||||
references: [assignments.id],
|
||||
relationName: "fromAssignment",
|
||||
}),
|
||||
toAssignment: one(assignments, {
|
||||
fields: [leadership_transfers.toAssignment],
|
||||
references: [assignments.id],
|
||||
relationName: "toAssignment",
|
||||
}),
|
||||
reviewedBy: one(users, {
|
||||
fields: [leadership_transfers.reviewedBy],
|
||||
references: [users.id],
|
||||
relationName: "reviewedBy",
|
||||
}),
|
||||
}));
|
||||
export const relations_missions_mission_roles_provided_roles = relations(
|
||||
missions_mission_roles_provided_roles,
|
||||
({ one }) => ({
|
||||
|
|
@ -10535,6 +10731,16 @@ export const relations_payload_locked_documents_rels = relations(
|
|||
references: [ribbon_submissions.id],
|
||||
relationName: "ribbon-submissions",
|
||||
}),
|
||||
"promotion-nominationsID": one(promotion_nominations, {
|
||||
fields: [payload_locked_documents_rels["promotion-nominationsID"]],
|
||||
references: [promotion_nominations.id],
|
||||
relationName: "promotion-nominations",
|
||||
}),
|
||||
"leadership-transfersID": one(leadership_transfers, {
|
||||
fields: [payload_locked_documents_rels["leadership-transfersID"]],
|
||||
references: [leadership_transfers.id],
|
||||
relationName: "leadership-transfers",
|
||||
}),
|
||||
missionsID: one(missions, {
|
||||
fields: [payload_locked_documents_rels.missionsID],
|
||||
references: [missions.id],
|
||||
|
|
@ -10889,6 +11095,11 @@ export const relations_game_rules = relations(game_rules, ({ one, many }) => ({
|
|||
references: [media.id],
|
||||
relationName: "currencySymbol",
|
||||
}),
|
||||
infantryAssignment: one(assignments, {
|
||||
fields: [game_rules.infantryAssignment],
|
||||
references: [assignments.id],
|
||||
relationName: "infantryAssignment",
|
||||
}),
|
||||
_rels: many(game_rules_rels, {
|
||||
relationName: "_rels",
|
||||
}),
|
||||
|
|
@ -10974,6 +11185,9 @@ type DatabaseSchema = {
|
|||
enum_ribbon_submissions_grantor_types: typeof enum_ribbon_submissions_grantor_types;
|
||||
enum_ribbon_submissions_status: typeof enum_ribbon_submissions_status;
|
||||
enum_ribbon_submissions_recipient_scope: typeof enum_ribbon_submissions_recipient_scope;
|
||||
enum_promotion_nominations_status: typeof enum_promotion_nominations_status;
|
||||
enum_promotion_nominations_leader_decision: typeof enum_promotion_nominations_leader_decision;
|
||||
enum_leadership_transfers_status: typeof enum_leadership_transfers_status;
|
||||
enum_missions_factions_involved_threat_level: typeof enum_missions_factions_involved_threat_level;
|
||||
enum_missions_logistics_and_support_insertion: typeof enum_missions_logistics_and_support_insertion;
|
||||
enum_missions_logistics_and_support_extraction: typeof enum_missions_logistics_and_support_extraction;
|
||||
|
|
@ -11109,6 +11323,8 @@ type DatabaseSchema = {
|
|||
evaluations: typeof evaluations;
|
||||
ribbon_submissions_grantor_types: typeof ribbon_submissions_grantor_types;
|
||||
ribbon_submissions: typeof ribbon_submissions;
|
||||
promotion_nominations: typeof promotion_nominations;
|
||||
leadership_transfers: typeof leadership_transfers;
|
||||
missions_mission_roles_provided_roles: typeof missions_mission_roles_provided_roles;
|
||||
missions_briefing: typeof missions_briefing;
|
||||
missions_mission_objectives: typeof missions_mission_objectives;
|
||||
|
|
@ -11299,6 +11515,8 @@ type DatabaseSchema = {
|
|||
relations_evaluations: typeof relations_evaluations;
|
||||
relations_ribbon_submissions_grantor_types: typeof relations_ribbon_submissions_grantor_types;
|
||||
relations_ribbon_submissions: typeof relations_ribbon_submissions;
|
||||
relations_promotion_nominations: typeof relations_promotion_nominations;
|
||||
relations_leadership_transfers: typeof relations_leadership_transfers;
|
||||
relations_missions_mission_roles_provided_roles: typeof relations_missions_mission_roles_provided_roles;
|
||||
relations_missions_briefing: typeof relations_missions_briefing;
|
||||
relations_missions_mission_objectives: typeof relations_missions_mission_objectives;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ export interface Config {
|
|||
'user-notifications': UserNotification;
|
||||
evaluations: Evaluation;
|
||||
'ribbon-submissions': RibbonSubmission;
|
||||
'promotion-nominations': PromotionNomination;
|
||||
'leadership-transfers': LeadershipTransfer;
|
||||
missions: Mission;
|
||||
'mission-attendances': MissionAttendance;
|
||||
'mission-role-signups': MissionRoleSignup;
|
||||
|
|
@ -183,6 +185,8 @@ export interface Config {
|
|||
'user-notifications': UserNotificationsSelect<false> | UserNotificationsSelect<true>;
|
||||
evaluations: EvaluationsSelect<false> | EvaluationsSelect<true>;
|
||||
'ribbon-submissions': RibbonSubmissionsSelect<false> | RibbonSubmissionsSelect<true>;
|
||||
'promotion-nominations': PromotionNominationsSelect<false> | PromotionNominationsSelect<true>;
|
||||
'leadership-transfers': LeadershipTransfersSelect<false> | LeadershipTransfersSelect<true>;
|
||||
missions: MissionsSelect<false> | MissionsSelect<true>;
|
||||
'mission-attendances': MissionAttendancesSelect<false> | MissionAttendancesSelect<true>;
|
||||
'mission-role-signups': MissionRoleSignupsSelect<false> | MissionRoleSignupsSelect<true>;
|
||||
|
|
@ -1685,6 +1689,7 @@ export interface Asset {
|
|||
| 'optic'
|
||||
| 'muzzle'
|
||||
| 'bipod'
|
||||
| 'accessory'
|
||||
| 'uniform'
|
||||
| 'vest'
|
||||
| 'backpack'
|
||||
|
|
@ -2386,6 +2391,8 @@ export interface GameEventLog {
|
|||
| 'custom-radio-tests'
|
||||
| 'custom-radio-test-scores'
|
||||
| 'ribbon-submissions'
|
||||
| 'promotion-nominations'
|
||||
| 'leadership-transfers'
|
||||
)
|
||||
| null;
|
||||
targetId?: number | null;
|
||||
|
|
@ -2951,11 +2958,11 @@ export interface Mission {
|
|||
*/
|
||||
evaluationRemindersSentAt?: string | null;
|
||||
/**
|
||||
* Server-local day the last web 'not Ready' reminder notification was sent to the op creator (managed by the mission tick, once per day).
|
||||
* Server-local day the last web 'not Scheduled' reminder notification was sent to the op creator (managed by the mission tick, once per day).
|
||||
*/
|
||||
readyReminderWebSentAt?: string | null;
|
||||
/**
|
||||
* Server-local day the last 'not Ready' reminder DM was sent to the op creator (managed by the Discord bot, once per day).
|
||||
* Server-local day the last 'not Scheduled' reminder DM was sent to the op creator (managed by the Discord bot, once per day).
|
||||
*/
|
||||
readyReminderDmSentAt?: string | null;
|
||||
/**
|
||||
|
|
@ -2988,6 +2995,9 @@ export interface Mission {
|
|||
ownershipAndStatus: {
|
||||
authors: (number | User)[];
|
||||
zeus?: (number | User)[] | null;
|
||||
/**
|
||||
* Side operations start as Ready (a quiet draft) and are committed to Scheduled by their creator, which posts the Discord roll-call. Only Scheduled/Active missions are driven by the automatic start/complete lifecycle; Concept/Planning/Ready are drafts.
|
||||
*/
|
||||
status: 'Concept' | 'Planning' | 'Ready' | 'Scheduled' | 'Active' | 'Completed' | 'Cancelled';
|
||||
visibility: 'unit' | 'leadership' | 'intel' | 'private';
|
||||
/**
|
||||
|
|
@ -3270,6 +3280,80 @@ export interface RibbonSubmission {
|
|||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "promotion-nominations".
|
||||
*/
|
||||
export interface PromotionNomination {
|
||||
id: number;
|
||||
/**
|
||||
* Member being nominated for promotion.
|
||||
*/
|
||||
nominee: number | User;
|
||||
/**
|
||||
* Member submitting the nomination (self for self-requests).
|
||||
*/
|
||||
nominator: number | User;
|
||||
/**
|
||||
* Written examples of performance, accolades, and reasons this member deserves promotion.
|
||||
*/
|
||||
accolades: string;
|
||||
status: 'pending' | 'awaiting_superuser' | 'approved' | 'rejected' | 'cancelled';
|
||||
/**
|
||||
* Decision of the nominee's division leader.
|
||||
*/
|
||||
leaderDecision?: ('pending' | 'endorsed' | 'rejected' | 'not_required') | null;
|
||||
leaderDecisionBy?: (number | null) | User;
|
||||
leaderDecidedAt?: string | null;
|
||||
/**
|
||||
* Note from the division leader's endorsement or rejection.
|
||||
*/
|
||||
leaderNote?: string | null;
|
||||
/**
|
||||
* Final reviewer feedback shown to the nominator.
|
||||
*/
|
||||
reviewNote?: string | null;
|
||||
reviewedBy?: (number | null) | User;
|
||||
reviewedAt?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "leadership-transfers".
|
||||
*/
|
||||
export interface LeadershipTransfer {
|
||||
id: number;
|
||||
/**
|
||||
* Division leader requesting the removal.
|
||||
*/
|
||||
initiator: number | User;
|
||||
/**
|
||||
* Member being transferred.
|
||||
*/
|
||||
subject: number | User;
|
||||
/**
|
||||
* Division the member is removed from.
|
||||
*/
|
||||
fromAssignment: number | Assignment;
|
||||
/**
|
||||
* Division the member is transferred to (the Infantry assignment).
|
||||
*/
|
||||
toAssignment: number | Assignment;
|
||||
/**
|
||||
* Optional reason for the removal, visible to command.
|
||||
*/
|
||||
reason?: string | null;
|
||||
status: 'pending' | 'approved' | 'denied' | 'cancelled';
|
||||
/**
|
||||
* Reviewer note recorded with the decision.
|
||||
*/
|
||||
reviewNote?: string | null;
|
||||
reviewedBy?: (number | null) | User;
|
||||
resolvedAt?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "mission-attendances".
|
||||
|
|
@ -5239,7 +5323,7 @@ export interface PluginAiInstruction {
|
|||
*/
|
||||
'field-type'?: ('text' | 'textarea' | 'upload' | 'richText') | null;
|
||||
'relation-to'?: string | null;
|
||||
'model-id'?: 'unsloth/gemma-4-26B-A4B-it-qat-GGUF' | null;
|
||||
'model-id'?: 'unsloth/Ornith-1.0-9B-GGUF' | null;
|
||||
/**
|
||||
* Please reload your collection after applying the changes
|
||||
*/
|
||||
|
|
@ -5259,7 +5343,7 @@ export interface PluginAiInstruction {
|
|||
| null;
|
||||
system?: string | null;
|
||||
layout?: string | null;
|
||||
'gemma-4-settings'?: {
|
||||
'ornith-9b-settings'?: {
|
||||
model?: string | null;
|
||||
};
|
||||
updatedAt: string;
|
||||
|
|
@ -5663,6 +5747,42 @@ export interface PayloadMcpApiKey {
|
|||
*/
|
||||
delete?: boolean | null;
|
||||
};
|
||||
promotionNominations?: {
|
||||
/**
|
||||
* Allow clients to find promotion-nominations.
|
||||
*/
|
||||
find?: boolean | null;
|
||||
/**
|
||||
* Allow clients to create promotion-nominations.
|
||||
*/
|
||||
create?: boolean | null;
|
||||
/**
|
||||
* Allow clients to update promotion-nominations.
|
||||
*/
|
||||
update?: boolean | null;
|
||||
/**
|
||||
* Allow clients to delete promotion-nominations.
|
||||
*/
|
||||
delete?: boolean | null;
|
||||
};
|
||||
leadershipTransfers?: {
|
||||
/**
|
||||
* Allow clients to find leadership-transfers.
|
||||
*/
|
||||
find?: boolean | null;
|
||||
/**
|
||||
* Allow clients to create leadership-transfers.
|
||||
*/
|
||||
create?: boolean | null;
|
||||
/**
|
||||
* Allow clients to update leadership-transfers.
|
||||
*/
|
||||
update?: boolean | null;
|
||||
/**
|
||||
* Allow clients to delete leadership-transfers.
|
||||
*/
|
||||
delete?: boolean | null;
|
||||
};
|
||||
missions?: {
|
||||
/**
|
||||
* Allow clients to find missions.
|
||||
|
|
@ -6768,6 +6888,14 @@ export interface PayloadLockedDocument {
|
|||
relationTo: 'ribbon-submissions';
|
||||
value: number | RibbonSubmission;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'promotion-nominations';
|
||||
value: number | PromotionNomination;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'leadership-transfers';
|
||||
value: number | LeadershipTransfer;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'missions';
|
||||
value: number | Mission;
|
||||
|
|
@ -7696,6 +7824,42 @@ export interface RibbonSubmissionsSelect<T extends boolean = true> {
|
|||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "promotion-nominations_select".
|
||||
*/
|
||||
export interface PromotionNominationsSelect<T extends boolean = true> {
|
||||
nominee?: T;
|
||||
nominator?: T;
|
||||
accolades?: T;
|
||||
status?: T;
|
||||
leaderDecision?: T;
|
||||
leaderDecisionBy?: T;
|
||||
leaderDecidedAt?: T;
|
||||
leaderNote?: T;
|
||||
reviewNote?: T;
|
||||
reviewedBy?: T;
|
||||
reviewedAt?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "leadership-transfers_select".
|
||||
*/
|
||||
export interface LeadershipTransfersSelect<T extends boolean = true> {
|
||||
initiator?: T;
|
||||
subject?: T;
|
||||
fromAssignment?: T;
|
||||
toAssignment?: T;
|
||||
reason?: T;
|
||||
status?: T;
|
||||
reviewNote?: T;
|
||||
reviewedBy?: T;
|
||||
resolvedAt?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "missions_select".
|
||||
|
|
@ -9360,7 +9524,7 @@ export interface PluginAiInstructionsSelect<T extends boolean = true> {
|
|||
};
|
||||
system?: T;
|
||||
layout?: T;
|
||||
'gemma-4-settings'?:
|
||||
'ornith-9b-settings'?:
|
||||
| T
|
||||
| {
|
||||
model?: T;
|
||||
|
|
@ -9544,6 +9708,22 @@ export interface PayloadMcpApiKeysSelect<T extends boolean = true> {
|
|||
update?: T;
|
||||
delete?: T;
|
||||
};
|
||||
promotionNominations?:
|
||||
| T
|
||||
| {
|
||||
find?: T;
|
||||
create?: T;
|
||||
update?: T;
|
||||
delete?: T;
|
||||
};
|
||||
leadershipTransfers?:
|
||||
| T
|
||||
| {
|
||||
find?: T;
|
||||
create?: T;
|
||||
update?: T;
|
||||
delete?: T;
|
||||
};
|
||||
missions?:
|
||||
| T
|
||||
| {
|
||||
|
|
@ -10068,6 +10248,10 @@ export interface GameRule {
|
|||
* Assignment(s) considered the intelligence division. Members and leaders of these assignments get elevated access to draft missions and intelligence content.
|
||||
*/
|
||||
intelAssignments?: (number | Assignment)[] | null;
|
||||
/**
|
||||
* Assignment that members are moved to when a division leader removes them from their division (the default destination for leadership-initiated transfers).
|
||||
*/
|
||||
infantryAssignment?: (number | null) | Assignment;
|
||||
/**
|
||||
* Distance threshold in real meters for instant transfers. Structures within this distance can transfer resources instantly. Beyond this, shipments are required.
|
||||
*/
|
||||
|
|
@ -10212,6 +10396,7 @@ export interface GameRulesSelect<T extends boolean = true> {
|
|||
currencyDenomination?: T;
|
||||
commandAssignments?: T;
|
||||
intelAssignments?: T;
|
||||
infantryAssignment?: T;
|
||||
proximityThreshold?: T;
|
||||
gameTickIntervalMinutes?: T;
|
||||
lockerGridWidth?: T;
|
||||
|
|
|
|||
Loading…
Reference in a new issue