@termix-ssh/plugin-sdk 1.0.5 → 1.0.6

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://raw.githubusercontent.com/Termix-SSH/Termix/main/public/icon.svg" width="120" height="120" alt="Termix Logo" />
3
+ <img src="https://termix.site/img/logo.svg" width="120" alt="Termix Logo" />
4
4
 
5
5
  <h1>Termix Plugin SDK</h1>
6
6
 
@@ -2,7 +2,7 @@ const __termixNoGlob = () => ({});
2
2
  import {
3
3
  hasPermission,
4
4
  usePermissions
5
- } from "./chunk-KOOUKYW3.js";
5
+ } from "./chunk-DIOJ3KW2.js";
6
6
  import {
7
7
  PRESETS,
8
8
  SYNC_CHANGED_EVENT,
@@ -39,7 +39,7 @@ import {
39
39
  usePluginStore,
40
40
  useTabTypes,
41
41
  websocketAuthProtocols
42
- } from "./chunk-OEOKIKXC.js";
42
+ } from "./chunk-NZG6HNQH.js";
43
43
  import {
44
44
  __export,
45
45
  define_import_meta_env_default
@@ -49010,7 +49010,9 @@ var docs_pages_default = {
49010
49010
  pluginCatalog: "plugins",
49011
49011
  cli: "cli",
49012
49012
  develop: "develop",
49013
- communityRegistry: "develop/community-registry"
49013
+ communityRegistry: "develop/community-registry",
49014
+ pluginRegistries: "guide/plugins#registries",
49015
+ hostRegistry: "develop/registries"
49014
49016
  };
49015
49017
 
49016
49018
  // src/ui/lib/docs.ts
@@ -49233,7 +49235,7 @@ function withAnchor(url, anchor) {
49233
49235
  }
49234
49236
 
49235
49237
  // src/ui/components/panel-layout.tsx
49236
- import { Children as Children5, Fragment as Fragment11, useRef as useRef28 } from "react";
49238
+ import { Children as Children5, Fragment as Fragment11, isValidElement as isValidElement2, useRef as useRef28 } from "react";
49237
49239
  import { useTranslation as useTranslation3 } from "react-i18next";
49238
49240
  import { Fragment as Fragment12, jsx as jsx31, jsxs as jsxs8 } from "react/jsx-runtime";
49239
49241
  var PANEL = {
@@ -49516,11 +49518,16 @@ function ToggleButton({
49516
49518
  }
49517
49519
  );
49518
49520
  }
49521
+ function flattenFacts(children) {
49522
+ return Children5.toArray(children).flatMap(
49523
+ (child) => isValidElement2(child) && child.type === Fragment11 ? flattenFacts(child.props.children) : [child]
49524
+ );
49525
+ }
49519
49526
  function Facts({
49520
49527
  className,
49521
49528
  children
49522
49529
  }) {
49523
- const items = Children5.toArray(children).filter(Boolean);
49530
+ const items = flattenFacts(children);
49524
49531
  if (items.length === 0) return null;
49525
49532
  return /* @__PURE__ */ jsx31("span", { className: cn("flex min-w-0 items-center gap-2", className), children: items.map((child, i) => /* @__PURE__ */ jsxs8(Fragment11, { children: [
49526
49533
  i > 0 && /* @__PURE__ */ jsx31("span", { "aria-hidden": true, className: "h-3 w-px shrink-0 bg-border" }),
@@ -50568,6 +50575,37 @@ var en_default = {
50568
50575
  desktopLinked: "Linked to {{server}}",
50569
50576
  pluginsDocsLink: "Read about each one"
50570
50577
  },
50578
+ desktopUpdates: {
50579
+ title: "Desktop app",
50580
+ mode: "Updates",
50581
+ modeHint: "How this app gets new versions.",
50582
+ manualModeHint: "This copy can not update itself, so Termix only tells you when a new version is out.",
50583
+ modeAutomatic: "Automatic",
50584
+ modePrompt: "Ask first",
50585
+ modeNever: "Never",
50586
+ automaticBody: "Download new versions in the background and install them when you restart.",
50587
+ promptBody: "Tell me when a new version is out and let me choose when to download it.",
50588
+ neverBody: "Do not check for updates. You can still check by hand in Settings.",
50589
+ onboardingTitle: "App updates",
50590
+ onboardingBody: "The desktop app can now update itself. Pick how you want new versions to arrive. You can change this later in Settings, Updates.",
50591
+ onboardingManual: "This copy of the app was installed in a way that can not update itself, so Termix will tell you when a new version is out with a link to download it.",
50592
+ status: "Version {{version}}",
50593
+ statusIdle: "Not checked yet",
50594
+ statusChecking: "Checking for updates",
50595
+ statusAvailable: "Version {{version}} is available",
50596
+ statusDownloading: "Downloading {{version}} ({{progress}}%)",
50597
+ statusReady: "Version {{version}} is ready. Restart to install it.",
50598
+ statusUpToDate: "You have the newest version",
50599
+ statusError: "Could not check for updates. Try again later.",
50600
+ checkNow: "Check now",
50601
+ download: "Download",
50602
+ restart: "Restart now",
50603
+ later: "Later",
50604
+ available: "Termix {{version}} is available",
50605
+ manualHint: "Download it from the release page and install it over this one.",
50606
+ ready: "Termix {{version}} is ready to install",
50607
+ readyHint: "It installs the next time Termix restarts."
50608
+ },
50571
50609
  nav: {
50572
50610
  home: "Home",
50573
50611
  terminal: "Terminal",
@@ -50615,7 +50653,8 @@ var en_default = {
50615
50653
  },
50616
50654
  searchEverything: "Search hosts, tabs and actions",
50617
50655
  search: "Search",
50618
- hiddenCount: "{{count}} hidden",
50656
+ hiddenCount_one: "{{count}} hidden",
50657
+ hiddenCount_other: "{{count}} hidden",
50619
50658
  showInRail: "Show in sidebar",
50620
50659
  moveUp: "Move up",
50621
50660
  moveDown: "Move down",
@@ -50679,7 +50718,8 @@ var en_default = {
50679
50718
  unsavedChangesDescription: "Your host changes have not been saved. Discard them?",
50680
50719
  keepEditing: "Keep editing",
50681
50720
  discardChanges: "Discard changes",
50682
- movedToFolder: 'Moved {{count}} host(s) to "{{folder}}"',
50721
+ movedToFolder_one: 'Moved {{count}} host to "{{folder}}"',
50722
+ movedToFolder_other: 'Moved {{count}} hosts to "{{folder}}"',
50683
50723
  editHostTooltip: "Edit host",
50684
50724
  behavior: "Behavior",
50685
50725
  scrollbackBuffer: "Scrollback Buffer",
@@ -50880,7 +50920,8 @@ var en_default = {
50880
50920
  collapseSubHosts: "Collapse sub-hosts",
50881
50921
  expandSubHosts: "Expand sub-hosts",
50882
50922
  cannotNestUnderDescendant: "Can't nest a host under its own sub-host",
50883
- movedToParent: 'Moved {{count}} host(s) under "{{parent}}"',
50923
+ movedToParent_one: 'Moved {{count}} host under "{{parent}}"',
50924
+ movedToParent_other: 'Moved {{count}} hosts under "{{parent}}"',
50884
50925
  newFolder: "New folder",
50885
50926
  createFolderTitle: "Create folder",
50886
50927
  editFolderTitle: "Edit folder",
@@ -50908,7 +50949,8 @@ var en_default = {
50908
50949
  folderSaved: "Folder saved",
50909
50950
  failedToSaveFolder: "Failed to save folder",
50910
50951
  folderDeleted: 'Deleted folder "{{name}}"',
50911
- deleteFolderConfirm: 'Delete "{{name}}" and its {{count}} host(s)? This cannot be undone.',
50952
+ deleteFolderConfirm_one: 'Delete "{{name}}" and its {{count}} host? This cannot be undone.',
50953
+ deleteFolderConfirm_other: 'Delete "{{name}}" and its {{count}} hosts? This cannot be undone.',
50912
50954
  failedToMoveHosts: "Failed to move hosts",
50913
50955
  failedToReorder: "Failed to reorder",
50914
50956
  expandAll: "Expand all folders",
@@ -50976,7 +51018,8 @@ var en_default = {
50976
51018
  copyLink: "Copy Link",
50977
51019
  deleteCredentialConfirm: 'Delete credential "{{name}}"?',
50978
51020
  deletedCredential: "Deleted {{name}}",
50979
- deleteHostsConfirm: "Delete {{count}} host{{plural}}? This cannot be undone.",
51021
+ deleteHostsConfirm_one: "Delete {{count}} host? This cannot be undone.",
51022
+ deleteHostsConfirm_other: "Delete {{count}} hosts? This cannot be undone.",
50980
51023
  movedToRoot: "Moved to root",
50981
51024
  addTagsPlaceholder: "Add tags...",
50982
51025
  authDetails: "Authentication Details",
@@ -51035,7 +51078,8 @@ var en_default = {
51035
51078
  groupFeatureFlags: "Plugin settings",
51036
51079
  groupAdvanced: "Advanced config",
51037
51080
  preview: "Preview",
51038
- moreHosts: "... {{count}} more hosts",
51081
+ moreHosts_one: "... {{count}} more host",
51082
+ moreHosts_other: "... {{count}} more hosts",
51039
51083
  summary: "{{selected}} of {{total}} hosts",
51040
51084
  credentialsIncluded: "credentials included",
51041
51085
  credentialsExcluded: "credentials excluded",
@@ -51048,16 +51092,20 @@ var en_default = {
51048
51092
  sampleDownloaded: "Sample file downloaded",
51049
51093
  failedToDeleteCredential2: "Failed to delete credential",
51050
51094
  noFolderOption: "(No folder)",
51051
- nSelected: "{{count}} selected",
51095
+ nSelected_one: "{{count}} selected",
51096
+ nSelected_other: "{{count}} selected",
51052
51097
  featuresMenu: "Plugins",
51053
51098
  moveMenu: "Move",
51054
51099
  connectSelected: "Connect",
51055
51100
  cancelSelection: "Cancel",
51056
- deletedCount: "Deleted {{count}} hosts",
51057
- failedToDeleteCount: "Failed to delete {{count}} hosts",
51101
+ deletedCount_one: "Deleted {{count}} host",
51102
+ deletedCount_other: "Deleted {{count}} hosts",
51103
+ failedToDeleteCount_one: "Failed to delete {{count}} host",
51104
+ failedToDeleteCount_other: "Failed to delete {{count}} hosts",
51058
51105
  duplicatedHost: 'Duplicated "{{name}}"',
51059
51106
  failedToDuplicateHost: "Failed to duplicate host",
51060
- updatedCount: "Updated {{count}} hosts",
51107
+ updatedCount_one: "Updated {{count}} host",
51108
+ updatedCount_other: "Updated {{count}} hosts",
51061
51109
  friendlyNameLabel: "Friendly Name",
51062
51110
  descriptionLabel: "Description",
51063
51111
  loadingHosts: "Loading hosts...",
@@ -51097,7 +51145,8 @@ var en_default = {
51097
51145
  shareHostTitle: "Share: {{name}}",
51098
51146
  shareFolder: "Share Folder",
51099
51147
  shareFolderTitle: "Share folder: {{name}}",
51100
- folderSharedSuccessfully: "Shared {{count}} host(s) in folder",
51148
+ folderSharedSuccessfully_one: "Shared {{count}} host in folder",
51149
+ folderSharedSuccessfully_other: "Shared {{count}} hosts in folder",
51101
51150
  failedToShareFolder: "Failed to share folder",
51102
51151
  sharing: {
51103
51152
  loadError: "Failed to load sharing data. Please try again.",
@@ -51256,7 +51305,8 @@ var en_default = {
51256
51305
  unsplit: "Unsplit",
51257
51306
  layouts: "Layouts",
51258
51307
  applyLayout: "Change layout",
51259
- maxPanes: "A split can hold up to {{count}} panes",
51308
+ maxPanes_one: "A split can hold up to {{count}} pane",
51309
+ maxPanes_other: "A split can hold up to {{count}} panes",
51260
51310
  dropSplit: "Drop to split",
51261
51311
  dropHere: "Drop to show here",
51262
51312
  paneActions: "Pane actions",
@@ -51414,7 +51464,7 @@ var en_default = {
51414
51464
  sessionExpiredLogin: "Session expired. Please log in again."
51415
51465
  },
51416
51466
  messages: {
51417
- registrationDisabled: "New account registration is currently disabled by an admin. Please log in or contact an administrator.",
51467
+ registrationDisabled: "You have no Termix account yet. Ask an admin to turn on Auto-create external accounts.",
51418
51468
  userNotAllowed: "Your account is not authorized to register. Please contact an administrator.",
51419
51469
  databaseConnectionFailed: "Failed to connect to the database server",
51420
51470
  embeddedServerPortInUse: "Port {{port}} is already in use by another program. This is usually a Termix Docker container or a leftover Termix process from a previous session. Close it, then restart Termix.",
@@ -51553,7 +51603,7 @@ var en_default = {
51553
51603
  allowPasswordLogin: "Allow Password Login",
51554
51604
  allowPasswordLoginDesc: "Username/password login",
51555
51605
  externalAutoProvision: "Auto-create external accounts",
51556
- externalAutoProvisionDesc: "Create an account the first time someone signs in through an external login such as SSO or LDAP, even when registration is off",
51606
+ externalAutoProvisionDesc: "Create an account the first time someone signs in through an external login such as SSO or LDAP. When off, only people who already have an account can sign in that way",
51557
51607
  secondFactorAfterExternalLogin: "Ask for a second factor after external logins (SSO, GitHub, Google, LDAP)",
51558
51608
  secondFactorAfterExternalLoginDesc: "Off, an enrolled second factor is only asked for after password and other local logins, same as before. On, it is asked for after every login method, including SSO and LDAP.",
51559
51609
  allowPasswordReset: "Allow Password Reset",
@@ -51572,7 +51622,8 @@ var en_default = {
51572
51622
  statusCheck: "Status Check",
51573
51623
  sec: "sec",
51574
51624
  logLevel: "Log Level",
51575
- usersCount: "{{count}} users",
51625
+ usersCount_one: "{{count}} user",
51626
+ usersCount_other: "{{count}} users",
51576
51627
  searchUsers: "Search users...",
51577
51628
  noUsers: "No users",
51578
51629
  noUsersMatch: "No users match your search",
@@ -51582,7 +51633,8 @@ var en_default = {
51582
51633
  roleName: "Name",
51583
51634
  roleDisplayName: "Display Name",
51584
51635
  roleDescription: "Description",
51585
- rolesCount: "{{count}} roles",
51636
+ rolesCount_one: "{{count}} role",
51637
+ rolesCount_other: "{{count}} roles",
51586
51638
  createRole: "Create",
51587
51639
  creating: "Creating...",
51588
51640
  exportDatabase: "Export Database",
@@ -51596,7 +51648,8 @@ var en_default = {
51596
51648
  changeFile: "Change",
51597
51649
  import: "Import",
51598
51650
  importing: "Importing...",
51599
- apiKeysCount: "{{count}} keys",
51651
+ apiKeysCount_one: "{{count}} key",
51652
+ apiKeysCount_other: "{{count}} keys",
51600
51653
  apiKeysDocsLink: "View docs",
51601
51654
  apiKeysCliHint: "Use an API key with the Termix CLI to manage servers from your terminal.",
51602
51655
  apiKeysCliLink: "View CLI docs",
@@ -51618,7 +51671,8 @@ var en_default = {
51618
51671
  systemBadge: "SYS",
51619
51672
  customBadge: "CUSTOM",
51620
51673
  youBadge: "YOU",
51621
- sessionsActive: "{{count}} active",
51674
+ sessionsActive_one: "{{count}} active",
51675
+ sessionsActive_other: "{{count}} active",
51622
51676
  sessionActive: "Active: {{time}}",
51623
51677
  sessionExpires: "Exp: {{time}}",
51624
51678
  revokeAll: "All",
@@ -51727,14 +51781,16 @@ var en_default = {
51727
51781
  exportUserDataDesc: "Download this user's hosts, credentials and file manager data as JSON. Secrets are decrypted.",
51728
51782
  exportUserDataSuccess: "User data exported",
51729
51783
  exportUserDataFailed: "Failed to export user data",
51730
- hostsCount: "{{count}} hosts",
51784
+ hostsCount_one: "{{count}} host",
51785
+ hostsCount_other: "{{count}} hosts",
51731
51786
  addHostForUser: "Add Host",
51732
51787
  noHostsForUser: "This user has no hosts",
51733
51788
  connectToHost: "Connect",
51734
51789
  deleteHostConfirm: 'Delete host "{{name}}" belonging to {{username}}?',
51735
51790
  hostDeletedSuccess: "Host deleted",
51736
51791
  hostDeleteFailed: "Failed to delete host",
51737
- credentialsCount: "{{count}} credentials",
51792
+ credentialsCount_one: "{{count}} credential",
51793
+ credentialsCount_other: "{{count}} credentials",
51738
51794
  addCredentialForUser: "Add Credential",
51739
51795
  noCredentialsForUser: "This user has no credentials",
51740
51796
  deleteCredentialConfirm: 'Delete credential "{{name}}" belonging to {{username}}?',
@@ -51763,7 +51819,8 @@ var en_default = {
51763
51819
  importError: "Database import failed",
51764
51820
  sectionHostDefaults: "Host Defaults",
51765
51821
  rolePermissions: {
51766
- count: "{{count}} permissions",
51822
+ count_one: "{{count}} permission",
51823
+ count_other: "{{count}} permissions",
51767
51824
  editAction: "Edit permissions",
51768
51825
  loadError: "Failed to load the permissions catalog",
51769
51826
  saved: "Role permissions saved",
@@ -51982,7 +52039,8 @@ var en_default = {
51982
52039
  apiKeyCreatedWarning: "Key created - copy it now, it won't be shown again.",
51983
52040
  copyApiKey: "Copy API key",
51984
52041
  copiedToClipboard: "Copied to clipboard",
51985
- apiKeyCount: "{{count}} keys",
52042
+ apiKeyCount_one: "{{count}} key",
52043
+ apiKeyCount_other: "{{count}} keys",
51986
52044
  newKey: "New Key",
51987
52045
  noApiKeys: "No API keys yet.",
51988
52046
  apiKeyActive: "Active",
@@ -52183,25 +52241,42 @@ var en_default = {
52183
52241
  tabs: {
52184
52242
  installed: "Installed",
52185
52243
  browse: "Browse",
52186
- updates: "Updates"
52244
+ updates: "Updates",
52245
+ registries: "Registries"
52187
52246
  },
52188
52247
  status: {
52189
52248
  summary: "{{installed}} installed, {{running}} running",
52190
52249
  running: "Running",
52191
52250
  disabled: "Disabled",
52192
52251
  failed: "Stopped unexpectedly",
52193
- blocked: "Waiting on another plugin"
52252
+ blocked: "Waiting on another plugin",
52253
+ server: "Runs on your server"
52194
52254
  },
52195
52255
  groups: {
52196
52256
  running: "Running",
52197
- notRunning: "Not running"
52257
+ notRunning: "Not running",
52258
+ onServer: "On your server"
52198
52259
  },
52260
+ runsOnServerHint: "This plugin only runs on your server, so it stays off in the desktop app. It still works there.",
52199
52261
  sort: {
52200
52262
  popular: "Most popular",
52201
52263
  name: "Name",
52202
52264
  updated: "Recently updated",
52203
52265
  category: "Category"
52204
52266
  },
52267
+ columns: {
52268
+ title: "Columns",
52269
+ auto: "Auto",
52270
+ count: "{{count}} wide"
52271
+ },
52272
+ table: {
52273
+ name: "Name",
52274
+ description: "Description",
52275
+ version: "Version",
52276
+ status: "Status",
52277
+ category: "Category",
52278
+ installs: "Installs"
52279
+ },
52205
52280
  risk: {
52206
52281
  critical: "Critical",
52207
52282
  high: "High risk",
@@ -52352,8 +52427,44 @@ var en_default = {
52352
52427
  noneInstalled: "No plugins installed yet. Browse to add some.",
52353
52428
  nothingHere: "Nothing here.",
52354
52429
  nothingHereHint: "Try another category or search.",
52355
- communitySoon: "Community plugins are coming in a later update. Plugin authors can already submit theirs to the community registry.",
52356
52430
  communitySubmit: "How to submit",
52431
+ registries: {
52432
+ intro: "Registries are lists of plugins you can install. The official one is always on. You can turn on the community registry or add your own.",
52433
+ hostYourOwn: "Host your own registry",
52434
+ add: "Add registry",
52435
+ addTitle: "Add a registry",
52436
+ addHint: "Paste the link to the registry's index.json. Termix reads it and shows the key it signs plugins with. Only add registries from people you trust.",
52437
+ urlLabel: "Index URL",
52438
+ check: "Check",
52439
+ addConfirm: "Trust and add",
52440
+ added: "Added {{name}}",
52441
+ customWarning: "Plugins from this registry are not reviewed by the Termix team. Only the owner of the registry decides what is in it. Every download must be signed by the key above.",
52442
+ keyFingerprint: "Key {{keyId}}",
52443
+ pluginCount_one: "{{count}} plugin",
52444
+ pluginCount_other: "{{count}} plugins",
52445
+ officialName: "Official",
52446
+ communityName: "Community",
52447
+ alwaysOn: "Always on",
52448
+ communityHint: "Plugins made by other people. Each version is checked by a person and by automated checks before it is listed.",
52449
+ communityConfirmTitle: "Turn on community plugins?",
52450
+ communityConfirmBody: "Community plugins are made by other people, not the Termix team. Every version is checked by a person and by automated checks before it is listed, but mistakes can still get through. Only install plugins you trust and check what each one asks for.",
52451
+ communityConfirm: "Turn on",
52452
+ communityBadge: "Community",
52453
+ communityBadgeHint: "From the community registry. Made by other people and reviewed before it was listed.",
52454
+ customBadge: "Custom",
52455
+ customBadgeHint: "From {{name}}, a registry an admin added. Not reviewed by the Termix team.",
52456
+ remove: "Remove",
52457
+ removeTitle: "Remove {{name}}?",
52458
+ removeBody: "Its plugins will no longer show in Browse. You can add it again later.",
52459
+ removed: "Removed {{name}}",
52460
+ inUse: "Uninstall the plugins from {{name}} first: {{list}}",
52461
+ changeFailed: "Could not change the registry: {{error}}",
52462
+ loadFailed: "Could not load registries: {{error}}",
52463
+ unreachable: "Could not read it: {{error}}",
52464
+ filter: "Registry",
52465
+ allRegistries: "All registries",
52466
+ browseHint: "Turn on community plugins or add your own registry in the Registries tab."
52467
+ },
52357
52468
  upToDate: "Everything is up to date.",
52358
52469
  lastChecked: "Last checked {{time}}",
52359
52470
  updatesReady_one: "{{count}} update ready.",
@@ -52555,7 +52666,12 @@ var en_default = {
52555
52666
  dashboardServiceLinks: "Service links",
52556
52667
  homepageItems: "Homepage items",
52557
52668
  networkTopology: "Network map",
52558
- workspaces: "Workspaces"
52669
+ workspaces: "Workspaces",
52670
+ hostDefaults: "Host defaults",
52671
+ hostDefaultsAdmin: "Server host defaults",
52672
+ aiProviders: "AI providers",
52673
+ homepageLayouts: "Homepage layouts",
52674
+ accountProfile: "Account profile"
52559
52675
  },
52560
52676
  proxy: {
52561
52677
  title: "Reverse proxy",
@@ -52602,9 +52718,11 @@ var en_default = {
52602
52718
  continue: "Continue",
52603
52719
  back: "Back",
52604
52720
  mergeTitle: "Add it to my account",
52605
- mergeBody: "The {{count}} items on this device are added to your account. Items your account already has stay as they are on the server.",
52721
+ mergeBody_one: "The item on this device is added to your account. Items your account already has stay as they are on the server.",
52722
+ mergeBody_other: "The {{count}} items on this device are added to your account. Items your account already has stay as they are on the server.",
52606
52723
  replaceTitle: "Replace it with my account",
52607
- replaceBody: "The {{count}} items on this device are removed, and this device takes everything from your account. Hosts kept on this device only stay.",
52724
+ replaceBody_one: "The item on this device is removed, and this device takes everything from your account. Hosts kept on this device only stay.",
52725
+ replaceBody_other: "The {{count}} items on this device are removed, and this device takes everything from your account. Hosts kept on this device only stay.",
52608
52726
  link: "Link",
52609
52727
  linking: "Linking and running the first sync...",
52610
52728
  linked: "Linked. Your data is syncing now.",
@@ -52704,46 +52822,131 @@ var en_default = {
52704
52822
  pickCredential: "Pick a credential to edit",
52705
52823
  pickDefaults: "Pick a level of defaults to edit",
52706
52824
  pickHint: "Everything about a connection lives here, grouped so you can find it."
52825
+ },
52826
+ rbac: {
52827
+ roles: {
52828
+ admin: "Admin",
52829
+ user: "User"
52830
+ }
52707
52831
  }
52708
52832
  };
52709
52833
 
52834
+ // src/ui/locales/languages.json
52835
+ var languages_default = [
52836
+ { code: "af", file: "af_ZA", name: "Afrikaans", label: "Afrikaans" },
52837
+ { code: "ar", file: "ar_SA", name: "Arabic", label: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629" },
52838
+ { code: "bn", file: "bn_BD", name: "Bengali", label: "\u09AC\u09BE\u0982\u09B2\u09BE" },
52839
+ { code: "bg", file: "bg_BG", name: "Bulgarian", label: "\u0411\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438" },
52840
+ { code: "ca", file: "ca_ES", name: "Catalan", label: "Catal\xE0" },
52841
+ {
52842
+ code: "zh-CN",
52843
+ file: "zh_CN",
52844
+ name: "Simplified Chinese",
52845
+ label: "\u4E2D\u6587 (\u7B80\u4F53)"
52846
+ },
52847
+ {
52848
+ code: "zh-TW",
52849
+ file: "zh_TW",
52850
+ name: "Traditional Chinese (Taiwan)",
52851
+ label: "\u4E2D\u6587 (\u7E41\u9AD4)"
52852
+ },
52853
+ { code: "hr", file: "hr_HR", name: "Croatian", label: "Hrvatski" },
52854
+ { code: "cs", file: "cs_CZ", name: "Czech", label: "\u010Ce\u0161tina" },
52855
+ { code: "da", file: "da_DK", name: "Danish", label: "Dansk" },
52856
+ { code: "nl", file: "nl_NL", name: "Dutch", label: "Nederlands" },
52857
+ { code: "et", file: "et_EE", name: "Estonian", label: "Eesti" },
52858
+ { code: "fi", file: "fi_FI", name: "Finnish", label: "Suomi" },
52859
+ { code: "fr", file: "fr_FR", name: "French", label: "Fran\xE7ais" },
52860
+ { code: "de", file: "de_DE", name: "German", label: "Deutsch" },
52861
+ { code: "el", file: "el_GR", name: "Greek", label: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC" },
52862
+ { code: "he", file: "he_IL", name: "Hebrew", label: "\u05E2\u05D1\u05E8\u05D9\u05EA" },
52863
+ { code: "hi", file: "hi_IN", name: "Hindi", label: "\u0939\u093F\u0928\u094D\u0926\u0940" },
52864
+ { code: "hu", file: "hu_HU", name: "Hungarian", label: "Magyar" },
52865
+ {
52866
+ code: "id",
52867
+ file: "id_ID",
52868
+ name: "Indonesian",
52869
+ label: "Indonesia"
52870
+ },
52871
+ { code: "it", file: "it_IT", name: "Italian", label: "Italiano" },
52872
+ { code: "ja", file: "ja_JP", name: "Japanese", label: "\u65E5\u672C\u8A9E" },
52873
+ { code: "ko", file: "ko_KR", name: "Korean", label: "\uD55C\uAD6D\uC5B4" },
52874
+ { code: "lv", file: "lv_LV", name: "Latvian", label: "Latvie\u0161u" },
52875
+ {
52876
+ code: "lt",
52877
+ file: "lt_LT",
52878
+ name: "Lithuanian",
52879
+ label: "Lietuvi\u0173"
52880
+ },
52881
+ { code: "ms", file: "ms_MY", name: "Malay", label: "Bahasa Melayu" },
52882
+ {
52883
+ code: "no",
52884
+ file: "no_NO",
52885
+ name: "Norwegian Bokm\xE5l",
52886
+ label: "Norsk"
52887
+ },
52888
+ { code: "pl", file: "pl_PL", name: "Polish", label: "Polski" },
52889
+ {
52890
+ code: "pt-PT",
52891
+ file: "pt_PT",
52892
+ name: "European Portuguese",
52893
+ label: "Portugu\xEAs (PT)"
52894
+ },
52895
+ {
52896
+ code: "pt-BR",
52897
+ file: "pt_BR",
52898
+ name: "Brazilian Portuguese",
52899
+ label: "Portugu\xEAs (BR)"
52900
+ },
52901
+ { code: "ro", file: "ro_RO", name: "Romanian", label: "Rom\xE2n\u0103" },
52902
+ { code: "ru", file: "ru_RU", name: "Russian", label: "\u0420\u0443\u0441\u0441\u043A\u0438\u0439" },
52903
+ {
52904
+ code: "sr",
52905
+ file: "sr_SP",
52906
+ name: "Serbian (Cyrillic script)",
52907
+ label: "\u0421\u0440\u043F\u0441\u043A\u0438"
52908
+ },
52909
+ { code: "sk", file: "sk_SK", name: "Slovak", label: "Sloven\u010Dina" },
52910
+ {
52911
+ code: "sl",
52912
+ file: "sl_SI",
52913
+ name: "Slovenian",
52914
+ label: "Sloven\u0161\u010Dina"
52915
+ },
52916
+ {
52917
+ code: "es-ES",
52918
+ file: "es_ES",
52919
+ name: "Spanish (Spain)",
52920
+ label: "Espa\xF1ol"
52921
+ },
52922
+ { code: "sv-SE", file: "sv_SE", name: "Swedish", label: "Svenska" },
52923
+ { code: "th", file: "th_TH", name: "Thai", label: "\u0E44\u0E17\u0E22" },
52924
+ { code: "tr", file: "tr_TR", name: "Turkish", label: "T\xFCrk\xE7e" },
52925
+ {
52926
+ code: "uk",
52927
+ file: "uk_UA",
52928
+ name: "Ukrainian",
52929
+ label: "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"
52930
+ },
52931
+ {
52932
+ code: "vi",
52933
+ file: "vi_VN",
52934
+ name: "Vietnamese",
52935
+ label: "Ti\u1EBFng Vi\u1EC7t"
52936
+ }
52937
+ ];
52938
+
52939
+ // src/ui/i18n/languages.ts
52940
+ var TRANSLATED_LANGUAGES = languages_default;
52941
+ var LANGUAGES = [
52942
+ { code: "en", label: "English" },
52943
+ ...TRANSLATED_LANGUAGES.map(({ code, label }) => ({ code, label }))
52944
+ ];
52945
+
52710
52946
  // src/ui/i18n/i18n.ts
52711
- var LOCALE_FILES = {
52712
- af: "af_ZA",
52713
- ar: "ar_SA",
52714
- bn: "bn_BD",
52715
- bg: "bg_BG",
52716
- ca: "ca_ES",
52717
- cs: "cs_CZ",
52718
- da: "da_DK",
52719
- de: "de_DE",
52720
- el: "el_GR",
52721
- "es-ES": "es_ES",
52722
- fi: "fi_FI",
52723
- fr: "fr_FR",
52724
- he: "he_IL",
52725
- hi: "hi_IN",
52726
- hu: "hu_HU",
52727
- id: "id_ID",
52728
- it: "it_IT",
52729
- ja: "ja_JP",
52730
- ko: "ko_KR",
52731
- nl: "nl_NL",
52732
- no: "no_NO",
52733
- pl: "pl_PL",
52734
- "pt-PT": "pt_PT",
52735
- "pt-BR": "pt_BR",
52736
- ro: "ro_RO",
52737
- ru: "ru_RU",
52738
- sr: "sr_SP",
52739
- "sv-SE": "sv_SE",
52740
- th: "th_TH",
52741
- tr: "tr_TR",
52742
- uk: "uk_UA",
52743
- vi: "vi_VN",
52744
- "zh-CN": "zh_CN",
52745
- "zh-TW": "zh_TW"
52746
- };
52947
+ var LOCALE_FILES = Object.fromEntries(
52948
+ TRANSLATED_LANGUAGES.map(({ code, file }) => [code, file])
52949
+ );
52747
52950
  var translatedFiles = __termixNoGlob(
52748
52951
  "../locales/translated/*.json"
52749
52952
  );
@@ -52771,8 +52974,16 @@ function normalizeLanguageCode(language) {
52771
52974
  (supported) => supported.toLowerCase() === normalized.toLowerCase()
52772
52975
  );
52773
52976
  if (exactMatch) return exactMatch;
52774
- const baseLanguage = normalized.split("-")[0];
52775
- return supportedLngs.includes(baseLanguage) ? baseLanguage : "en";
52977
+ const baseLanguage = normalized.split("-")[0].toLowerCase();
52978
+ if (supportedLngs.includes(baseLanguage)) return baseLanguage;
52979
+ if (baseLanguage === "zh") {
52980
+ return /-(tw|hk|mo|hant)\b/i.test(normalized) ? "zh-TW" : "zh-CN";
52981
+ }
52982
+ if (baseLanguage === "nb" || baseLanguage === "nn") return "no";
52983
+ if (baseLanguage === "pt") return "pt-BR";
52984
+ return supportedLngs.find(
52985
+ (supported) => supported.toLowerCase().startsWith(`${baseLanguage}-`)
52986
+ ) ?? "en";
52776
52987
  }
52777
52988
  var localeBackend = {
52778
52989
  type: "backend",
@@ -53342,6 +53553,20 @@ function pluginApiFor(pluginId, origin, local) {
53342
53553
  }
53343
53554
  return client;
53344
53555
  }
53556
+ async function fetchSocketTicket() {
53557
+ const base = (authApi.defaults.baseURL ?? "").replace(/\/+$/, "");
53558
+ try {
53559
+ const response = await fetch(`${base}/users/ws-ticket`, {
53560
+ method: "POST",
53561
+ credentials: "include"
53562
+ });
53563
+ if (!response.ok) return null;
53564
+ const data = await response.json();
53565
+ return typeof data.ticket === "string" ? data.ticket : null;
53566
+ } catch {
53567
+ return null;
53568
+ }
53569
+ }
53345
53570
  async function pluginWsUrl(pluginId, path2, options2 = {}) {
53346
53571
  const suffix = path2.startsWith("/") ? path2 : `/${path2}`;
53347
53572
  const route = `/plugin-ws/${pluginId}${suffix}`;
@@ -53353,7 +53578,7 @@ async function pluginWsUrl(pluginId, path2, options2 = {}) {
53353
53578
  remotePath: route
53354
53579
  });
53355
53580
  }
53356
- const token = localStorage.getItem("jwt");
53581
+ const token = await fetchSocketTicket() ?? localStorage.getItem("jwt");
53357
53582
  const protocols2 = websocketAuthProtocols(token);
53358
53583
  const devProxy = !define_import_meta_env_default.VITE_API_HOST && (window.location.port === "3000" || window.location.port === "5173");
53359
53584
  const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws";
@@ -54900,6 +55125,7 @@ export {
54900
55125
  getSecondFactorUI,
54901
55126
  useSecondFactors,
54902
55127
  listSecondFactorUIs,
55128
+ LANGUAGES,
54903
55129
  setPluginLocaleResolver,
54904
55130
  normalizeLanguageCode,
54905
55131
  changeAppLanguage,
@@ -21,7 +21,7 @@ var inFlight = null;
21
21
  function load() {
22
22
  if (cache) return Promise.resolve(cache);
23
23
  if (inFlight) return inFlight;
24
- inFlight = import("./rbac-api-UJGGTQVA.js").then(({ getMyPermissions }) => getMyPermissions()).then((result) => {
24
+ inFlight = import("./rbac-api-5267EMX7.js").then(({ getMyPermissions }) => getMyPermissions()).then((result) => {
25
25
  cache = {
26
26
  permissions: result.permissions ?? [],
27
27
  isAdmin: !!result.isAdmin