@fluid-app/fluid-cli-portal 0.1.7 → 0.1.9

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/dist/index.d.mts CHANGED
@@ -106,6 +106,13 @@ interface DestroyOptions {
106
106
  readonly yes?: boolean;
107
107
  }
108
108
  /**
109
+ * Options for the widget create command
110
+ */
111
+ interface WidgetCreateOptions {
112
+ /** Category for palette grouping */
113
+ readonly category?: string;
114
+ }
115
+ /**
109
116
  * Template variables for Handlebars processing
110
117
  */
111
118
  interface TemplateVariables {
@@ -236,6 +243,21 @@ declare const createCommand: Command;
236
243
  //#region src/commands/destroy.d.ts
237
244
  declare const destroyCommand: Command;
238
245
  //#endregion
246
+ //#region src/commands/pull.d.ts
247
+ declare const pullCommand: Command;
248
+ //#endregion
249
+ //#region src/commands/push.d.ts
250
+ declare const pushCommand: Command;
251
+ //#endregion
252
+ //#region src/commands/widget-create.d.ts
253
+ declare const widgetCommand: Command;
254
+ //#endregion
255
+ //#region src/commands/version.d.ts
256
+ declare const versionCommand: Command;
257
+ //#endregion
258
+ //#region src/commands/doctor.d.ts
259
+ declare const doctorCommand: Command;
260
+ //#endregion
239
261
  //#region src/utils/cloud-run.d.ts
240
262
  /**
241
263
  * Cloud Run error codes and default messages
@@ -569,8 +591,592 @@ declare function createDatabaseToken(config: TursoConfig, dbName: string): Promi
569
591
  */
570
592
  declare function provisionDatabase(config: TursoConfig, projectName: string, location?: string, callbacks?: TursoProvisionCallbacks): Promise<Result<TursoDatabase, TursoError>>;
571
593
  //#endregion
594
+ //#region src/utils/mappings.d.ts
595
+ /** Definition metadata stored at the top level of the mappings file. */
596
+ interface DefinitionMapping {
597
+ readonly name: string;
598
+ readonly id: number;
599
+ }
600
+ /**
601
+ * Resource types that support slug-to-ID mappings.
602
+ * "countries" and "ranks" use display names as keys (not slugified).
603
+ */
604
+ type MappedResourceType = "screens" | "themes" | "navigations" | "profiles" | "countries" | "ranks";
605
+ /** Full mappings structure persisted to disk. */
606
+ interface PortalMappings {
607
+ readonly definition: DefinitionMapping;
608
+ readonly screens: Record<string, number>;
609
+ readonly themes: Record<string, number>;
610
+ readonly navigations: Record<string, number>;
611
+ readonly profiles: Record<string, number>;
612
+ readonly countries: Record<string, number>;
613
+ readonly ranks: Record<string, number>;
614
+ }
615
+ /**
616
+ * Read the mappings file from the `.portal-sync/` directory.
617
+ * Returns `null` if the file does not exist.
618
+ */
619
+ declare function readMappings(portalSyncDir: string): Promise<PortalMappings | null>;
620
+ /**
621
+ * Write the mappings file to the `.portal-sync/` directory.
622
+ * Creates the directory if it does not exist.
623
+ */
624
+ declare function writeMappings(portalSyncDir: string, mappings: PortalMappings): Promise<void>;
625
+ /**
626
+ * Derive a filesystem-safe slug from a resource name.
627
+ *
628
+ * - Lowercases the name
629
+ * - Replaces non-alphanumeric characters (except hyphens) with hyphens
630
+ * - Collapses consecutive hyphens
631
+ * - Trims leading/trailing hyphens
632
+ *
633
+ * If the derived slug collides with an existing slug in `existingSlugs`,
634
+ * a numeric suffix is appended (e.g., `home-2`, `home-3`).
635
+ */
636
+ declare function deriveSlug(name: string, existingSlugs?: ReadonlySet<string>): string;
637
+ /**
638
+ * Resolve a slug to its server-side ID.
639
+ * Returns `undefined` if the slug is not mapped.
640
+ */
641
+ declare function resolveSlugToId(mappings: PortalMappings, resourceType: MappedResourceType, slug: string): number | undefined;
642
+ /**
643
+ * Resolve a server-side ID back to its slug.
644
+ * Returns `undefined` if no slug maps to the given ID.
645
+ */
646
+ declare function resolveIdToSlug(mappings: PortalMappings, resourceType: MappedResourceType, id: number): string | undefined;
647
+ /**
648
+ * Add or update a mapping entry for a given resource type.
649
+ * Returns a new `PortalMappings` object (immutable update).
650
+ */
651
+ declare function updateMapping(mappings: PortalMappings, resourceType: MappedResourceType, slug: string, id: number): PortalMappings;
652
+ /**
653
+ * Remove a mapping entry for a given resource type.
654
+ * Returns a new `PortalMappings` object (immutable update).
655
+ * If the slug does not exist, the original mappings are returned unchanged.
656
+ */
657
+ declare function removeMapping(mappings: PortalMappings, resourceType: MappedResourceType, slug: string): PortalMappings;
658
+ //#endregion
659
+ //#region src/utils/snapshot.d.ts
660
+ /** SHA-256 hex digest of a file's contents. */
661
+ type FileHash = string;
662
+ /** Map of relative file paths to their content hashes. */
663
+ type FileHashMap = Record<string, FileHash>;
664
+ /** Snapshot structure persisted to `.portal-sync/snapshot.json`. */
665
+ interface Snapshot {
666
+ /** Human-readable name of the portal definition. */
667
+ readonly definition: string;
668
+ /** Server-side ID of the portal definition. */
669
+ readonly definition_id: number;
670
+ /** ISO 8601 timestamp of when the snapshot was created. */
671
+ readonly pulled_at: string;
672
+ /** Map of relative file paths → SHA-256 hashes. */
673
+ readonly files: FileHashMap;
674
+ }
675
+ /** Result of diffing current files against a snapshot. */
676
+ interface SnapshotDiff {
677
+ /** Files that exist on disk but not in the snapshot. */
678
+ readonly new: readonly string[];
679
+ /** Files that exist in both but have different hashes. */
680
+ readonly changed: readonly string[];
681
+ /** Files that exist in the snapshot but not on disk. */
682
+ readonly deleted: readonly string[];
683
+ }
684
+ /**
685
+ * Compute the SHA-256 hash of a file's contents.
686
+ * Returns the hex-encoded digest.
687
+ */
688
+ declare function computeFileHash(filePath: string): Promise<FileHash>;
689
+ /**
690
+ * Read the snapshot file from the `.portal-sync/` directory.
691
+ * Returns `null` if the file does not exist.
692
+ */
693
+ declare function readSnapshot(portalSyncDir: string): Promise<Snapshot | null>;
694
+ /**
695
+ * Write the snapshot file to the `.portal-sync/` directory.
696
+ * Creates the directory if it does not exist.
697
+ */
698
+ declare function writeSnapshot(portalSyncDir: string, snapshot: Snapshot): Promise<void>;
699
+ /**
700
+ * Compare the current portal directory contents against a snapshot.
701
+ *
702
+ * Returns lists of new, changed, and deleted files (relative paths).
703
+ */
704
+ declare function diffAgainstSnapshot(portalDir: string, snapshot: Snapshot): Promise<SnapshotDiff>;
705
+ /**
706
+ * Build a fresh snapshot from the current portal directory contents.
707
+ *
708
+ * Hashes every file in `portalDir` (excluding `.portal-sync/`)
709
+ * and records the definition metadata.
710
+ */
711
+ declare function buildSnapshot(portalDir: string, definitionName: string, definitionId: number): Promise<Snapshot>;
712
+ //#endregion
713
+ //#region ../../api-clients/fluidos/src/generated/fluid_os.d.ts
714
+ interface components {
715
+ schemas: {
716
+ ResponseMeta: {
717
+ /** @example 123e4567-e89b-12d3-a456-426614174000 */request_id?: string; /** @example 2021-01-01T00:00:00Z */
718
+ timestamp?: string;
719
+ }; /** @description Pagination metadata for list responses */
720
+ PaginationMeta: {
721
+ /**
722
+ * @description Total number of items across all pages
723
+ * @example 42
724
+ */
725
+ total_count?: number;
726
+ /**
727
+ * @description Total number of pages
728
+ * @example 5
729
+ */
730
+ total_pages?: number;
731
+ /**
732
+ * @description Current page number
733
+ * @example 1
734
+ */
735
+ current_page?: number;
736
+ /**
737
+ * @description Unique identifier for the request
738
+ * @example 123e4567-e89b-12d3-a456-426614174000
739
+ */
740
+ request_id?: string;
741
+ /**
742
+ * @description Timestamp of the response
743
+ * @example 2021-01-01T00:00:00Z
744
+ */
745
+ timestamp?: string;
746
+ } & {
747
+ [key: string]: unknown;
748
+ }; /** FluidOS::NavigationItem */
749
+ FluidOSNavigationItem: {
750
+ id: number;
751
+ icon?: string | null;
752
+ label?: string | null;
753
+ parent_id?: number | null;
754
+ position?: number | null;
755
+ screen_id?: number | null;
756
+ slug?: string | null; /** @enum {string} */
757
+ source: "user" | "system" | "code";
758
+ children: components["schemas"]["FluidOSNavigationItem"][];
759
+ }; /** @description Permission configuration object defining access rights. Empty arrays mean 'allow all' for that dimension. */
760
+ FluidOSPermissions: {
761
+ /** @description Array of rank IDs that can access this profile. Empty array allows all ranks. */ranks?: number[]; /** @description Array of roles that can access this profile. Empty array allows all roles. */
762
+ roles?: ("admin" | "rep")[]; /** @description Array of platforms that can access this profile. Empty array allows all platforms. */
763
+ platform?: ("mobile" | "browser")[]; /** @description Array of country IDs that can access this profile. Empty array allows all countries. */
764
+ countries?: number[];
765
+ }; /** @description Standard error response */
766
+ Error: {
767
+ /**
768
+ * @description Simple error message (used for 404 and other simple errors)
769
+ * @example Resource not found
770
+ * @example Unauthorized
771
+ */
772
+ error?: string;
773
+ /**
774
+ * @description Error message for validation errors
775
+ * @example Invalid parameters
776
+ */
777
+ error_message?: string;
778
+ /**
779
+ * @description Detailed validation errors by field
780
+ * @example {
781
+ * "definition": {
782
+ * "name": [
783
+ * "must be filled"
784
+ * ]
785
+ * }
786
+ * }
787
+ */
788
+ errors?: {
789
+ [key: string]: unknown;
790
+ };
791
+ meta?: components["schemas"]["ResponseMeta"];
792
+ } & {
793
+ [key: string]: unknown;
794
+ }; /** @description A profile optimized for rendering, with permissions stripped. Contains only the data needed to render the app. */
795
+ FluidOSRendererProfile: {
796
+ /** @description Unique identifier for the profile */id?: number; /** @description Display name of the profile */
797
+ name?: string; /** @description Whether this is the default profile for its platform */
798
+ default?: boolean; /** @description Navigation configuration for this profile */
799
+ navigation?: {
800
+ /** @description Tree structure of navigation items */navigation_tree?: components["schemas"]["FluidOSNavigationItem"][];
801
+ }; /** @description Array of theme IDs associated with this profile */
802
+ themes?: number[];
803
+ }; /** @description The Fluid OS manifest optimized for rendering. Contains a single matched profile based on platform, country, rank, and role parameters, along with filtered screens and themes. */
804
+ FluidOSRendererManifest: {
805
+ /** @description Name of the Fluid OS app */name?: string; /** @description ID of the Fluid OS definition */
806
+ definition_id?: number; /** @description Version number of the published manifest */
807
+ published_version?: number;
808
+ /**
809
+ * Format: date-time
810
+ * @description When this version was published
811
+ */
812
+ published_at?: string; /** @description Navigation configurations for the app */
813
+ navigations?: components["schemas"]["FluidOSNavigationBasic"][]; /** @description The best matching profile for the given parameters */
814
+ profile?: components["schemas"]["FluidOSRendererProfile"]; /** @description Screens associated with the matched profile's navigation */
815
+ screens?: components["schemas"]["FluidOSScreen"][]; /** @description Themes associated with the matched profile */
816
+ themes?: components["schemas"]["FluidOSTheme"][];
817
+ }; /** FluidOS::Navigation */
818
+ FluidOSNavigationBasic: {
819
+ id: number;
820
+ name?: string | null;
821
+ definition_id: number; /** @enum {string} */
822
+ platform: "web" | "mobile";
823
+ }; /** FluidOS::Screen */
824
+ FluidOSScreen: {
825
+ id: number;
826
+ name?: string | null;
827
+ slug?: string | null;
828
+ definition_id: number;
829
+ component_tree?: Record<string, unknown> | null;
830
+ }; /** FluidOS::Theme */
831
+ FluidOSTheme: {
832
+ id: number;
833
+ config?: Record<string, unknown> | null;
834
+ active?: boolean | null;
835
+ name?: string | null;
836
+ definition_id: number;
837
+ }; /** FluidOS::Definition */
838
+ FluidOSDefinition: {
839
+ id: number;
840
+ name?: string | null;
841
+ active?: boolean | null;
842
+ profiles: components["schemas"]["FluidOSProfile"][];
843
+ screens: components["schemas"]["FluidOSScreenBasic"][];
844
+ navigations: components["schemas"]["FluidOSNavigationBasic"][];
845
+ themes: components["schemas"]["FluidOSTheme"][];
846
+ }; /** FluidOS::Definition */
847
+ FluidOSDefinitionBasic: {
848
+ id: number;
849
+ name?: string | null;
850
+ active?: boolean | null;
851
+ };
852
+ FluidOSDefinitionCreate: {
853
+ definition: {
854
+ name: string;
855
+ active?: boolean;
856
+ };
857
+ };
858
+ FluidOSDefinitionUpdate: {
859
+ definition: {
860
+ name?: string;
861
+ active?: boolean;
862
+ };
863
+ }; /** FluidOS::Screen */
864
+ FluidOSScreenBasic: {
865
+ id: number;
866
+ name?: string | null;
867
+ slug?: string | null;
868
+ definition_id: number;
869
+ };
870
+ FluidOSScreenCreate: {
871
+ screen: {
872
+ name: string;
873
+ slug: string;
874
+ component_tree?: null | Record<string, unknown>;
875
+ };
876
+ };
877
+ FluidOSScreenUpdate: {
878
+ screen?: unknown;
879
+ }; /** FluidOS::Profile */
880
+ FluidOSProfile: {
881
+ id: number;
882
+ name?: string | null;
883
+ default?: boolean | null;
884
+ permissions?: components["schemas"]["FluidOSPermissions"] | null;
885
+ definition_id: number;
886
+ navigation: components["schemas"]["FluidOSNavigationWithItems"];
887
+ mobile_navigation: components["schemas"]["FluidOSNavigationWithItems"];
888
+ themes: components["schemas"]["FluidOSTheme"][];
889
+ }; /** FluidOS::Profile */
890
+ FluidOSProfileWithScreens: {
891
+ id: number;
892
+ name?: string | null;
893
+ default?: boolean | null;
894
+ permissions?: components["schemas"]["FluidOSPermissions"] | null;
895
+ definition_id: number;
896
+ navigation: components["schemas"]["FluidOSNavigationWithItems"];
897
+ mobile_navigation: components["schemas"]["FluidOSNavigationWithItems"];
898
+ themes: components["schemas"]["FluidOSTheme"][];
899
+ screens: {
900
+ [key: string]: unknown;
901
+ }[];
902
+ };
903
+ FluidOSProfileCreate: {
904
+ profile: {
905
+ name: string;
906
+ default?: boolean; /** @description Mutually exclusive with navigation_attributes */
907
+ navigation_id?: number; /** @description Mutually exclusive with mobile_navigation_attributes */
908
+ mobile_navigation_id?: number; /** @description Mutually exclusive with navigation_id */
909
+ navigation_attributes?: {
910
+ name: string;
911
+ navigation_items_attributes?: {
912
+ screen_id?: number;
913
+ icon?: string;
914
+ label?: string;
915
+ position?: number;
916
+ parent_id?: number;
917
+ slug?: string; /** @enum {null|string} */
918
+ source?: "user" | "system" | "code" | null;
919
+ }[];
920
+ }; /** @description Mutually exclusive with mobile_navigation_id */
921
+ mobile_navigation_attributes?: {
922
+ name: string;
923
+ navigation_items_attributes?: {
924
+ screen_id?: number;
925
+ icon?: string;
926
+ label?: string;
927
+ position?: number;
928
+ parent_id?: number;
929
+ slug?: string; /** @enum {null|string} */
930
+ source?: "user" | "system" | "code" | null;
931
+ }[];
932
+ };
933
+ theme_ids?: number[];
934
+ permissions?: {
935
+ countries?: number[];
936
+ ranks?: number[];
937
+ roles?: string[];
938
+ platform?: string[];
939
+ };
940
+ };
941
+ };
942
+ FluidOSProfileUpdate: {
943
+ profile: {
944
+ name?: string;
945
+ default?: boolean;
946
+ navigation_id?: number;
947
+ mobile_navigation_id?: number;
948
+ theme_ids?: number[];
949
+ permissions?: {
950
+ countries?: number[];
951
+ ranks?: number[];
952
+ roles?: string[];
953
+ platform?: string[];
954
+ };
955
+ };
956
+ };
957
+ FluidOSThemeCreate: {
958
+ theme: {
959
+ name: string;
960
+ config: Record<string, unknown>;
961
+ active?: boolean;
962
+ };
963
+ };
964
+ FluidOSThemeUpdate: {
965
+ theme: {
966
+ name?: string;
967
+ active?: boolean;
968
+ config?: Record<string, unknown>;
969
+ };
970
+ }; /** FluidOS::Navigation */
971
+ FluidOSNavigation: {
972
+ id: number;
973
+ name?: string | null;
974
+ definition_id: number; /** @enum {string} */
975
+ platform: "web" | "mobile";
976
+ screens: {
977
+ id: number;
978
+ name?: string | null;
979
+ slug?: string | null;
980
+ definition_id: number;
981
+ component_tree?: Record<string, unknown> | null;
982
+ }[];
983
+ }; /** FluidOS::Navigation */
984
+ FluidOSNavigationWithItems: {
985
+ id: number;
986
+ name?: string | null;
987
+ definition_id: number; /** @enum {string} */
988
+ platform: "web" | "mobile";
989
+ navigation_items: components["schemas"]["FluidOSNavigationItem"][];
990
+ };
991
+ FluidOSNavigationCreate: {
992
+ navigation: {
993
+ name: string; /** @enum {string} */
994
+ platform: "web" | "mobile";
995
+ };
996
+ };
997
+ FluidOSNavigationUpdate: {
998
+ navigation: {
999
+ name?: string; /** @enum {string} */
1000
+ platform?: "web" | "mobile";
1001
+ };
1002
+ };
1003
+ FluidOSNavigationItemCreate: {
1004
+ navigation_item: {
1005
+ icon?: string;
1006
+ label: string;
1007
+ position: number;
1008
+ parent_id?: null | number;
1009
+ screen_id?: null | number;
1010
+ slug?: null | string; /** @enum {null|string} */
1011
+ source?: "user" | "system" | "code" | null;
1012
+ };
1013
+ };
1014
+ FluidOSNavigationItemUpdate: {
1015
+ navigation_item: {
1016
+ icon?: string;
1017
+ label?: string;
1018
+ position?: number;
1019
+ parent_id?: null | number;
1020
+ screen_id?: null | number;
1021
+ slug?: null | string; /** @enum {null|string} */
1022
+ source?: "user" | "system" | "code" | null;
1023
+ };
1024
+ }; /** FluidOS::Version */
1025
+ FluidOSVersion: {
1026
+ id: number;
1027
+ active?: boolean | null;
1028
+ manifest?: Record<string, unknown> | null; /** Format: date-time */
1029
+ published_at?: string | null;
1030
+ definition_id: number;
1031
+ };
1032
+ FluidOSVersionUpdate: {
1033
+ version: {
1034
+ active?: boolean;
1035
+ };
1036
+ };
1037
+ };
1038
+ responses: never;
1039
+ parameters: never;
1040
+ requestBodies: never;
1041
+ headers: never;
1042
+ pathItems: never;
1043
+ }
1044
+ //#endregion
1045
+ //#region src/utils/transform.d.ts
1046
+ type ApiScreen = components["schemas"]["FluidOSScreen"];
1047
+ type ApiTheme = components["schemas"]["FluidOSTheme"];
1048
+ type ApiNavigationBasic = components["schemas"]["FluidOSNavigationBasic"];
1049
+ type ApiNavigationItem = components["schemas"]["FluidOSNavigationItem"];
1050
+ type ApiProfile = components["schemas"]["FluidOSProfile"];
1051
+ interface LocalScreen {
1052
+ readonly name: string;
1053
+ readonly component_tree: Record<string, unknown>[];
1054
+ }
1055
+ interface LocalTheme {
1056
+ readonly name: string;
1057
+ readonly config: Record<string, unknown>;
1058
+ readonly active: boolean;
1059
+ }
1060
+ interface LocalNavigationItem {
1061
+ readonly id: number;
1062
+ readonly icon: string | null;
1063
+ readonly label: string | null;
1064
+ readonly screen: string | null;
1065
+ readonly slug: string | null;
1066
+ readonly source: string;
1067
+ readonly position: number | null;
1068
+ readonly parent_id: number | null;
1069
+ readonly children: LocalNavigationItem[];
1070
+ }
1071
+ interface LocalNavigation {
1072
+ readonly name: string;
1073
+ readonly platform: string;
1074
+ readonly navigation_items: LocalNavigationItem[];
1075
+ }
1076
+ interface LocalProfile {
1077
+ readonly name: string;
1078
+ readonly default: boolean;
1079
+ readonly navigation: string | null;
1080
+ readonly mobile_navigation: string | null;
1081
+ readonly themes: string[];
1082
+ readonly permissions: {
1083
+ readonly ranks: number[];
1084
+ readonly roles: string[];
1085
+ readonly platform: string[];
1086
+ readonly countries: number[];
1087
+ };
1088
+ }
1089
+ /**
1090
+ * Transform an API screen response into the local file format.
1091
+ * Strips server-only fields and normalizes `component_tree` to always be an array.
1092
+ */
1093
+ declare function transformScreen(screen: ApiScreen): LocalScreen;
1094
+ /**
1095
+ * Derive a slug for a screen. Screens use the existing `slug` field from the API.
1096
+ * Falls back to slugifying the name if no slug exists.
1097
+ */
1098
+ declare function deriveScreenSlug(screen: ApiScreen, existingSlugs: Set<string>): string;
1099
+ /**
1100
+ * Transform an API theme response into the local file format.
1101
+ * Passes theme config through as-is (hex conversion is a separate ticket).
1102
+ */
1103
+ declare function transformTheme(theme: ApiTheme): LocalTheme;
1104
+ /**
1105
+ * Build an ID → slug lookup map by inverting a slug → id mapping.
1106
+ */
1107
+ declare function buildIdToSlugMap(mappings: Record<string, number>): Map<number, string>;
1108
+ /**
1109
+ * Transform API navigation items into local format.
1110
+ * Converts `screen_id` to `screen` slug reference. Keeps `id` for sync.
1111
+ */
1112
+ declare function transformNavigationItems(items: ApiNavigationItem[], screenIdToSlug: Map<number, string>): LocalNavigationItem[];
1113
+ /**
1114
+ * Transform an API navigation with its items into the local file format.
1115
+ */
1116
+ declare function transformNavigation(nav: ApiNavigationBasic, items: ApiNavigationItem[], screenIdToSlug: Map<number, string>): LocalNavigation;
1117
+ /** Typed alias for call-site clarity. */
1118
+ declare const buildNavigationIdToSlugMap: (mappings: Record<string, number>) => Map<number, string>;
1119
+ /** Typed alias for call-site clarity. */
1120
+ declare const buildThemeIdToSlugMap: (mappings: Record<string, number>) => Map<number, string>;
1121
+ /**
1122
+ * Transform an API profile response into the local file format.
1123
+ * Converts navigation_id, mobile_navigation_id, and theme_ids to slug references.
1124
+ *
1125
+ * TODO (REP-842): Country/rank IDs in profile permissions need to be translated
1126
+ * to human-readable names via the main Fluid API. For now, the permission arrays
1127
+ * are written as-is with integer IDs.
1128
+ */
1129
+ declare function transformProfile(profile: ApiProfile, navIdToSlug: Map<number, string>, themeIdToSlug: Map<number, string>): LocalProfile;
1130
+ //#endregion
1131
+ //#region src/utils/push-validation.d.ts
1132
+ /** Categorize changed files by resource type. */
1133
+ interface CategorizedChanges {
1134
+ readonly screens: {
1135
+ new: string[];
1136
+ changed: string[];
1137
+ deleted: string[];
1138
+ };
1139
+ readonly themes: {
1140
+ new: string[];
1141
+ changed: string[];
1142
+ deleted: string[];
1143
+ };
1144
+ readonly navigations: {
1145
+ new: string[];
1146
+ changed: string[];
1147
+ deleted: string[];
1148
+ };
1149
+ readonly profiles: {
1150
+ new: string[];
1151
+ changed: string[];
1152
+ deleted: string[];
1153
+ };
1154
+ }
1155
+ /** A validation error found during cross-reference checking. */
1156
+ interface ValidationError {
1157
+ readonly file: string;
1158
+ readonly message: string;
1159
+ }
1160
+ /**
1161
+ * Extract the slug from a file path (e.g., "screens/home.json" -> "home").
1162
+ */
1163
+ declare function slugFromPath(filePath: string): string;
1164
+ /**
1165
+ * Categorize a snapshot diff into resource-type-specific change lists.
1166
+ */
1167
+ declare function categorizeChanges(diff: SnapshotDiff): CategorizedChanges;
1168
+ /**
1169
+ * Validate that all cross-references between local portal files are valid.
1170
+ *
1171
+ * Checks:
1172
+ * - Navigation items' "screen" slugs reference existing screen files or mappings
1173
+ * - Profile "navigation" and "mobile_navigation" slugs reference existing nav files or mappings
1174
+ * - Profile "themes" slugs reference existing theme files or mappings
1175
+ */
1176
+ declare function validateCrossReferences(portalDir: string, mappings: PortalMappings, changes: CategorizedChanges): Promise<ValidationError[]>;
1177
+ //#endregion
572
1178
  //#region src/index.d.ts
573
1179
  declare const plugin: FluidPlugin;
574
1180
  //#endregion
575
- export { type BuildOptions, CLOUD_RUN_ERRORS, type CloudRunConfig, type CloudRunDeployCallbacks, type CloudRunError, type CloudRunResult, type CreateOptions, type DeployOptions, type DestroyOptions, type DevOptions, FILE_SYSTEM_ERRORS, FLUID_API_ERROR, type FileSystemError, type FileSystemErrorCode, type FluidApiError, type FluidApiErrorCode, type FluidCompany, type ProjectConfig, type ResolvedTursoConfig, type SelectedPageTemplate, TEMPLATES, TURSO_ERROR, type TemplateName, type TemplatePaths, type TemplateVariables, type TursoConfig, type TursoConfigSource, type TursoDatabase, type TursoError, type TursoOrg, type TursoProvisionCallbacks, copyTemplate, copyTemplateSafe, createCommand, createDatabase, createDatabaseToken, createDirectory, createDirectorySafe, plugin as default, deleteCloudRunService, deleteDatabase, deployToCloudRun, destroyCommand, directoryExists, ensureGroup, fetchLocations, fileExists, getGcpProject, getInstallCommand, getRunCommand, getSdkVersion, getSdkVersionSafe, getTemplatePaths, installDependencies, isTemplateName, parseOrgList, pathExists, promptProjectConfig, provisionDatabase, readFileSafe, resolveFluidApiKey, resolveTursoConfig, runPackageManager, validateFluidApiKey, validateGcloudAuth, validateGcloudInstalled, validateLocation, validateTursoConfig, writeFileSafe };
1181
+ export { type BuildOptions, CLOUD_RUN_ERRORS, type CategorizedChanges, type CloudRunConfig, type CloudRunDeployCallbacks, type CloudRunError, type CloudRunResult, type CreateOptions, type DefinitionMapping, type DeployOptions, type DestroyOptions, type DevOptions, FILE_SYSTEM_ERRORS, FLUID_API_ERROR, type FileHash, type FileHashMap, type FileSystemError, type FileSystemErrorCode, type FluidApiError, type FluidApiErrorCode, type FluidCompany, type LocalNavigation, type LocalNavigationItem, type LocalProfile, type LocalScreen, type LocalTheme, type MappedResourceType, type PortalMappings, type ProjectConfig, type ResolvedTursoConfig, type SelectedPageTemplate, type Snapshot, type SnapshotDiff, TEMPLATES, TURSO_ERROR, type TemplateName, type TemplatePaths, type TemplateVariables, type TursoConfig, type TursoConfigSource, type TursoDatabase, type TursoError, type TursoOrg, type TursoProvisionCallbacks, type ValidationError, type WidgetCreateOptions, buildIdToSlugMap, buildNavigationIdToSlugMap, buildSnapshot, buildThemeIdToSlugMap, categorizeChanges, computeFileHash, copyTemplate, copyTemplateSafe, createCommand, createDatabase, createDatabaseToken, createDirectory, createDirectorySafe, plugin as default, deleteCloudRunService, deleteDatabase, deployToCloudRun, deriveScreenSlug, deriveSlug, destroyCommand, diffAgainstSnapshot, directoryExists, doctorCommand, ensureGroup, fetchLocations, fileExists, getGcpProject, getInstallCommand, getRunCommand, getSdkVersion, getSdkVersionSafe, getTemplatePaths, installDependencies, isTemplateName, parseOrgList, pathExists, promptProjectConfig, provisionDatabase, pullCommand, pushCommand, readFileSafe, readMappings, readSnapshot, removeMapping, resolveFluidApiKey, resolveIdToSlug, resolveSlugToId, resolveTursoConfig, runPackageManager, slugFromPath, transformNavigation, transformNavigationItems, transformProfile, transformScreen, transformTheme, updateMapping, validateCrossReferences, validateFluidApiKey, validateGcloudAuth, validateGcloudInstalled, validateLocation, validateTursoConfig, versionCommand, widgetCommand, writeFileSafe, writeMappings, writeSnapshot };
576
1182
  //# sourceMappingURL=index.d.mts.map