@hexclave/tanstack-start 1.0.24 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/components/elements/sidebar-layout.js +1 -1
  2. package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
  3. package/dist/dev-tool/dev-tool-core.js +3 -67
  4. package/dist/dev-tool/dev-tool-core.js.map +1 -1
  5. package/dist/esm/components/elements/sidebar-layout.js +1 -1
  6. package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
  7. package/dist/esm/dev-tool/dev-tool-core.js +3 -67
  8. package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
  9. package/dist/esm/generated/quetzal-translations.d.ts +2 -2
  10. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  11. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js +2 -0
  12. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  13. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  14. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +9 -3
  15. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  16. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +1 -1
  17. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -1
  18. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js +2 -1
  19. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -1
  20. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js +26 -0
  21. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -1
  22. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.d.ts +7 -1
  23. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.d.ts.map +1 -1
  24. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.js +11 -1
  25. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.js.map +1 -1
  26. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.test.js +43 -0
  27. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.test.js.map +1 -1
  28. package/dist/esm/lib/hexclave-app/projects/index.d.ts +6 -0
  29. package/dist/esm/lib/hexclave-app/projects/index.d.ts.map +1 -1
  30. package/dist/esm/lib/hexclave-app/projects/index.js.map +1 -1
  31. package/dist/esm/pushed-config-error-overlay/index.d.ts +7 -0
  32. package/dist/esm/pushed-config-error-overlay/index.d.ts.map +1 -0
  33. package/dist/esm/pushed-config-error-overlay/index.js +464 -0
  34. package/dist/esm/pushed-config-error-overlay/index.js.map +1 -0
  35. package/dist/generated/quetzal-translations.d.ts +2 -2
  36. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  37. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js +2 -0
  38. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  39. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  40. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +9 -3
  41. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  42. package/dist/lib/hexclave-app/apps/implementations/common.js +1 -1
  43. package/dist/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -1
  44. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js +1 -0
  45. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -1
  46. package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js +26 -0
  47. package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -1
  48. package/dist/lib/hexclave-app/apps/implementations/session-replay.d.ts +7 -1
  49. package/dist/lib/hexclave-app/apps/implementations/session-replay.d.ts.map +1 -1
  50. package/dist/lib/hexclave-app/apps/implementations/session-replay.js +11 -0
  51. package/dist/lib/hexclave-app/apps/implementations/session-replay.js.map +1 -1
  52. package/dist/lib/hexclave-app/apps/implementations/session-replay.test.js +43 -0
  53. package/dist/lib/hexclave-app/apps/implementations/session-replay.test.js.map +1 -1
  54. package/dist/lib/hexclave-app/projects/index.d.ts +6 -0
  55. package/dist/lib/hexclave-app/projects/index.d.ts.map +1 -1
  56. package/dist/lib/hexclave-app/projects/index.js.map +1 -1
  57. package/dist/pushed-config-error-overlay/index.d.ts +7 -0
  58. package/dist/pushed-config-error-overlay/index.d.ts.map +1 -0
  59. package/dist/pushed-config-error-overlay/index.js +466 -0
  60. package/dist/pushed-config-error-overlay/index.js.map +1 -0
  61. package/package.json +3 -3
  62. package/src/dev-tool/dev-tool-core.ts +4 -58
  63. package/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +6 -0
  64. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +11 -3
  65. package/src/lib/hexclave-app/apps/implementations/event-tracker.test.ts +33 -0
  66. package/src/lib/hexclave-app/apps/implementations/event-tracker.ts +6 -1
  67. package/src/lib/hexclave-app/apps/implementations/session-replay.test.ts +52 -0
  68. package/src/lib/hexclave-app/apps/implementations/session-replay.ts +20 -0
  69. package/src/lib/hexclave-app/projects/index.ts +2 -0
  70. package/src/pushed-config-error-overlay/index.ts +548 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/hexclave-app/projects/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { ProductionModeError } from \"@hexclave/shared/dist/helpers/production-mode\";\nimport { AdminUserProjectsCrud, ProjectsCrud } from \"@hexclave/shared/dist/interface/crud/projects\";\nimport { ProjectOnboardingStatus } from \"@hexclave/shared/dist/schema-fields\";\n\nimport { CompleteConfig, EnvironmentConfigNormalizedOverride, EnvironmentConfigOverrideOverride } from \"@hexclave/shared/dist/config/schema\";\nimport { StackAdminApp } from \"../apps/interfaces/admin-app\";\nimport { AdminProjectConfig, AdminProjectConfigUpdateOptions, ProjectConfig } from \"../project-configs\";\n\n/**\n * SDK type for pushed config source (camelCase for SDK).\n * Represents where the branch config was pushed from.\n */\nexport type PushedConfigSource =\n | { type: \"pushed-from-github\", owner: string, repo: string, branch: string, commitHash: string, configFilePath: string, workflowPath?: string }\n | { type: \"pushed-from-unknown\" }\n | { type: \"unlinked\" };\n\nexport type PushConfigOptions = {\n /**\n * The source of this config push.\n */\n source: PushedConfigSource,\n};\n\n\nexport type Project = {\n readonly id: string,\n readonly displayName: string,\n readonly config: ProjectConfig,\n};\n\nexport type AdminProject = {\n readonly id: string,\n readonly displayName: string,\n readonly description: string | null,\n readonly createdAt: Date,\n readonly isProductionMode: boolean,\n readonly isDevelopmentEnvironment: boolean,\n readonly ownerTeamId: string | null,\n readonly onboardingStatus: ProjectOnboardingStatus,\n readonly logoUrl: string | null | undefined,\n readonly logoFullUrl: string | null | undefined,\n readonly logoDarkModeUrl: string | null | undefined,\n readonly logoFullDarkModeUrl: string | null | undefined,\n\n readonly config: AdminProjectConfig,\n\n update(this: AdminProject, update: AdminProjectUpdateOptions): Promise<void>,\n delete(this: AdminProject): Promise<void>,\n\n getConfig(this: AdminProject): Promise<CompleteConfig>,\n useConfig(this: AdminProject): CompleteConfig,\n\n /**\n * Updates the environment's config by merging the provided config into the existing config.\n *\n * Changes made with `updateConfig` always take precedence over those made with `pushConfig`, even if the `pushConfig`\n * config was pushed after the changes were made with `updateConfig`. This is best for environment-specific\n * configuration like secrets, API keys, and other values that you wouldn't push into a source repository.\n */\n // We have some strict types here in order to prevent accidental overwriting of a top-level property of a config object\n updateConfig(\n this: AdminProject,\n config: EnvironmentConfigOverrideOverride,\n ): Promise<void>,\n\n /**\n * Pushes a config, replacing any previous config pushed with `pushConfig`.\n *\n * **Note:** This function does **not** replace any changes made with `updateConfig`. Changes made with\n * `updateConfig` always take precedence over those made with `pushConfig`, even if the `pushConfig`\n * config was pushed after the changes were made with `updateConfig`.\n *\n * This is useful for programmatically deploying configuration. More often than not, you'll want to use\n * `updateConfig` instead.\n */\n pushConfig(\n this: AdminProject,\n config: EnvironmentConfigOverrideOverride,\n options: PushConfigOptions,\n ): Promise<void>,\n\n /**\n * Updates the pushed config by merging the provided config into the existing pushed config.\n *\n * **Warning:** This is almost always **not** the function you want to call. Changes made with\n * `updatePushedConfig` will be replaced entirely the next time `pushConfig` is called. Consider using\n * `pushConfig` to set the full pushed config, or `updateConfig` for environment-specific values that\n * should persist across pushes.\n *\n * This function is useful for making temporary modifications to the pushed config before the next push.\n */\n updatePushedConfig(\n this: AdminProject,\n config: EnvironmentConfigOverrideOverride\n ): Promise<void>,\n\n /**\n * Gets the source metadata for the pushed config, indicating where it was pushed from.\n *\n * The source can be:\n * - `pushed-from-github`: Config was pushed from a GitHub repository\n * - `pushed-from-unknown`: Config was pushed via CLI but source details unknown\n * - `unlinked`: Config can be edited directly on the dashboard\n */\n getPushedConfigSource(this: AdminProject): Promise<PushedConfigSource>,\n\n /**\n * Unlinks the pushed config source, setting it to \"unlinked\".\n * This allows the config to be edited directly on the dashboard without external push restrictions.\n */\n unlinkPushedConfigSource(this: AdminProject): Promise<void>,\n\n /**\n * Resets (removes) specific keys from the config override at the specified level.\n * Uses the same nested key logic as the override algorithm: resetting key \"a.b\" also resets \"a.b.c\".\n *\n * This is useful when updating the pushed config (branch level) and wanting to remove the same keys\n * from the environment config override so that the branch config values take precedence.\n */\n resetConfigOverrideKeys(this: AdminProject, level: \"branch\" | \"environment\", keys: string[]): Promise<void>,\n\n /**\n * Gets the raw config override at the specified level (before merging/defaults).\n * Useful for inspecting exactly what's been set at each level.\n */\n getConfigOverride(this: AdminProject, level: \"branch\" | \"environment\"): Promise<Record<string, unknown>>,\n\n /**\n * Replaces the entire config override at the specified level.\n * For branch level, preserves the existing source metadata.\n */\n replaceConfigOverride(this: AdminProject, level: \"branch\" | \"environment\", config: Record<string, unknown>): Promise<void>,\n\n getProductionModeErrors(this: AdminProject): Promise<ProductionModeError[]>,\n useProductionModeErrors(this: AdminProject): ProductionModeError[],\n} & Project;\n\nexport type AdminOwnedProject = {\n readonly app: StackAdminApp<false>,\n} & AdminProject;\n\nexport type AdminProjectUpdateOptions = {\n displayName?: string,\n description?: string,\n isProductionMode?: boolean,\n onboardingStatus?: ProjectOnboardingStatus,\n /**\n * Updates `project.requirePublishableClientKey` in the project-level config override.\n */\n requirePublishableClientKey?: boolean,\n logoUrl?: string | null,\n logoFullUrl?: string | null,\n logoDarkModeUrl?: string | null,\n logoFullDarkModeUrl?: string | null,\n config?: AdminProjectConfigUpdateOptions,\n};\nexport function adminProjectUpdateOptionsToCrud(options: AdminProjectUpdateOptions): ProjectsCrud[\"Admin\"][\"Update\"] {\n return {\n display_name: options.displayName,\n description: options.description,\n is_production_mode: options.isProductionMode,\n onboarding_status: options.onboardingStatus,\n logo_url: options.logoUrl,\n logo_full_url: options.logoFullUrl,\n logo_dark_mode_url: options.logoDarkModeUrl,\n logo_full_dark_mode_url: options.logoFullDarkModeUrl,\n /**\n * NOTE: Do not update this config anymore. It's been superseded by the new config in schema.ts.\n * @deprecated\n */\n config: {\n domains: options.config?.domains?.map((d) => ({\n domain: d.domain,\n handler_path: d.handlerPath\n })),\n oauth_providers: options.config?.oauthProviders\n ?.filter((p): p is Exclude<typeof p, { type: 'custom_oidc' }> => p.type !== 'custom_oidc')\n .map((p) => ({\n id: p.id as any,\n type: p.type,\n ...(p.type === 'standard' && {\n client_id: p.clientId,\n client_secret: p.clientSecret,\n facebook_config_id: p.facebookConfigId,\n microsoft_tenant_id: p.microsoftTenantId,\n apple_bundle_ids: p.appleBundleIds,\n }),\n })),\n email_config: options.config?.emailConfig && (\n options.config.emailConfig.type === 'shared' ? {\n type: 'shared',\n } : {\n type: 'standard',\n host: options.config.emailConfig.host,\n port: options.config.emailConfig.port,\n username: options.config.emailConfig.username,\n password: options.config.emailConfig.password,\n sender_name: options.config.emailConfig.senderName,\n sender_email: options.config.emailConfig.senderEmail,\n }\n ),\n email_theme: options.config?.emailTheme,\n sign_up_enabled: options.config?.signUpEnabled,\n credential_enabled: options.config?.credentialEnabled,\n magic_link_enabled: options.config?.magicLinkEnabled,\n passkey_enabled: options.config?.passkeyEnabled,\n allow_localhost: options.config?.allowLocalhost,\n create_team_on_sign_up: options.config?.createTeamOnSignUp,\n client_team_creation_enabled: options.config?.clientTeamCreationEnabled,\n client_user_deletion_enabled: options.config?.clientUserDeletionEnabled,\n team_creator_default_permissions: options.config?.teamCreatorDefaultPermissions,\n team_member_default_permissions: options.config?.teamMemberDefaultPermissions,\n user_default_permissions: options.config?.userDefaultPermissions,\n oauth_account_merge_strategy: options.config?.oauthAccountMergeStrategy,\n allow_user_api_keys: options.config?.allowUserApiKeys,\n allow_team_api_keys: options.config?.allowTeamApiKeys,\n },\n };\n}\n\nexport type AdminProjectCreateOptions = Omit<AdminProjectUpdateOptions, 'displayName'> & {\n displayName: string,\n teamId: string,\n isDevelopmentEnvironment?: boolean,\n};\nexport function adminProjectCreateOptionsToCrud(options: AdminProjectCreateOptions): AdminUserProjectsCrud[\"Server\"][\"Create\"] {\n return {\n ...adminProjectUpdateOptionsToCrud(options),\n display_name: options.displayName,\n is_development_environment: options.isDevelopmentEnvironment,\n owner_team_id: options.teamId,\n };\n}\n"],"mappings":";AAiKA,SAAgB,gCAAgC,SAAqE;AACnH,QAAO;EACL,cAAc,QAAQ;EACtB,aAAa,QAAQ;EACrB,oBAAoB,QAAQ;EAC5B,mBAAmB,QAAQ;EAC3B,UAAU,QAAQ;EAClB,eAAe,QAAQ;EACvB,oBAAoB,QAAQ;EAC5B,yBAAyB,QAAQ;EAKjC,QAAQ;GACN,SAAS,QAAQ,QAAQ,SAAS,KAAK,OAAO;IAC5C,QAAQ,EAAE;IACV,cAAc,EAAE;IACjB,EAAE;GACH,iBAAiB,QAAQ,QAAQ,gBAC7B,QAAQ,MAAuD,EAAE,SAAS,cAAc,CACzF,KAAK,OAAO;IACX,IAAI,EAAE;IACN,MAAM,EAAE;IACR,GAAI,EAAE,SAAS,cAAc;KAC3B,WAAW,EAAE;KACb,eAAe,EAAE;KACjB,oBAAoB,EAAE;KACtB,qBAAqB,EAAE;KACvB,kBAAkB,EAAE;KACrB;IACF,EAAE;GACL,cAAc,QAAQ,QAAQ,gBAC5B,QAAQ,OAAO,YAAY,SAAS,WAAW,EAC7C,MAAM,UACP,GAAG;IACF,MAAM;IACN,MAAM,QAAQ,OAAO,YAAY;IACjC,MAAM,QAAQ,OAAO,YAAY;IACjC,UAAU,QAAQ,OAAO,YAAY;IACrC,UAAU,QAAQ,OAAO,YAAY;IACrC,aAAa,QAAQ,OAAO,YAAY;IACxC,cAAc,QAAQ,OAAO,YAAY;IAC1C;GAEH,aAAa,QAAQ,QAAQ;GAC7B,iBAAiB,QAAQ,QAAQ;GACjC,oBAAoB,QAAQ,QAAQ;GACpC,oBAAoB,QAAQ,QAAQ;GACpC,iBAAiB,QAAQ,QAAQ;GACjC,iBAAiB,QAAQ,QAAQ;GACjC,wBAAwB,QAAQ,QAAQ;GACxC,8BAA8B,QAAQ,QAAQ;GAC9C,8BAA8B,QAAQ,QAAQ;GAC9C,kCAAkC,QAAQ,QAAQ;GAClD,iCAAiC,QAAQ,QAAQ;GACjD,0BAA0B,QAAQ,QAAQ;GAC1C,8BAA8B,QAAQ,QAAQ;GAC9C,qBAAqB,QAAQ,QAAQ;GACrC,qBAAqB,QAAQ,QAAQ;GACtC;EACF;;AAQH,SAAgB,gCAAgC,SAA+E;AAC7H,QAAO;EACL,GAAG,gCAAgC,QAAQ;EAC3C,cAAc,QAAQ;EACtB,4BAA4B,QAAQ;EACpC,eAAe,QAAQ;EACxB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/hexclave-app/projects/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { ProductionModeError } from \"@hexclave/shared/dist/helpers/production-mode\";\nimport { AdminUserProjectsCrud, ProjectsCrud } from \"@hexclave/shared/dist/interface/crud/projects\";\nimport { ProjectOnboardingStatus } from \"@hexclave/shared/dist/schema-fields\";\n\nimport { CompleteConfig, EnvironmentConfigNormalizedOverride, EnvironmentConfigOverrideOverride } from \"@hexclave/shared/dist/config/schema\";\nimport { StackAdminApp } from \"../apps/interfaces/admin-app\";\nimport { AdminProjectConfig, AdminProjectConfigUpdateOptions, ProjectConfig } from \"../project-configs\";\n\n/**\n * SDK type for pushed config source (camelCase for SDK).\n * Represents where the branch config was pushed from.\n */\nexport type PushedConfigSource =\n | { type: \"pushed-from-github\", owner: string, repo: string, branch: string, commitHash: string, configFilePath: string, workflowPath?: string }\n | { type: \"pushed-from-unknown\" }\n | { type: \"unlinked\" };\n\nexport type PushConfigOptions = {\n /**\n * The source of this config push.\n */\n source: PushedConfigSource,\n};\n\n\nexport type Project = {\n readonly id: string,\n readonly displayName: string,\n readonly pushedConfigError: { message: string } | null,\n readonly configWarnings: { message: string }[],\n readonly config: ProjectConfig,\n};\n\nexport type AdminProject = {\n readonly id: string,\n readonly displayName: string,\n readonly description: string | null,\n readonly createdAt: Date,\n readonly isProductionMode: boolean,\n readonly isDevelopmentEnvironment: boolean,\n readonly ownerTeamId: string | null,\n readonly onboardingStatus: ProjectOnboardingStatus,\n readonly logoUrl: string | null | undefined,\n readonly logoFullUrl: string | null | undefined,\n readonly logoDarkModeUrl: string | null | undefined,\n readonly logoFullDarkModeUrl: string | null | undefined,\n\n readonly config: AdminProjectConfig,\n\n update(this: AdminProject, update: AdminProjectUpdateOptions): Promise<void>,\n delete(this: AdminProject): Promise<void>,\n\n getConfig(this: AdminProject): Promise<CompleteConfig>,\n useConfig(this: AdminProject): CompleteConfig,\n\n /**\n * Updates the environment's config by merging the provided config into the existing config.\n *\n * Changes made with `updateConfig` always take precedence over those made with `pushConfig`, even if the `pushConfig`\n * config was pushed after the changes were made with `updateConfig`. This is best for environment-specific\n * configuration like secrets, API keys, and other values that you wouldn't push into a source repository.\n */\n // We have some strict types here in order to prevent accidental overwriting of a top-level property of a config object\n updateConfig(\n this: AdminProject,\n config: EnvironmentConfigOverrideOverride,\n ): Promise<void>,\n\n /**\n * Pushes a config, replacing any previous config pushed with `pushConfig`.\n *\n * **Note:** This function does **not** replace any changes made with `updateConfig`. Changes made with\n * `updateConfig` always take precedence over those made with `pushConfig`, even if the `pushConfig`\n * config was pushed after the changes were made with `updateConfig`.\n *\n * This is useful for programmatically deploying configuration. More often than not, you'll want to use\n * `updateConfig` instead.\n */\n pushConfig(\n this: AdminProject,\n config: EnvironmentConfigOverrideOverride,\n options: PushConfigOptions,\n ): Promise<void>,\n\n /**\n * Updates the pushed config by merging the provided config into the existing pushed config.\n *\n * **Warning:** This is almost always **not** the function you want to call. Changes made with\n * `updatePushedConfig` will be replaced entirely the next time `pushConfig` is called. Consider using\n * `pushConfig` to set the full pushed config, or `updateConfig` for environment-specific values that\n * should persist across pushes.\n *\n * This function is useful for making temporary modifications to the pushed config before the next push.\n */\n updatePushedConfig(\n this: AdminProject,\n config: EnvironmentConfigOverrideOverride\n ): Promise<void>,\n\n /**\n * Gets the source metadata for the pushed config, indicating where it was pushed from.\n *\n * The source can be:\n * - `pushed-from-github`: Config was pushed from a GitHub repository\n * - `pushed-from-unknown`: Config was pushed via CLI but source details unknown\n * - `unlinked`: Config can be edited directly on the dashboard\n */\n getPushedConfigSource(this: AdminProject): Promise<PushedConfigSource>,\n\n /**\n * Unlinks the pushed config source, setting it to \"unlinked\".\n * This allows the config to be edited directly on the dashboard without external push restrictions.\n */\n unlinkPushedConfigSource(this: AdminProject): Promise<void>,\n\n /**\n * Resets (removes) specific keys from the config override at the specified level.\n * Uses the same nested key logic as the override algorithm: resetting key \"a.b\" also resets \"a.b.c\".\n *\n * This is useful when updating the pushed config (branch level) and wanting to remove the same keys\n * from the environment config override so that the branch config values take precedence.\n */\n resetConfigOverrideKeys(this: AdminProject, level: \"branch\" | \"environment\", keys: string[]): Promise<void>,\n\n /**\n * Gets the raw config override at the specified level (before merging/defaults).\n * Useful for inspecting exactly what's been set at each level.\n */\n getConfigOverride(this: AdminProject, level: \"branch\" | \"environment\"): Promise<Record<string, unknown>>,\n\n /**\n * Replaces the entire config override at the specified level.\n * For branch level, preserves the existing source metadata.\n */\n replaceConfigOverride(this: AdminProject, level: \"branch\" | \"environment\", config: Record<string, unknown>): Promise<void>,\n\n getProductionModeErrors(this: AdminProject): Promise<ProductionModeError[]>,\n useProductionModeErrors(this: AdminProject): ProductionModeError[],\n} & Project;\n\nexport type AdminOwnedProject = {\n readonly app: StackAdminApp<false>,\n} & AdminProject;\n\nexport type AdminProjectUpdateOptions = {\n displayName?: string,\n description?: string,\n isProductionMode?: boolean,\n onboardingStatus?: ProjectOnboardingStatus,\n /**\n * Updates `project.requirePublishableClientKey` in the project-level config override.\n */\n requirePublishableClientKey?: boolean,\n logoUrl?: string | null,\n logoFullUrl?: string | null,\n logoDarkModeUrl?: string | null,\n logoFullDarkModeUrl?: string | null,\n config?: AdminProjectConfigUpdateOptions,\n};\nexport function adminProjectUpdateOptionsToCrud(options: AdminProjectUpdateOptions): ProjectsCrud[\"Admin\"][\"Update\"] {\n return {\n display_name: options.displayName,\n description: options.description,\n is_production_mode: options.isProductionMode,\n onboarding_status: options.onboardingStatus,\n logo_url: options.logoUrl,\n logo_full_url: options.logoFullUrl,\n logo_dark_mode_url: options.logoDarkModeUrl,\n logo_full_dark_mode_url: options.logoFullDarkModeUrl,\n /**\n * NOTE: Do not update this config anymore. It's been superseded by the new config in schema.ts.\n * @deprecated\n */\n config: {\n domains: options.config?.domains?.map((d) => ({\n domain: d.domain,\n handler_path: d.handlerPath\n })),\n oauth_providers: options.config?.oauthProviders\n ?.filter((p): p is Exclude<typeof p, { type: 'custom_oidc' }> => p.type !== 'custom_oidc')\n .map((p) => ({\n id: p.id as any,\n type: p.type,\n ...(p.type === 'standard' && {\n client_id: p.clientId,\n client_secret: p.clientSecret,\n facebook_config_id: p.facebookConfigId,\n microsoft_tenant_id: p.microsoftTenantId,\n apple_bundle_ids: p.appleBundleIds,\n }),\n })),\n email_config: options.config?.emailConfig && (\n options.config.emailConfig.type === 'shared' ? {\n type: 'shared',\n } : {\n type: 'standard',\n host: options.config.emailConfig.host,\n port: options.config.emailConfig.port,\n username: options.config.emailConfig.username,\n password: options.config.emailConfig.password,\n sender_name: options.config.emailConfig.senderName,\n sender_email: options.config.emailConfig.senderEmail,\n }\n ),\n email_theme: options.config?.emailTheme,\n sign_up_enabled: options.config?.signUpEnabled,\n credential_enabled: options.config?.credentialEnabled,\n magic_link_enabled: options.config?.magicLinkEnabled,\n passkey_enabled: options.config?.passkeyEnabled,\n allow_localhost: options.config?.allowLocalhost,\n create_team_on_sign_up: options.config?.createTeamOnSignUp,\n client_team_creation_enabled: options.config?.clientTeamCreationEnabled,\n client_user_deletion_enabled: options.config?.clientUserDeletionEnabled,\n team_creator_default_permissions: options.config?.teamCreatorDefaultPermissions,\n team_member_default_permissions: options.config?.teamMemberDefaultPermissions,\n user_default_permissions: options.config?.userDefaultPermissions,\n oauth_account_merge_strategy: options.config?.oauthAccountMergeStrategy,\n allow_user_api_keys: options.config?.allowUserApiKeys,\n allow_team_api_keys: options.config?.allowTeamApiKeys,\n },\n };\n}\n\nexport type AdminProjectCreateOptions = Omit<AdminProjectUpdateOptions, 'displayName'> & {\n displayName: string,\n teamId: string,\n isDevelopmentEnvironment?: boolean,\n};\nexport function adminProjectCreateOptionsToCrud(options: AdminProjectCreateOptions): AdminUserProjectsCrud[\"Server\"][\"Create\"] {\n return {\n ...adminProjectUpdateOptionsToCrud(options),\n display_name: options.displayName,\n is_development_environment: options.isDevelopmentEnvironment,\n owner_team_id: options.teamId,\n };\n}\n"],"mappings":";AAmKA,SAAgB,gCAAgC,SAAqE;AACnH,QAAO;EACL,cAAc,QAAQ;EACtB,aAAa,QAAQ;EACrB,oBAAoB,QAAQ;EAC5B,mBAAmB,QAAQ;EAC3B,UAAU,QAAQ;EAClB,eAAe,QAAQ;EACvB,oBAAoB,QAAQ;EAC5B,yBAAyB,QAAQ;EAKjC,QAAQ;GACN,SAAS,QAAQ,QAAQ,SAAS,KAAK,OAAO;IAC5C,QAAQ,EAAE;IACV,cAAc,EAAE;IACjB,EAAE;GACH,iBAAiB,QAAQ,QAAQ,gBAC7B,QAAQ,MAAuD,EAAE,SAAS,cAAc,CACzF,KAAK,OAAO;IACX,IAAI,EAAE;IACN,MAAM,EAAE;IACR,GAAI,EAAE,SAAS,cAAc;KAC3B,WAAW,EAAE;KACb,eAAe,EAAE;KACjB,oBAAoB,EAAE;KACtB,qBAAqB,EAAE;KACvB,kBAAkB,EAAE;KACrB;IACF,EAAE;GACL,cAAc,QAAQ,QAAQ,gBAC5B,QAAQ,OAAO,YAAY,SAAS,WAAW,EAC7C,MAAM,UACP,GAAG;IACF,MAAM;IACN,MAAM,QAAQ,OAAO,YAAY;IACjC,MAAM,QAAQ,OAAO,YAAY;IACjC,UAAU,QAAQ,OAAO,YAAY;IACrC,UAAU,QAAQ,OAAO,YAAY;IACrC,aAAa,QAAQ,OAAO,YAAY;IACxC,cAAc,QAAQ,OAAO,YAAY;IAC1C;GAEH,aAAa,QAAQ,QAAQ;GAC7B,iBAAiB,QAAQ,QAAQ;GACjC,oBAAoB,QAAQ,QAAQ;GACpC,oBAAoB,QAAQ,QAAQ;GACpC,iBAAiB,QAAQ,QAAQ;GACjC,iBAAiB,QAAQ,QAAQ;GACjC,wBAAwB,QAAQ,QAAQ;GACxC,8BAA8B,QAAQ,QAAQ;GAC9C,8BAA8B,QAAQ,QAAQ;GAC9C,kCAAkC,QAAQ,QAAQ;GAClD,iCAAiC,QAAQ,QAAQ;GACjD,0BAA0B,QAAQ,QAAQ;GAC1C,8BAA8B,QAAQ,QAAQ;GAC9C,qBAAqB,QAAQ,QAAQ;GACrC,qBAAqB,QAAQ,QAAQ;GACtC;EACF;;AAQH,SAAgB,gCAAgC,SAA+E;AAC7H,QAAO;EACL,GAAG,gCAAgC,QAAQ;EAC3C,cAAc,QAAQ;EACtB,4BAA4B,QAAQ;EACpC,eAAe,QAAQ;EACxB"}
