import { Querier } from '@platform-modules/db';
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';

type Actor = {
    id: string;
    canManageMenus?: boolean;
};
declare function assertCanManageMenus(actor: Actor): void;

declare class MenuAuthorizationError extends Error {
    readonly actorId: string;
    readonly action: string;
    readonly _tag: "MenuAuthorizationError";
    readonly name = "MenuAuthorizationError";
    constructor(actorId: string, action: string);
}
declare class MenuNotFoundError extends Error {
    readonly kind: 'menu' | 'item';
    readonly id: string;
    readonly _tag: "MenuNotFoundError";
    readonly name = "MenuNotFoundError";
    constructor(kind: 'menu' | 'item', id: string);
}
declare class MenuValidationError extends Error {
    readonly field: string;
    readonly detail: string;
    readonly _tag: "MenuValidationError";
    readonly name = "MenuValidationError";
    constructor(field: string, detail: string);
}
declare class MenuDepthExceededError extends Error {
    readonly maxDepth: number;
    readonly _tag: "MenuDepthExceededError";
    readonly name = "MenuDepthExceededError";
    constructor(maxDepth: number);
}
declare class MenuLimitExceededError extends Error {
    readonly maxItems: number;
    readonly _tag: "MenuLimitExceededError";
    readonly name = "MenuLimitExceededError";
    constructor(maxItems: number);
}
declare class MenuCycleError extends Error {
    readonly itemId: string;
    readonly _tag: "MenuCycleError";
    readonly name = "MenuCycleError";
    constructor(itemId: string);
}
declare class MenuUrlSchemeError extends Error {
    readonly url: string;
    readonly _tag: "MenuUrlSchemeError";
    readonly name = "MenuUrlSchemeError";
    constructor(url: string);
}
declare const isMenuAuthorizationError: (e: unknown) => e is MenuAuthorizationError;
declare const isMenuNotFoundError: (e: unknown) => e is MenuNotFoundError;
declare const isMenuValidationError: (e: unknown) => e is MenuValidationError;
declare const isMenuDepthExceededError: (e: unknown) => e is MenuDepthExceededError;
declare const isMenuLimitExceededError: (e: unknown) => e is MenuLimitExceededError;
declare const isMenuCycleError: (e: unknown) => e is MenuCycleError;
declare const isMenuUrlSchemeError: (e: unknown) => e is MenuUrlSchemeError;

declare const MAX_MENU_DEPTH = 5;
declare const MAX_ITEMS_PER_MENU = 200;

type MenuTarget = {
    kind: 'url';
    url: string;
    openInNew?: boolean;
} | {
    kind: 'entity';
    entityType: string;
    entityId: string;
    openInNew?: boolean;
};
type MenuRow = {
    id: string;
    key: string;
    label: string;
    createdAtMs: number;
    updatedAtMs: number;
};
type MenuItemRow = {
    id: string;
    menuId: string;
    parentId: string | null;
    position: number;
    depth: number;
    label: string;
    targetKind: 'url' | 'entity';
    url: string | null;
    targetEntityType: string | null;
    targetEntityId: string | null;
    openInNew: boolean;
    createdAtMs: number;
    updatedAtMs: number;
};
type MenuItemNode = MenuItemRow & {
    children: MenuItemNode[];
};

