import type { ColorHarmony } from '@ankhorage/color-theory'; import type { SplashScreenSpec } from './appManifest/splashScreen'; import type { AuthIdentifierKind, AuthSignUpField } from './auth'; import type { BindingValueSource, ComponentDataBindingRegistry, ScreenDataLoaderDefinition, } from './bindings'; import type { EntityRegistry } from './collections'; import type { DataSourceRegistry } from './data'; import type { AppDeployManifest } from './deploy'; import type { InfraManifest } from './infra'; import type { MediaAssetReference, MediaManifest } from './media'; import type { AppNavigatorManifest } from './navigator'; import type { RepositoryManifest } from './repository'; import type { ScreenRequirements } from './requirements'; import type { SerializableValue } from './serializable'; import type { AppStateSpec } from './state'; import type { ThemeGlobalTokenOverrides, ThemeRecipeOverrides } from './theme'; export interface ThemeModeConfig { primaryColor: string; harmony: ColorHarmony; } export type ThemeId = string; export interface ThemeConfig { id: ThemeId; name: string; light: ThemeModeConfig; dark: ThemeModeConfig; /** Theme-global authored token overrides shared by light and dark mode. */ tokens?: ThemeGlobalTokenOverrides; /** Component/pattern recipe override values; recipe schemas remain package-owned metadata. */ recipes?: ThemeRecipeOverrides; } export type ThemeRegistry = EntityRegistry; export type ActionType = 'navigate' | 'alert' | 'console' | 'toggleDarkMode' | 'setLanguage' | 'search' | 'filter'; export interface NavigateAction { type: 'navigate'; payload: { route: string; params?: Record; }; } export interface AlertAction { type: 'alert'; payload?: { message?: string; }; } export interface ConsoleAction { type: 'console'; payload?: Record; } export interface ToggleDarkModeAction { type: 'toggleDarkMode'; payload?: never; } export interface SetLanguageAction { type: 'setLanguage'; payload: { locale: string; }; } export interface SearchAction { type: 'search'; payload: { query: string; scope?: string; }; } export interface FilterAction { type: 'filter'; payload: { filterKey: string; filterValue: string; }; } export type Action = | AlertAction | ConsoleAction | FilterAction | NavigateAction | SearchAction | SetLanguageAction | ToggleDarkModeAction; export type ManifestValue = SerializableValue; export type ComponentEventPayloadValue = ManifestValue; export interface ComponentEventDto< TType extends string = string, TPayload extends object = Record, > { readonly type: TType; readonly sourceNodeId: string; readonly payload: TPayload; } export type FormSubmitValues = Record; export type FormSubmitEventDto = ComponentEventDto< 'form.submit', { readonly values: FormSubmitValues; } >; export type ButtonPressEventDto = ComponentEventDto<'button.press', Record>; export interface CollectionItemPressPayload { readonly itemId: string | number; readonly item: Record; } export type CollectionItemPressEventDto = ComponentEventDto< 'collection.itemPress', CollectionItemPressPayload >; export type ComponentEventDtoKind = ButtonPressEventDto['type'] | CollectionItemPressEventDto['type'] | FormSubmitEventDto['type']; export type KnownComponentEventDto = ButtonPressEventDto | CollectionItemPressEventDto | FormSubmitEventDto; export const APP_CATEGORIES = [ 'books_reading', 'business_productivity', 'developer_tools', 'education_learning', 'entertainment_media', 'finance_money', 'food_drink', 'games', 'graphics_design', 'health_fitness', 'kids_family', 'lifestyle', 'medical', 'music_audio', 'navigation_travel', 'news_magazines', 'photo_video', 'reference', 'shopping_commerce', 'social_community', 'sports', 'utilities_tools', 'weather', ] as const; export type AppCategory = (typeof APP_CATEGORIES)[number]; export const AUTH_SCOPES = ['global', 'none', 'integrated'] as const; export type AuthScope = (typeof AUTH_SCOPES)[number]; export const AUTH_SIGN_IN_IDENTIFIERS = ['email', 'username', 'phone'] as const; export type AuthSignInIdentifier = AuthIdentifierKind; export const AUTH_SIGN_UP_POLICIES = ['autoSignIn', 'requireVerification'] as const; export type AuthSignUpPolicy = (typeof AUTH_SIGN_UP_POLICIES)[number]; export const AUTH_PROFILE_FIELDS = [ ...AUTH_SIGN_IN_IDENTIFIERS, 'firstName', 'lastName', 'displayName', 'avatarUrl', ] as const; export type KnownAuthProfileField = (typeof AUTH_PROFILE_FIELDS)[number]; export type AuthProfileField = KnownAuthProfileField | (string & {}); export const AUTH_PROFILE_PRIMARY_KEY_STRATEGIES = ['authUserId'] as const; export type AuthProfilePrimaryKeyStrategy = (typeof AUTH_PROFILE_PRIMARY_KEY_STRATEGIES)[number]; export const AUTH_PROFILE_CREATE_STRATEGIES = ['trigger', 'api', 'app'] as const; export type AuthProfileCreateStrategy = (typeof AUTH_PROFILE_CREATE_STRATEGIES)[number]; export const AUTH_PROFILE_UPDATE_STRATEGIES = ['api', 'app'] as const; export type AuthProfileUpdateStrategy = (typeof AUTH_PROFILE_UPDATE_STRATEGIES)[number]; interface IconPresentationSpec { size?: number | string; color?: string; } export interface NamedIconSpec extends IconPresentationSpec { name: string; provider?: string; source?: never; } export interface SvgIconSpec extends IconPresentationSpec { source: MediaAssetReference; name?: never; provider?: never; } export type IconSpec = NamedIconSpec | SvgIconSpec; export interface UiNodeRepeatSpec { source: BindingValueSource; itemAlias?: string; keyPath?: string; empty?: readonly UiNode[]; } export interface UiNode { id: string; type: string; alias?: string; props?: Record; children?: UiNode[]; style?: Record; repeat?: UiNodeRepeatSpec; } export interface ScreenMetadataSpec { id: string; name: string; title?: string; description?: string; } export interface ScreenSpec extends ScreenMetadataSpec { root: UiNode; dataLoaders?: readonly ScreenDataLoaderDefinition[]; requires?: ScreenRequirements; } export interface AuthSignInSpec { identifiers: AuthSignInIdentifier[]; } export interface AuthSignUpSpec { requiredFields: AuthSignUpField[]; optionalFields?: AuthSignUpField[]; signUpPolicy?: AuthSignUpPolicy; } export interface AuthProfileSpec { fields: AuthProfileField[]; table?: string; primaryKey?: AuthProfilePrimaryKeyStrategy; createStrategy?: AuthProfileCreateStrategy; updateStrategy?: AuthProfileUpdateStrategy; } export interface AppSettings { localization: { defaultLocale: string; locales: string[]; }; } export interface AppManifest { metadata: { name: string; slug: string; version: string; category: AppCategory; themeId: ThemeId; created?: string; updated?: string; }; themes: ThemeRegistry; activeThemeId: ThemeId; activeThemeMode?: 'dark' | 'light'; splashScreen?: SplashScreenSpec; /** Studio-managed authoring media. Runtime/user uploads are intentionally separate. */ media?: MediaManifest; /** App distribution desired state, separate from environment-specific infrastructure. */ deploy?: AppDeployManifest; /** Application runtime state is not provisioned by Infra. */ state?: AppStateSpec; infra: InfraManifest; navigator: AppNavigatorManifest; screens: EntityRegistry; dataSources?: DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; repository?: RepositoryManifest; settings: AppSettings; }