@@ -0,0 +1,7 @@
1
+ import { StackClientApp } from "../lib/hexclave-app";
2
+
3
+ //#region src/pushed-config-error-overlay/index.d.ts
4
+ declare function mountPushedConfigErrorOverlay(app: StackClientApp<true>): () => void;
5
+ //#endregion
6
+ export { mountPushedConfigErrorOverlay };
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/pushed-config-error-overlay/index.ts"],"mappings":";;;iBA6VgB,6BAAA,CAA8B,GAAA,EAAK,cAAA"}
@@ -0,0 +1,464 @@
1
+ import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
2
+ import { canMountIntoDom, getGlobalUiInstance, h, setGlobalUiInstance, setHtml } from "../in-page-ui/dom.js";
3
+ import { getInPageUiBaseCSS } from "../in-page-ui/base-styles.js";
4
+ import { captureError } from "@hexclave/shared/dist/utils/errors";
5
+ import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
6
+ import { envVars } from "../generated/env.js";
7
+
8
+ //#region src/pushed-config-error-overlay/index.ts
9
+ const GLOBAL_INSTANCE_KEY = "__hexclave-pushed-config-error-overlay";
10
+ const MINIMIZED_STORAGE_KEY = "hexclave-pushed-config-error-minimized-key";
11
+ const REFRESH_INTERVAL_MS = 5e3;
12
+ const HEXCLAVE_LOGO_SVG = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 48 48\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linejoin=\"miter\"><path d=\"M 24 4 L 41.32 14 L 41.32 34 L 24 44 L 6.68 34 L 6.68 14 Z\"/><path d=\"M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z\" fill=\"currentColor\" stroke=\"none\" transform=\"rotate(120 24 24)\"/><path d=\"M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z\" fill=\"currentColor\" stroke=\"none\" transform=\"rotate(240 24 24)\"/></svg>";
13
+ const COPY_ICON_SVG = "<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>";
14
+ const css = getInPageUiBaseCSS(".hexclave-config-error-overlay") + `
15
+ .hexclave-config-error-overlay .hce-backdrop {
16
+ position: fixed;
17
+ inset: 0;
18
+ z-index: 2147483647;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ padding: 24px;
23
+ background: rgba(0, 0, 0, 0.46);
24
+ backdrop-filter: blur(6px);
25
+ overflow: auto;
26
+ }
27
+
28
+ .hexclave-config-error-overlay .hce-card {
29
+ --hce-status: var(--sdt-error);
30
+ width: min(720px, calc(100vw - 32px));
31
+ max-height: min(640px, calc(100dvh - 48px));
32
+ border: 1px solid color-mix(in srgb, var(--hce-status) 35%, var(--sdt-border));
33
+ border-radius: 18px;
34
+ background: var(--sdt-overlay-bg);
35
+ box-shadow: var(--sdt-shadow);
36
+ backdrop-filter: blur(18px);
37
+ display: flex;
38
+ overflow: hidden;
39
+ }
40
+
41
+ .hexclave-config-error-overlay .hce-card-warning {
42
+ --hce-status: var(--sdt-warning);
43
+ }
44
+
45
+ .hexclave-config-error-overlay .hce-card-inner {
46
+ padding: 18px;
47
+ width: 100%;
48
+ overflow: auto;
49
+ }
50
+
51
+ .hexclave-config-error-overlay .hce-header {
52
+ display: flex;
53
+ align-items: flex-start;
54
+ justify-content: space-between;
55
+ gap: 12px;
56
+ margin-bottom: 12px;
57
+ }
58
+
59
+ .hexclave-config-error-overlay .hce-title-row {
60
+ display: flex;
61
+ align-items: flex-start;
62
+ gap: 10px;
63
+ min-width: 0;
64
+ }
65
+
66
+ .hexclave-config-error-overlay .hce-logo {
67
+ flex-shrink: 0;
68
+ display: flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ width: 34px;
72
+ height: 34px;
73
+ border-radius: 10px;
74
+ background: var(--hce-status);
75
+ color: white;
76
+ box-shadow: 0 10px 30px color-mix(in srgb, var(--hce-status) 32%, transparent);
77
+ }
78
+
79
+ .hexclave-config-error-overlay .hce-badge {
80
+ display: inline-flex;
81
+ flex-shrink: 0;
82
+ padding: 2px 6px;
83
+ border-radius: 999px;
84
+ background: var(--hce-status);
85
+ color: white;
86
+ font-size: 10px;
87
+ font-weight: 700;
88
+ letter-spacing: 0.06em;
89
+ text-transform: uppercase;
90
+ }
91
+
92
+ .hexclave-config-error-overlay .hce-title {
93
+ color: var(--sdt-text);
94
+ margin-top: 4px;
95
+ font-size: 18px;
96
+ font-weight: 700;
97
+ line-height: 1.25;
98
+ }
99
+
100
+ .hexclave-config-error-overlay .hce-actions {
101
+ display: flex;
102
+ gap: 4px;
103
+ }
104
+
105
+ .hexclave-config-error-overlay .hce-icon-btn {
106
+ display: inline-flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ width: 28px;
110
+ height: 28px;
111
+ border: 1px solid var(--sdt-border);
112
+ border-radius: 8px;
113
+ background: var(--sdt-bg-elevated);
114
+ color: var(--sdt-text-secondary);
115
+ cursor: pointer;
116
+ font: inherit;
117
+ line-height: 1;
118
+ vertical-align: top;
119
+ }
120
+
121
+ .hexclave-config-error-overlay .hce-icon-btn svg {
122
+ display: block;
123
+ flex-shrink: 0;
124
+ }
125
+
126
+ .hexclave-config-error-overlay .hce-text-btn {
127
+ align-items: center;
128
+ gap: 6px;
129
+ min-height: 28px;
130
+ padding: 0 10px;
131
+ width: auto;
132
+ font-size: 12px;
133
+ line-height: 1;
134
+ }
135
+
136
+ .hexclave-config-error-overlay .hce-icon-btn:hover {
137
+ background: var(--sdt-bg-hover);
138
+ color: var(--sdt-text);
139
+ }
140
+
141
+ .hexclave-config-error-overlay .hce-body {
142
+ color: var(--sdt-text-secondary);
143
+ font-size: 14px;
144
+ line-height: 1.5;
145
+ }
146
+
147
+ .hexclave-config-error-overlay .hce-message-header {
148
+ display: flex;
149
+ align-items: center;
150
+ justify-content: space-between;
151
+ gap: 10px;
152
+ margin-top: 14px;
153
+ margin-bottom: 8px;
154
+ }
155
+
156
+ .hexclave-config-error-overlay .hce-message-label {
157
+ color: var(--sdt-text);
158
+ font-size: 12px;
159
+ font-weight: 650;
160
+ }
161
+
162
+ .hexclave-config-error-overlay .hce-message {
163
+ padding: 12px;
164
+ max-height: min(260px, max(96px, 30dvh));
165
+ overflow: auto;
166
+ border: 1px solid var(--sdt-border-subtle);
167
+ border-radius: 10px;
168
+ background: var(--sdt-bg-subtle);
169
+ color: var(--sdt-text);
170
+ font-family: var(--sdt-font-mono);
171
+ font-size: 12px;
172
+ white-space: pre-wrap;
173
+ overflow-wrap: anywhere;
174
+ }
175
+
176
+ .hexclave-config-error-overlay .hce-footer {
177
+ margin-top: 10px;
178
+ color: var(--sdt-text-tertiary);
179
+ font-size: 12px;
180
+ }
181
+
182
+ .hexclave-config-error-overlay .hce-pill {
183
+ position: fixed;
184
+ right: 18px;
185
+ bottom: 18px;
186
+ z-index: 2147483647;
187
+ display: flex;
188
+ align-items: center;
189
+ gap: 8px;
190
+ padding: 8px 12px 8px 8px;
191
+ --hce-status: var(--sdt-error);
192
+ border: 1px solid color-mix(in srgb, var(--hce-status) 35%, var(--sdt-border));
193
+ border-radius: 999px;
194
+ background: var(--sdt-overlay-bg);
195
+ box-shadow: var(--sdt-trigger-shadow);
196
+ color: var(--sdt-text);
197
+ cursor: pointer;
198
+ font: inherit;
199
+ backdrop-filter: blur(18px);
200
+ }
201
+
202
+ .hexclave-config-error-overlay .hce-pill-warning {
203
+ --hce-status: var(--sdt-warning);
204
+ }
205
+
206
+ .hexclave-config-error-overlay .hce-pill-logo {
207
+ display: flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ width: 26px;
211
+ height: 26px;
212
+ border-radius: 999px;
213
+ background: var(--hce-status);
214
+ color: white;
215
+ }
216
+
217
+ @media (max-height: 520px) {
218
+ .hexclave-config-error-overlay .hce-backdrop {
219
+ align-items: flex-start;
220
+ padding: 12px;
221
+ }
222
+
223
+ .hexclave-config-error-overlay .hce-card {
224
+ width: min(720px, calc(100vw - 24px));
225
+ max-height: calc(100dvh - 24px);
226
+ }
227
+
228
+ .hexclave-config-error-overlay .hce-card-inner {
229
+ padding: 12px;
230
+ }
231
+
232
+ .hexclave-config-error-overlay .hce-header {
233
+ margin-bottom: 8px;
234
+ }
235
+
236
+ .hexclave-config-error-overlay .hce-title {
237
+ font-size: 16px;
238
+ }
239
+
240
+ .hexclave-config-error-overlay .hce-body {
241
+ font-size: 13px;
242
+ }
243
+
244
+ .hexclave-config-error-overlay .hce-message {
245
+ max-height: max(80px, 24dvh);
246
+ }
247
+ }
248
+ `;
249
+ function storageGet(key) {
250
+ try {
251
+ return localStorage.getItem(key);
252
+ } catch {
253
+ return null;
254
+ }
255
+ }
256
+ function storageSet(key, value) {
257
+ try {
258
+ localStorage.setItem(key, value);
259
+ } catch {}
260
+ }
261
+ function storageRemove(key) {
262
+ try {
263
+ localStorage.removeItem(key);
264
+ } catch {}
265
+ }
266
+ function shouldMount() {
267
+ if (!canMountIntoDom()) return false;
268
+ const nodeEnv = envVars.NODE_ENV;
269
+ if (nodeEnv !== void 0) return nodeEnv === "development";
270
+ try {
271
+ if (new URL(window.location.href).protocol === "file:") return true;
272
+ } catch {
273
+ return false;
274
+ }
275
+ return isLocalhost(window.location.href);
276
+ }
277
+ async function copyTextToClipboard(text) {
278
+ const clipboard = Reflect.get(navigator, "clipboard");
279
+ const writeText = clipboard != null && typeof clipboard === "object" ? Reflect.get(clipboard, "writeText") : null;
280
+ if (typeof writeText === "function") {
281
+ await writeText.call(clipboard, text);
282
+ return;
283
+ }
284
+ const textarea = h("textarea", {
285
+ style: {
286
+ position: "fixed",
287
+ left: "-9999px",
288
+ top: "0",
289
+ opacity: "0"
290
+ },
291
+ readonly: "true"
292
+ });
293
+ textarea.value = text;
294
+ document.body.appendChild(textarea);
295
+ textarea.select();
296
+ const copied = document.execCommand("copy");
297
+ textarea.remove();
298
+ if (!copied) throw new Error("Browser refused to copy the config error message.");
299
+ }
300
+ function buildConfigIssueAiPrompt(issue) {
301
+ const issueLabel = issue.kind === "error" ? "error" : "warning";
302
+ return [
303
+ `Help me fix this Hexclave config ${issueLabel}.`,
304
+ "",
305
+ "Hexclave reminder:",
306
+ `This ${issueLabel} comes from a pushed Hexclave config file. The app may keep running with the synced Hexclave config, but I need to fix the config file mentioned in the message and save it again so Hexclave can sync the config successfully and clear the dialog. Use your web fetch tool to read https://skill.hexclave.com to learn more about Hexclave.`,
307
+ "",
308
+ issue.kind === "error" ? "Error message:" : "Warning message:",
309
+ issue.messages.join("\n"),
310
+ "",
311
+ "Please explain the likely cause, identify the config key or value I should change, and suggest the smallest safe fix."
312
+ ].join("\n");
313
+ }
314
+ function mountPushedConfigErrorOverlay(app) {
315
+ if (!shouldMount()) return () => {};
316
+ getGlobalUiInstance(GLOBAL_INSTANCE_KEY)?.cleanup();
317
+ const root = h("div", { className: "hexclave-config-error-overlay" });
318
+ const style = h("style", null, css);
319
+ root.appendChild(style);
320
+ document.body.appendChild(root);
321
+ let disposed = false;
322
+ let lastErrorKey = null;
323
+ let lastConsoleErrorKey = null;
324
+ let minimized = false;
325
+ const render = (issue) => {
326
+ root.replaceChildren(style);
327
+ if (issue == null) {
328
+ lastErrorKey = null;
329
+ minimized = false;
330
+ return;
331
+ }
332
+ const issueMessage = issue.messages.join("\n");
333
+ const issueKey = `${app.projectId}:${issue.kind}:${issueMessage}`;
334
+ const issueLabel = issue.kind === "error" ? "error" : "warning";
335
+ const issueTitle = issue.kind === "error" ? "Your Hexclave config has been saved, but contains errors" : "Your Hexclave config has been saved, but has warnings";
336
+ const bodyText = issue.kind === "error" ? "Your app can keep running, but Hexclave is still using the last valid config until this is fixed." : "Your app can keep running, but part of your Hexclave config may not behave the way you expect until this is fixed.";
337
+ const footerText = issue.kind === "error" ? "Fix the config file mentioned above and save it again. This message will disappear after the config sync succeeds." : "Fix the config file mentioned above and save it again. This warning will disappear after Hexclave syncs a config without warnings.";
338
+ if (issueKey !== lastConsoleErrorKey) {
339
+ lastConsoleErrorKey = issueKey;
340
+ const consoleMessage = `[Hexclave] Config ${issueLabel}: ${issueMessage}`;
341
+ if (issue.kind === "error") console.error(consoleMessage);
342
+ else console.warn(consoleMessage);
343
+ }
344
+ if (issueKey !== lastErrorKey) {
345
+ lastErrorKey = issueKey;
346
+ minimized = storageGet(MINIMIZED_STORAGE_KEY) === issueKey;
347
+ }
348
+ if (minimized) {
349
+ const logoSpan = h("span", { className: "hce-pill-logo" });
350
+ setHtml(logoSpan, HEXCLAVE_LOGO_SVG);
351
+ root.appendChild(h("button", {
352
+ className: issue.kind === "error" ? "hce-pill" : "hce-pill hce-pill-warning",
353
+ type: "button",
354
+ onClick: () => {
355
+ minimized = false;
356
+ storageRemove(MINIMIZED_STORAGE_KEY);
357
+ render(issue);
358
+ }
359
+ }, logoSpan, h("span", null, issue.kind === "error" ? "Config error" : "Config warning")));
360
+ return;
361
+ }
362
+ const logoSpan = h("span", { className: "hce-logo" });
363
+ setHtml(logoSpan, HEXCLAVE_LOGO_SVG);
364
+ const copyButton = h("button", {
365
+ className: "hce-icon-btn hce-text-btn",
366
+ type: "button",
367
+ title: issue.kind === "error" ? "Copy error message" : "Copy warning message",
368
+ "aria-label": issue.kind === "error" ? "Copy config error message" : "Copy config warning message",
369
+ onClick: () => {
370
+ runAsynchronously(async () => {
371
+ await copyTextToClipboard(issueMessage);
372
+ copyButton.textContent = "Copied";
373
+ setTimeout(() => {
374
+ setHtml(copyButton, `${COPY_ICON_SVG}Copy`);
375
+ }, 1500);
376
+ }, {
377
+ noErrorLogging: true,
378
+ onError: (copyError) => {
379
+ captureError("pushed-config-error-overlay-copy", copyError);
380
+ copyButton.textContent = "Copy failed";
381
+ setTimeout(() => {
382
+ setHtml(copyButton, `${COPY_ICON_SVG}Copy`);
383
+ }, 1500);
384
+ }
385
+ });
386
+ }
387
+ });
388
+ setHtml(copyButton, `${COPY_ICON_SVG}Copy`);
389
+ const aiPromptCopyButton = h("button", {
390
+ className: "hce-icon-btn",
391
+ type: "button",
392
+ title: "Copy AI prompt",
393
+ "aria-label": issue.kind === "error" ? "Copy AI prompt for config error" : "Copy AI prompt for config warning",
394
+ onClick: () => {
395
+ runAsynchronously(async () => {
396
+ await copyTextToClipboard(buildConfigIssueAiPrompt(issue));
397
+ aiPromptCopyButton.textContent = "✓";
398
+ setTimeout(() => {
399
+ setHtml(aiPromptCopyButton, COPY_ICON_SVG);
400
+ }, 1500);
401
+ }, {
402
+ noErrorLogging: true,
403
+ onError: (copyError) => {
404
+ captureError("pushed-config-error-overlay-copy-ai-prompt", copyError);
405
+ aiPromptCopyButton.textContent = "!";
406
+ setTimeout(() => {
407
+ setHtml(aiPromptCopyButton, COPY_ICON_SVG);
408
+ }, 1500);
409
+ }
410
+ });
411
+ }
412
+ });
413
+ setHtml(aiPromptCopyButton, COPY_ICON_SVG);
414
+ root.appendChild(h("div", { className: "hce-backdrop" }, h("div", {
415
+ className: issue.kind === "error" ? "hce-card" : "hce-card hce-card-warning",
416
+ role: "alertdialog",
417
+ "aria-modal": "true",
418
+ "aria-label": `Hexclave config ${issueLabel}`
419
+ }, h("div", { className: "hce-card-inner" }, h("div", { className: "hce-header" }, h("div", { className: "hce-title-row" }, logoSpan, h("div", null, h("span", { className: "hce-badge" }, `Config ${issueLabel}`), h("div", { className: "hce-title" }, issueTitle))), h("div", { className: "hce-actions" }, aiPromptCopyButton, h("button", {
420
+ className: "hce-icon-btn",
421
+ type: "button",
422
+ title: "Minimize",
423
+ "aria-label": issue.kind === "error" ? "Minimize config error" : "Minimize config warning",
424
+ onClick: () => {
425
+ minimized = true;
426
+ storageSet(MINIMIZED_STORAGE_KEY, issueKey);
427
+ render(issue);
428
+ }
429
+ }, "–"))), h("div", { className: "hce-body" }, bodyText, h("div", { className: "hce-message-header" }, h("div", { className: "hce-message-label" }, issue.kind === "error" ? "Error message" : "Warning message"), copyButton), h("div", { className: "hce-message" }, issueMessage), h("div", { className: "hce-footer" }, footerText))))));
430
+ };
431
+ const refresh = () => {
432
+ if (disposed || !canMountIntoDom()) return;
433
+ runAsynchronously(async () => {
434
+ const project = await app.getProject();
435
+ if (disposed) return;
436
+ render(project.pushedConfigError == null ? project.configWarnings.length === 0 ? null : {
437
+ kind: "warning",
438
+ messages: project.configWarnings.map((warning) => warning.message)
439
+ } : {
440
+ kind: "error",
441
+ messages: [project.pushedConfigError.message]
442
+ });
443
+ }, {
444
+ noErrorLogging: true,
445
+ onError: (error) => {
446
+ captureError("pushed-config-error-overlay-refresh", error);
447
+ }
448
+ });
449
+ };
450
+ refresh();
451
+ const interval = setInterval(refresh, REFRESH_INTERVAL_MS);
452
+ const cleanup = () => {
453
+ disposed = true;
454
+ clearInterval(interval);
455
+ root.remove();
456
+ if (getGlobalUiInstance(GLOBAL_INSTANCE_KEY)?.cleanup === cleanup) setGlobalUiInstance(GLOBAL_INSTANCE_KEY, null);
457
+ };
458
+ setGlobalUiInstance(GLOBAL_INSTANCE_KEY, { cleanup });
459
+ return cleanup;
460
+ }
461
+
462
+ //#endregion
463
+ export { mountPushedConfigErrorOverlay };
464
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/pushed-config-error-overlay/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { captureError } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { isLocalhost } from \"@hexclave/shared/dist/utils/urls\";\nimport { envVars } from \"../generated/env\";\nimport { getInPageUiBaseCSS } from \"../in-page-ui/base-styles\";\nimport { canMountIntoDom, getGlobalUiInstance, h, setGlobalUiInstance, setHtml } from \"../in-page-ui/dom\";\nimport type { StackClientApp } from \"../lib/hexclave-app\";\n\nconst GLOBAL_INSTANCE_KEY = \"__hexclave-pushed-config-error-overlay\";\nconst MINIMIZED_STORAGE_KEY = \"hexclave-pushed-config-error-minimized-key\";\nconst REFRESH_INTERVAL_MS = 5_000;\nconst HEXCLAVE_LOGO_SVG = '<svg width=\"16\" height=\"16\" viewBox=\"0 0 48 48\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linejoin=\"miter\"><path d=\"M 24 4 L 41.32 14 L 41.32 34 L 24 44 L 6.68 34 L 6.68 14 Z\"/><path d=\"M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z\" fill=\"currentColor\" stroke=\"none\" transform=\"rotate(120 24 24)\"/><path d=\"M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z\" fill=\"currentColor\" stroke=\"none\" transform=\"rotate(240 24 24)\"/></svg>';\nconst COPY_ICON_SVG = '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>';\n\ntype ConfigIssue = {\n kind: \"error\" | \"warning\",\n messages: string[],\n};\n\nconst css = getInPageUiBaseCSS(\".hexclave-config-error-overlay\") + `\n .hexclave-config-error-overlay .hce-backdrop {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: rgba(0, 0, 0, 0.46);\n backdrop-filter: blur(6px);\n overflow: auto;\n }\n\n .hexclave-config-error-overlay .hce-card {\n --hce-status: var(--sdt-error);\n width: min(720px, calc(100vw - 32px));\n max-height: min(640px, calc(100dvh - 48px));\n border: 1px solid color-mix(in srgb, var(--hce-status) 35%, var(--sdt-border));\n border-radius: 18px;\n background: var(--sdt-overlay-bg);\n box-shadow: var(--sdt-shadow);\n backdrop-filter: blur(18px);\n display: flex;\n overflow: hidden;\n }\n\n .hexclave-config-error-overlay .hce-card-warning {\n --hce-status: var(--sdt-warning);\n }\n\n .hexclave-config-error-overlay .hce-card-inner {\n padding: 18px;\n width: 100%;\n overflow: auto;\n }\n\n .hexclave-config-error-overlay .hce-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n }\n\n .hexclave-config-error-overlay .hce-title-row {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n }\n\n .hexclave-config-error-overlay .hce-logo {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n height: 34px;\n border-radius: 10px;\n background: var(--hce-status);\n color: white;\n box-shadow: 0 10px 30px color-mix(in srgb, var(--hce-status) 32%, transparent);\n }\n\n .hexclave-config-error-overlay .hce-badge {\n display: inline-flex;\n flex-shrink: 0;\n padding: 2px 6px;\n border-radius: 999px;\n background: var(--hce-status);\n color: white;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n\n .hexclave-config-error-overlay .hce-title {\n color: var(--sdt-text);\n margin-top: 4px;\n font-size: 18px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n .hexclave-config-error-overlay .hce-actions {\n display: flex;\n gap: 4px;\n }\n\n .hexclave-config-error-overlay .hce-icon-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--sdt-border);\n border-radius: 8px;\n background: var(--sdt-bg-elevated);\n color: var(--sdt-text-secondary);\n cursor: pointer;\n font: inherit;\n line-height: 1;\n vertical-align: top;\n }\n\n .hexclave-config-error-overlay .hce-icon-btn svg {\n display: block;\n flex-shrink: 0;\n }\n\n .hexclave-config-error-overlay .hce-text-btn {\n align-items: center;\n gap: 6px;\n min-height: 28px;\n padding: 0 10px;\n width: auto;\n font-size: 12px;\n line-height: 1;\n }\n\n .hexclave-config-error-overlay .hce-icon-btn:hover {\n background: var(--sdt-bg-hover);\n color: var(--sdt-text);\n }\n\n .hexclave-config-error-overlay .hce-body {\n color: var(--sdt-text-secondary);\n font-size: 14px;\n line-height: 1.5;\n }\n\n .hexclave-config-error-overlay .hce-message-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-top: 14px;\n margin-bottom: 8px;\n }\n\n .hexclave-config-error-overlay .hce-message-label {\n color: var(--sdt-text);\n font-size: 12px;\n font-weight: 650;\n }\n\n .hexclave-config-error-overlay .hce-message {\n padding: 12px;\n max-height: min(260px, max(96px, 30dvh));\n overflow: auto;\n border: 1px solid var(--sdt-border-subtle);\n border-radius: 10px;\n background: var(--sdt-bg-subtle);\n color: var(--sdt-text);\n font-family: var(--sdt-font-mono);\n font-size: 12px;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n }\n\n .hexclave-config-error-overlay .hce-footer {\n margin-top: 10px;\n color: var(--sdt-text-tertiary);\n font-size: 12px;\n }\n\n .hexclave-config-error-overlay .hce-pill {\n position: fixed;\n right: 18px;\n bottom: 18px;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px 8px 8px;\n --hce-status: var(--sdt-error);\n border: 1px solid color-mix(in srgb, var(--hce-status) 35%, var(--sdt-border));\n border-radius: 999px;\n background: var(--sdt-overlay-bg);\n box-shadow: var(--sdt-trigger-shadow);\n color: var(--sdt-text);\n cursor: pointer;\n font: inherit;\n backdrop-filter: blur(18px);\n }\n\n .hexclave-config-error-overlay .hce-pill-warning {\n --hce-status: var(--sdt-warning);\n }\n\n .hexclave-config-error-overlay .hce-pill-logo {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border-radius: 999px;\n background: var(--hce-status);\n color: white;\n }\n\n @media (max-height: 520px) {\n .hexclave-config-error-overlay .hce-backdrop {\n align-items: flex-start;\n padding: 12px;\n }\n\n .hexclave-config-error-overlay .hce-card {\n width: min(720px, calc(100vw - 24px));\n max-height: calc(100dvh - 24px);\n }\n\n .hexclave-config-error-overlay .hce-card-inner {\n padding: 12px;\n }\n\n .hexclave-config-error-overlay .hce-header {\n margin-bottom: 8px;\n }\n\n .hexclave-config-error-overlay .hce-title {\n font-size: 16px;\n }\n\n .hexclave-config-error-overlay .hce-body {\n font-size: 13px;\n }\n\n .hexclave-config-error-overlay .hce-message {\n max-height: max(80px, 24dvh);\n }\n }\n`;\n\nfunction storageGet(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction storageSet(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n // Storage may be unavailable in private or embedded contexts.\n }\n}\n\nfunction storageRemove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // Storage may be unavailable in private or embedded contexts.\n }\n}\n\nfunction shouldMount(): boolean {\n if (!canMountIntoDom()) {\n return false;\n }\n\n const nodeEnv = envVars.NODE_ENV;\n if (nodeEnv !== undefined) {\n return nodeEnv === \"development\";\n }\n\n try {\n const url = new URL(window.location.href);\n if (url.protocol === \"file:\") {\n return true;\n }\n } catch {\n return false;\n }\n return isLocalhost(window.location.href);\n}\n\nasync function copyTextToClipboard(text: string): Promise<void> {\n const clipboard: unknown = Reflect.get(navigator, \"clipboard\");\n const writeText = clipboard != null && typeof clipboard === \"object\"\n ? Reflect.get(clipboard, \"writeText\")\n : null;\n if (typeof writeText === \"function\") {\n await writeText.call(clipboard, text);\n return;\n }\n\n const textarea = h(\"textarea\", {\n style: {\n position: \"fixed\",\n left: \"-9999px\",\n top: \"0\",\n opacity: \"0\",\n },\n readonly: \"true\",\n }) as HTMLTextAreaElement;\n textarea.value = text;\n document.body.appendChild(textarea);\n textarea.select();\n const copied = document.execCommand(\"copy\");\n textarea.remove();\n if (!copied) {\n throw new Error(\"Browser refused to copy the config error message.\");\n }\n}\n\nfunction buildConfigIssueAiPrompt(issue: ConfigIssue): string {\n const issueLabel = issue.kind === \"error\" ? \"error\" : \"warning\";\n return [\n `Help me fix this Hexclave config ${issueLabel}.`,\n \"\",\n \"Hexclave reminder:\",\n `This ${issueLabel} comes from a pushed Hexclave config file. The app may keep running with the synced Hexclave config, but I need to fix the config file mentioned in the message and save it again so Hexclave can sync the config successfully and clear the dialog. Use your web fetch tool to read https://skill.hexclave.com to learn more about Hexclave.`,\n \"\",\n issue.kind === \"error\" ? \"Error message:\" : \"Warning message:\",\n issue.messages.join(\"\\n\"),\n \"\",\n \"Please explain the likely cause, identify the config key or value I should change, and suggest the smallest safe fix.\",\n ].join(\"\\n\");\n}\n\nexport function mountPushedConfigErrorOverlay(app: StackClientApp<true>): () => void {\n if (!shouldMount()) {\n return () => {};\n }\n\n getGlobalUiInstance(GLOBAL_INSTANCE_KEY)?.cleanup();\n\n const root = h(\"div\", { className: \"hexclave-config-error-overlay\" });\n const style = h(\"style\", null, css);\n root.appendChild(style);\n document.body.appendChild(root);\n\n let disposed = false;\n let lastErrorKey: string | null = null;\n let lastConsoleErrorKey: string | null = null;\n let minimized = false;\n\n const render = (issue: ConfigIssue | null) => {\n root.replaceChildren(style);\n if (issue == null) {\n lastErrorKey = null;\n minimized = false;\n return;\n }\n\n const issueMessage = issue.messages.join(\"\\n\");\n const issueKey = `${app.projectId}:${issue.kind}:${issueMessage}`;\n const issueLabel = issue.kind === \"error\" ? \"error\" : \"warning\";\n const issueTitle = issue.kind === \"error\"\n ? \"Your Hexclave config has been saved, but contains errors\"\n : \"Your Hexclave config has been saved, but has warnings\";\n const bodyText = issue.kind === \"error\"\n ? \"Your app can keep running, but Hexclave is still using the last valid config until this is fixed.\"\n : \"Your app can keep running, but part of your Hexclave config may not behave the way you expect until this is fixed.\";\n const footerText = issue.kind === \"error\"\n ? \"Fix the config file mentioned above and save it again. This message will disappear after the config sync succeeds.\"\n : \"Fix the config file mentioned above and save it again. This warning will disappear after Hexclave syncs a config without warnings.\";\n if (issueKey !== lastConsoleErrorKey) {\n lastConsoleErrorKey = issueKey;\n const consoleMessage = `[Hexclave] Config ${issueLabel}: ${issueMessage}`;\n if (issue.kind === \"error\") {\n console.error(consoleMessage);\n } else {\n console.warn(consoleMessage);\n }\n }\n\n if (issueKey !== lastErrorKey) {\n lastErrorKey = issueKey;\n minimized = storageGet(MINIMIZED_STORAGE_KEY) === issueKey;\n }\n\n if (minimized) {\n const logoSpan = h(\"span\", { className: \"hce-pill-logo\" });\n setHtml(logoSpan, HEXCLAVE_LOGO_SVG);\n root.appendChild(h(\"button\", {\n className: issue.kind === \"error\" ? \"hce-pill\" : \"hce-pill hce-pill-warning\",\n type: \"button\",\n onClick: () => {\n minimized = false;\n storageRemove(MINIMIZED_STORAGE_KEY);\n render(issue);\n },\n },\n logoSpan,\n h(\"span\", null, issue.kind === \"error\" ? \"Config error\" : \"Config warning\")));\n return;\n }\n\n const logoSpan = h(\"span\", { className: \"hce-logo\" });\n setHtml(logoSpan, HEXCLAVE_LOGO_SVG);\n const copyButton = h(\"button\", {\n className: \"hce-icon-btn hce-text-btn\",\n type: \"button\",\n title: issue.kind === \"error\" ? \"Copy error message\" : \"Copy warning message\",\n \"aria-label\": issue.kind === \"error\" ? \"Copy config error message\" : \"Copy config warning message\",\n onClick: () => {\n runAsynchronously(async () => {\n await copyTextToClipboard(issueMessage);\n copyButton.textContent = \"Copied\";\n setTimeout(() => {\n setHtml(copyButton, `${COPY_ICON_SVG}Copy`);\n }, 1500);\n }, {\n noErrorLogging: true,\n onError: (copyError) => {\n captureError(\"pushed-config-error-overlay-copy\", copyError);\n copyButton.textContent = \"Copy failed\";\n setTimeout(() => {\n setHtml(copyButton, `${COPY_ICON_SVG}Copy`);\n }, 1500);\n },\n });\n },\n });\n setHtml(copyButton, `${COPY_ICON_SVG}Copy`);\n\n const aiPromptCopyButton = h(\"button\", {\n className: \"hce-icon-btn\",\n type: \"button\",\n title: \"Copy AI prompt\",\n \"aria-label\": issue.kind === \"error\" ? \"Copy AI prompt for config error\" : \"Copy AI prompt for config warning\",\n onClick: () => {\n runAsynchronously(async () => {\n await copyTextToClipboard(buildConfigIssueAiPrompt(issue));\n aiPromptCopyButton.textContent = \"✓\";\n setTimeout(() => {\n setHtml(aiPromptCopyButton, COPY_ICON_SVG);\n }, 1500);\n }, {\n noErrorLogging: true,\n onError: (copyError) => {\n captureError(\"pushed-config-error-overlay-copy-ai-prompt\", copyError);\n aiPromptCopyButton.textContent = \"!\";\n setTimeout(() => {\n setHtml(aiPromptCopyButton, COPY_ICON_SVG);\n }, 1500);\n },\n });\n },\n });\n setHtml(aiPromptCopyButton, COPY_ICON_SVG);\n\n root.appendChild(h(\"div\", { className: \"hce-backdrop\" },\n h(\"div\", { className: issue.kind === \"error\" ? \"hce-card\" : \"hce-card hce-card-warning\", role: \"alertdialog\", \"aria-modal\": \"true\", \"aria-label\": `Hexclave config ${issueLabel}` },\n h(\"div\", { className: \"hce-card-inner\" },\n h(\"div\", { className: \"hce-header\" },\n h(\"div\", { className: \"hce-title-row\" },\n logoSpan,\n h(\"div\", null,\n h(\"span\", { className: \"hce-badge\" }, `Config ${issueLabel}`),\n h(\"div\", { className: \"hce-title\" }, issueTitle),\n ),\n ),\n h(\"div\", { className: \"hce-actions\" },\n aiPromptCopyButton,\n h(\"button\", {\n className: \"hce-icon-btn\",\n type: \"button\",\n title: \"Minimize\",\n \"aria-label\": issue.kind === \"error\" ? \"Minimize config error\" : \"Minimize config warning\",\n onClick: () => {\n minimized = true;\n storageSet(MINIMIZED_STORAGE_KEY, issueKey);\n render(issue);\n },\n }, \"–\"),\n ),\n ),\n h(\"div\", { className: \"hce-body\" },\n bodyText,\n h(\"div\", { className: \"hce-message-header\" },\n h(\"div\", { className: \"hce-message-label\" }, issue.kind === \"error\" ? \"Error message\" : \"Warning message\"),\n copyButton,\n ),\n h(\"div\", { className: \"hce-message\" }, issueMessage),\n h(\"div\", { className: \"hce-footer\" }, footerText),\n ),\n ),\n )));\n };\n\n const refresh = () => {\n if (disposed || !canMountIntoDom()) {\n return;\n }\n runAsynchronously(async () => {\n const project = await app.getProject();\n if (disposed) {\n return;\n }\n render(project.pushedConfigError == null\n ? project.configWarnings.length === 0\n ? null\n : { kind: \"warning\", messages: project.configWarnings.map((warning) => warning.message) }\n : { kind: \"error\", messages: [project.pushedConfigError.message] });\n }, {\n noErrorLogging: true,\n onError: (error) => {\n captureError(\"pushed-config-error-overlay-refresh\", error);\n },\n });\n };\n\n refresh();\n const interval = setInterval(refresh, REFRESH_INTERVAL_MS);\n\n const cleanup = () => {\n disposed = true;\n clearInterval(interval);\n root.remove();\n if (getGlobalUiInstance(GLOBAL_INSTANCE_KEY)?.cleanup === cleanup) {\n setGlobalUiInstance(GLOBAL_INSTANCE_KEY, null);\n }\n };\n setGlobalUiInstance(GLOBAL_INSTANCE_KEY, { cleanup });\n return cleanup;\n}\n\n"],"mappings":";;;;;;;;AAaA,MAAM,sBAAsB;AAC5B,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;AAC5B,MAAM,oBAAoB;AAC1B,MAAM,gBAAgB;AAOtB,MAAM,MAAM,mBAAmB,iCAAiC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4OnE,SAAS,WAAW,KAA4B;AAC9C,KAAI;AACF,SAAO,aAAa,QAAQ,IAAI;SAC1B;AACN,SAAO;;;AAIX,SAAS,WAAW,KAAa,OAAqB;AACpD,KAAI;AACF,eAAa,QAAQ,KAAK,MAAM;SAC1B;;AAKV,SAAS,cAAc,KAAmB;AACxC,KAAI;AACF,eAAa,WAAW,IAAI;SACtB;;AAKV,SAAS,cAAuB;AAC9B,KAAI,CAAC,iBAAiB,CACpB,QAAO;CAGT,MAAM,UAAU,QAAQ;AACxB,KAAI,YAAY,OACd,QAAO,YAAY;AAGrB,KAAI;AAEF,MADY,IAAI,IAAI,OAAO,SAAS,KAAK,CACjC,aAAa,QACnB,QAAO;SAEH;AACN,SAAO;;AAET,QAAO,YAAY,OAAO,SAAS,KAAK;;AAG1C,eAAe,oBAAoB,MAA6B;CAC9D,MAAM,YAAqB,QAAQ,IAAI,WAAW,YAAY;CAC9D,MAAM,YAAY,aAAa,QAAQ,OAAO,cAAc,WACxD,QAAQ,IAAI,WAAW,YAAY,GACnC;AACJ,KAAI,OAAO,cAAc,YAAY;AACnC,QAAM,UAAU,KAAK,WAAW,KAAK;AACrC;;CAGF,MAAM,WAAW,EAAE,YAAY;EAC7B,OAAO;GACL,UAAU;GACV,MAAM;GACN,KAAK;GACL,SAAS;GACV;EACD,UAAU;EACX,CAAC;AACF,UAAS,QAAQ;AACjB,UAAS,KAAK,YAAY,SAAS;AACnC,UAAS,QAAQ;CACjB,MAAM,SAAS,SAAS,YAAY,OAAO;AAC3C,UAAS,QAAQ;AACjB,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,oDAAoD;;AAIxE,SAAS,yBAAyB,OAA4B;CAC5D,MAAM,aAAa,MAAM,SAAS,UAAU,UAAU;AACtD,QAAO;EACL,oCAAoC,WAAW;EAC/C;EACA;EACA,QAAQ,WAAW;EACnB;EACA,MAAM,SAAS,UAAU,mBAAmB;EAC5C,MAAM,SAAS,KAAK,KAAK;EACzB;EACA;EACD,CAAC,KAAK,KAAK;;AAGd,SAAgB,8BAA8B,KAAuC;AACnF,KAAI,CAAC,aAAa,CAChB,cAAa;AAGf,qBAAoB,oBAAoB,EAAE,SAAS;CAEnD,MAAM,OAAO,EAAE,OAAO,EAAE,WAAW,iCAAiC,CAAC;CACrE,MAAM,QAAQ,EAAE,SAAS,MAAM,IAAI;AACnC,MAAK,YAAY,MAAM;AACvB,UAAS,KAAK,YAAY,KAAK;CAE/B,IAAI,WAAW;CACf,IAAI,eAA8B;CAClC,IAAI,sBAAqC;CACzC,IAAI,YAAY;CAEhB,MAAM,UAAU,UAA8B;AAC5C,OAAK,gBAAgB,MAAM;AAC3B,MAAI,SAAS,MAAM;AACjB,kBAAe;AACf,eAAY;AACZ;;EAGF,MAAM,eAAe,MAAM,SAAS,KAAK,KAAK;EAC9C,MAAM,WAAW,GAAG,IAAI,UAAU,GAAG,MAAM,KAAK,GAAG;EACnD,MAAM,aAAa,MAAM,SAAS,UAAU,UAAU;EACtD,MAAM,aAAa,MAAM,SAAS,UAC9B,6DACA;EACJ,MAAM,WAAW,MAAM,SAAS,UAC5B,sGACA;EACJ,MAAM,aAAa,MAAM,SAAS,UAC9B,uHACA;AACJ,MAAI,aAAa,qBAAqB;AACpC,yBAAsB;GACtB,MAAM,iBAAiB,qBAAqB,WAAW,IAAI;AAC3D,OAAI,MAAM,SAAS,QACjB,SAAQ,MAAM,eAAe;OAE7B,SAAQ,KAAK,eAAe;;AAIhC,MAAI,aAAa,cAAc;AAC7B,kBAAe;AACf,eAAY,WAAW,sBAAsB,KAAK;;AAGpD,MAAI,WAAW;GACb,MAAM,WAAW,EAAE,QAAQ,EAAE,WAAW,iBAAiB,CAAC;AAC1D,WAAQ,UAAU,kBAAkB;AACpC,QAAK,YAAY,EAAE,UAAU;IAC3B,WAAW,MAAM,SAAS,UAAU,aAAa;IACjD,MAAM;IACN,eAAe;AACb,iBAAY;AACZ,mBAAc,sBAAsB;AACpC,YAAO,MAAM;;IAEhB,EACD,UACA,EAAE,QAAQ,MAAM,MAAM,SAAS,UAAU,iBAAiB,iBAAiB,CAAC,CAAC;AAC7E;;EAGF,MAAM,WAAW,EAAE,QAAQ,EAAE,WAAW,YAAY,CAAC;AACrD,UAAQ,UAAU,kBAAkB;EACpC,MAAM,aAAa,EAAE,UAAU;GAC7B,WAAW;GACX,MAAM;GACN,OAAO,MAAM,SAAS,UAAU,uBAAuB;GACvD,cAAc,MAAM,SAAS,UAAU,8BAA8B;GACrE,eAAe;AACb,sBAAkB,YAAY;AAC5B,WAAM,oBAAoB,aAAa;AACvC,gBAAW,cAAc;AACzB,sBAAiB;AACf,cAAQ,YAAY,GAAG,cAAc,MAAM;QAC1C,KAAK;OACP;KACD,gBAAgB;KAChB,UAAU,cAAc;AACtB,mBAAa,oCAAoC,UAAU;AAC3D,iBAAW,cAAc;AACzB,uBAAiB;AACf,eAAQ,YAAY,GAAG,cAAc,MAAM;SAC1C,KAAK;;KAEX,CAAC;;GAEL,CAAC;AACF,UAAQ,YAAY,GAAG,cAAc,MAAM;EAE3C,MAAM,qBAAqB,EAAE,UAAU;GACrC,WAAW;GACX,MAAM;GACN,OAAO;GACP,cAAc,MAAM,SAAS,UAAU,oCAAoC;GAC3E,eAAe;AACb,sBAAkB,YAAY;AAC5B,WAAM,oBAAoB,yBAAyB,MAAM,CAAC;AAC1D,wBAAmB,cAAc;AACjC,sBAAiB;AACf,cAAQ,oBAAoB,cAAc;QACzC,KAAK;OACP;KACD,gBAAgB;KAChB,UAAU,cAAc;AACtB,mBAAa,8CAA8C,UAAU;AACrE,yBAAmB,cAAc;AACjC,uBAAiB;AACf,eAAQ,oBAAoB,cAAc;SACzC,KAAK;;KAEX,CAAC;;GAEL,CAAC;AACF,UAAQ,oBAAoB,cAAc;AAE1C,OAAK,YAAY,EAAE,OAAO,EAAE,WAAW,gBAAgB,EACrD,EAAE,OAAO;GAAE,WAAW,MAAM,SAAS,UAAU,aAAa;GAA6B,MAAM;GAAe,cAAc;GAAQ,cAAc,mBAAmB;GAAc,EACnL,EAAE,OAAO,EAAE,WAAW,kBAAkB,EACtC,EAAE,OAAO,EAAE,WAAW,cAAc,EAClC,EAAE,OAAO,EAAE,WAAW,iBAAiB,EACrC,UACA,EAAE,OAAO,MACP,EAAE,QAAQ,EAAE,WAAW,aAAa,EAAE,UAAU,aAAa,EAC7D,EAAE,OAAO,EAAE,WAAW,aAAa,EAAE,WAAW,CACjD,CACF,EACD,EAAE,OAAO,EAAE,WAAW,eAAe,EACnC,oBACA,EAAE,UAAU;GACV,WAAW;GACX,MAAM;GACN,OAAO;GACP,cAAc,MAAM,SAAS,UAAU,0BAA0B;GACjE,eAAe;AACb,gBAAY;AACZ,eAAW,uBAAuB,SAAS;AAC3C,WAAO,MAAM;;GAEhB,EAAE,IAAI,CACR,CACF,EACD,EAAE,OAAO,EAAE,WAAW,YAAY,EAChC,UACA,EAAE,OAAO,EAAE,WAAW,sBAAsB,EAC1C,EAAE,OAAO,EAAE,WAAW,qBAAqB,EAAE,MAAM,SAAS,UAAU,kBAAkB,kBAAkB,EAC1G,WACD,EACD,EAAE,OAAO,EAAE,WAAW,eAAe,EAAE,aAAa,EACpD,EAAE,OAAO,EAAE,WAAW,cAAc,EAAE,WAAW,CAClD,CACF,CACF,CAAC,CAAC;;CAGL,MAAM,gBAAgB;AACpB,MAAI,YAAY,CAAC,iBAAiB,CAChC;AAEF,oBAAkB,YAAY;GAC5B,MAAM,UAAU,MAAM,IAAI,YAAY;AACtC,OAAI,SACF;AAEF,UAAO,QAAQ,qBAAqB,OAChC,QAAQ,eAAe,WAAW,IAChC,OACA;IAAE,MAAM;IAAW,UAAU,QAAQ,eAAe,KAAK,YAAY,QAAQ,QAAQ;IAAE,GACzF;IAAE,MAAM;IAAS,UAAU,CAAC,QAAQ,kBAAkB,QAAQ;IAAE,CAAC;KACpE;GACD,gBAAgB;GAChB,UAAU,UAAU;AAClB,iBAAa,uCAAuC,MAAM;;GAE7D,CAAC;;AAGJ,UAAS;CACT,MAAM,WAAW,YAAY,SAAS,oBAAoB;CAE1D,MAAM,gBAAgB;AACpB,aAAW;AACX,gBAAc,SAAS;AACvB,OAAK,QAAQ;AACb,MAAI,oBAAoB,oBAAoB,EAAE,YAAY,QACxD,qBAAoB,qBAAqB,KAAK;;AAGlD,qBAAoB,qBAAqB,EAAE,SAAS,CAAC;AACrD,QAAO"}