declare const MENU_KEY_RE: RegExp;
declare const menus: drizzle_orm_pg_core.PgTableWithColumns<{
    name: "menus";
    schema: undefined;
    columns: {
        id: drizzle_orm_pg_core.PgColumn<{
            name: "id";
            tableName: "menus";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: true;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        key: drizzle_orm_pg_core.PgColumn<{
            name: "key";
            tableName: "menus";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        label: drizzle_orm_pg_core.PgColumn<{
            name: "label";
            tableName: "menus";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        createdAtMs: drizzle_orm_pg_core.PgColumn<{
            name: "created_at_ms";
            tableName: "menus";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        updatedAtMs: drizzle_orm_pg_core.PgColumn<{
            name: "updated_at_ms";
            tableName: "menus";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
    };
    dialect: "pg";
}>;
declare const menuItems: drizzle_orm_pg_core.PgTableWithColumns<{
    name: "menu_items";
    schema: undefined;
    columns: {
        id: drizzle_orm_pg_core.PgColumn<{
            name: "id";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: true;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        menuId: drizzle_orm_pg_core.PgColumn<{
            name: "menu_id";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        parentId: drizzle_orm_pg_core.PgColumn<{
            name: "parent_id";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        position: drizzle_orm_pg_core.PgColumn<{
            name: "position";
            tableName: "menu_items";
            dataType: "number";
            columnType: "PgInteger";
            data: number;
            driverParam: string | number;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        depth: drizzle_orm_pg_core.PgColumn<{
            name: "depth";
            tableName: "menu_items";
            dataType: "number";
            columnType: "PgInteger";
            data: number;
            driverParam: string | number;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        label: drizzle_orm_pg_core.PgColumn<{
            name: "label";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        targetKind: drizzle_orm_pg_core.PgColumn<{
            name: "target_kind";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        url: drizzle_orm_pg_core.PgColumn<{
            name: "url";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        targetEntityType: drizzle_orm_pg_core.PgColumn<{
            name: "target_entity_type";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        targetEntityId: drizzle_orm_pg_core.PgColumn<{
            name: "target_entity_id";
            tableName: "menu_items";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        openInNew: drizzle_orm_pg_core.PgColumn<{
            name: "open_in_new";
            tableName: "menu_items";
            dataType: "boolean";
            columnType: "PgBoolean";
            data: boolean;
            driverParam: boolean;
            notNull: true;
            hasDefault: true;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        createdAtMs: drizzle_orm_pg_core.PgColumn<{
            name: "created_at_ms";
            tableName: "menu_items";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        updatedAtMs: drizzle_orm_pg_core.PgColumn<{
            name: "updated_at_ms";
            tableName: "menu_items";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
    };
    dialect: "pg";
}>;
declare const menusSchema: {
    menus: drizzle_orm_pg_core.PgTableWithColumns<{
        name: "menus";
        schema: undefined;
        columns: {
            id: drizzle_orm_pg_core.PgColumn<{
                name: "id";
                tableName: "menus";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: true;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            key: drizzle_orm_pg_core.PgColumn<{
                name: "key";
                tableName: "menus";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            label: drizzle_orm_pg_core.PgColumn<{
                name: "label";
                tableName: "menus";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            createdAtMs: drizzle_orm_pg_core.PgColumn<{
                name: "created_at_ms";
                tableName: "menus";
                dataType: "number";
                columnType: "PgBigInt53";
                data: number;
                driverParam: string | number;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            updatedAtMs: drizzle_orm_pg_core.PgColumn<{
                name: "updated_at_ms";
                tableName: "menus";
                dataType: "number";
                columnType: "PgBigInt53";
                data: number;
                driverParam: string | number;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
        };
        dialect: "pg";
    }>;
    menuItems: drizzle_orm_pg_core.PgTableWithColumns<{
        name: "menu_items";
        schema: undefined;
        columns: {
            id: drizzle_orm_pg_core.PgColumn<{
                name: "id";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: true;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            menuId: drizzle_orm_pg_core.PgColumn<{
                name: "menu_id";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            parentId: drizzle_orm_pg_core.PgColumn<{
                name: "parent_id";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: false;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            position: drizzle_orm_pg_core.PgColumn<{
                name: "position";
                tableName: "menu_items";
                dataType: "number";
                columnType: "PgInteger";
                data: number;
                driverParam: string | number;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            depth: drizzle_orm_pg_core.PgColumn<{
                name: "depth";
                tableName: "menu_items";
                dataType: "number";
                columnType: "PgInteger";
                data: number;
                driverParam: string | number;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            label: drizzle_orm_pg_core.PgColumn<{
                name: "label";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            targetKind: drizzle_orm_pg_core.PgColumn<{
                name: "target_kind";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            url: drizzle_orm_pg_core.PgColumn<{
                name: "url";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: false;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            targetEntityType: drizzle_orm_pg_core.PgColumn<{
                name: "target_entity_type";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: false;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            targetEntityId: drizzle_orm_pg_core.PgColumn<{
                name: "target_entity_id";
                tableName: "menu_items";
                dataType: "string";
                columnType: "PgText";
                data: string;
                driverParam: string;
                notNull: false;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: [string, ...string[]];
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            openInNew: drizzle_orm_pg_core.PgColumn<{
                name: "open_in_new";
                tableName: "menu_items";
                dataType: "boolean";
                columnType: "PgBoolean";
                data: boolean;
                driverParam: boolean;
                notNull: true;
                hasDefault: true;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            createdAtMs: drizzle_orm_pg_core.PgColumn<{
                name: "created_at_ms";
                tableName: "menu_items";
                dataType: "number";
                columnType: "PgBigInt53";
                data: number;
                driverParam: string | number;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
            updatedAtMs: drizzle_orm_pg_core.PgColumn<{
                name: "updated_at_ms";
                tableName: "menu_items";
                dataType: "number";
                columnType: "PgBigInt53";
                data: number;
                driverParam: string | number;
                notNull: true;
                hasDefault: false;
                isPrimaryKey: false;
                isAutoincrement: false;
                hasRuntimeDefault: false;
                enumValues: undefined;
                baseColumn: never;
                identity: undefined;
                generated: undefined;
            }, {}, {}>;
        };
        dialect: "pg";
    }>;
};
type MenusSchema = typeof menusSchema;
/** Idempotent additive DDL for menus tables. */
declare const menusMigrationSql: () => string;

/**
 * Menu metadata plus nested item nodes returned by {@link getMenuTree}.
 *
 * @remarks Entity targets in `items` are unresolved and not visibility-filtered;
 * the caller MUST resolve each entity target through its own visibility/authorization
 * filter at render time and drop anything not publicly visible before end-user exposure —
 * see {@link getMenuTree}.
 */
type MenuTree = {
    menu: MenuRow;
    items: MenuItemNode[];
};
declare function listMenus(db: Querier<MenusSchema>): Promise<MenuRow[]>;
/**
 * Load a menu and its item tree by stable key. Returns null when the key is missing.
 *
 * Returns UNRESOLVED opaque targets exactly as stored — entity targets are NOT
 * visibility-filtered; this core never resolves entity ids and cannot know whether
 * a target points at a draft, private, or trashed entity. The caller MUST resolve
 * each entity target through its own visibility/authorization filter at render time
 * and drop anything not publicly visible before exposing the tree to an end user.
 */
declare function getMenuTree(db: Querier<MenusSchema>, key: string): Promise<MenuTree | null>;

declare function createMenu(db: Querier<MenusSchema>, actor: Actor, input: {
    key: string;
    label: string;
}): Promise<MenuRow>;
declare function updateMenu(db: Querier<MenusSchema>, actor: Actor, menuId: string, patch: {
    label?: string;
}): Promise<MenuRow>;
declare function deleteMenu(db: Querier<MenusSchema>, actor: Actor, menuId: string): Promise<void>;

declare function addMenuItem(db: Querier<MenusSchema>, actor: Actor, menuId: string, input: {
    parentId?: string;
    label: string;
    target: MenuTarget;
}): Promise<MenuItemRow>;
declare function updateMenuItem(db: Querier<MenusSchema>, actor: Actor, itemId: string, patch: {
    label?: string;
    target?: MenuTarget;
    openInNew?: boolean;
}): Promise<MenuItemRow>;
declare function removeMenuItem(db: Querier<MenusSchema>, actor: Actor, itemId: string): Promise<void>;
declare function moveMenuItem(db: Querier<MenusSchema>, actor: Actor, itemId: string, input: {
    newParentId: string | null;
    newPosition: number;
}): Promise<MenuItemRow>;
declare function reorderMenuItems(db: Querier<MenusSchema>, actor: Actor, menuId: string, parentId: string | null, orderedIds: string[]): Promise<void>;

/**
 * Accept http/https/mailto/path-relative URLs; reject dangerous schemes before any write.
 * Path-relative means a single leading `/` NOT followed by `/` or `\`: protocol-relative
 * `//host` and backslash-authority `/\host` both resolve cross-host in browsers (WHATWG
 * slash-normalization for special schemes) and are rejected as open-redirect/phishing vectors.
 * The host should re-use this guard at render, never re-author it.
 */
declare function assertAllowedMenuUrl(url: string): string;

export { type Actor, MAX_ITEMS_PER_MENU, MAX_MENU_DEPTH, MENU_KEY_RE, MenuAuthorizationError, MenuCycleError, MenuDepthExceededError, type MenuItemNode, type MenuItemRow, MenuLimitExceededError, MenuNotFoundError, type MenuRow, type MenuTarget, type MenuTree, MenuUrlSchemeError, MenuValidationError, type MenusSchema, addMenuItem, assertAllowedMenuUrl, assertCanManageMenus, createMenu, deleteMenu, getMenuTree, isMenuAuthorizationError, isMenuCycleError, isMenuDepthExceededError, isMenuLimitExceededError, isMenuNotFoundError, isMenuUrlSchemeError, isMenuValidationError, listMenus, menuItems, menus, menusMigrationSql, menusSchema, moveMenuItem, removeMenuItem, reorderMenuItems, updateMenu, updateMenuItem };
