@admin-layout/client 12.0.16-alpha.59 → 12.0.16-alpha.64

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ConfigurationModelWrapper.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigurationModelWrapper.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ConfigurationModelWrapper.test.ts"],"names":[],"mappings":""}
@@ -1,7 +1,62 @@
1
+ /**
2
+ * Cookie configuration for storing user settings
3
+ * - Max age: 30 days
4
+ * - Client-side accessible for dynamic UI updates
5
+ * - Domain-scoped in production for subdomain sharing
6
+ */
1
7
  export declare const settingsCookie: import("@remix-run/server-runtime").Cookie;
8
+ /**
9
+ * Fetches page settings from GraphQL backend with device/route-specific overrides
10
+ *
11
+ * @param request - The incoming HTTP request (used for forwarding cookies and headers)
12
+ * @param overrideIdentifier - Optional override identifier (e.g., "[mobile]", "[desktop]", "[/dashboard][mobile]")
13
+ * @returns GraphQL query result containing merged settings with overrides applied
14
+ *
15
+ * @remarks
16
+ * - The GraphQL backend implements Redis caching for performance
17
+ * - Settings are returned in a flat structure with bracket notation for overrides
18
+ * - Example structure: { logo: '...', theme: '...', '[mobile]': { ... }, '[/dashboard][mobile]': { ... } }
19
+ */
2
20
  export declare function fetchPageSettingsWithFetch(request: Request, overrideIdentifier?: string): Promise<{
3
21
  data: any;
4
22
  }>;
23
+ /**
24
+ * Universal settings loader utility for both Remix loaders and actions
25
+ *
26
+ * @param params - Object containing request, context, and params
27
+ * @param params.request - The incoming HTTP request
28
+ * @param params.context - Optional Remix load context
29
+ * @param params.params - Optional route parameters
30
+ *
31
+ * @returns Object containing merged settings and cookie string
32
+ * @returns settings - Fully merged settings (GraphQL + env + cookies + request payload)
33
+ * @returns setCookie - Cookie string to set in response headers
34
+ *
35
+ * @remarks
36
+ * This utility handles both loader (GET) and action (POST/PUT/DELETE) requests:
37
+ * - **Loaders (GET)**: Fetches and merges settings from GraphQL, env, and cookies
38
+ * - **Actions (POST/PUT)**: Additionally processes request payload and updates cookies
39
+ *
40
+ * Settings merge order (later sources override earlier ones):
41
+ * 1. GraphQL backend settings (with device overrides)
42
+ * 2. Environment variable settings
43
+ * 3. Cookie settings (user preferences)
44
+ * 4. Request payload (only for actions)
45
+ *
46
+ * @example
47
+ * // In a Remix loader
48
+ * export const loader = async ({ request }) => {
49
+ * const { settings, setCookie } = await settingsLoaderUtil({ request });
50
+ * return json({ settings }, { headers: { 'Set-Cookie': setCookie } });
51
+ * };
52
+ *
53
+ * @example
54
+ * // In a Remix action
55
+ * export const action = async ({ request }) => {
56
+ * const { settings, setCookie } = await settingsLoaderUtil({ request });
57
+ * return json(settings, { headers: { 'Set-Cookie': setCookie } });
58
+ * };
59
+ */
5
60
  export declare function settingsLoaderUtil({ request, context, params }: {
6
61
  request: any;
7
62
  context: any;
@@ -1 +1 @@
1
- {"version":3,"file":"UpdateSettings.server.d.ts","sourceRoot":"","sources":["../../../src/components/UpdateSettings/UpdateSettings.server.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,cAAc,4CAMzB,CAAC;AAIH,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,EAAE,MAAM;;GAqF7F;AAED,wBAAsB,kBAAkB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;;;;CAAA;;;GAqGpE"}
1
+ {"version":3,"file":"UpdateSettings.server.d.ts","sourceRoot":"","sources":["../../../src/components/UpdateSettings/UpdateSettings.server.ts"],"names":[],"mappings":"AAgBA;;;;;GAKG;AACH,eAAO,MAAM,cAAc,4CAMzB,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,EAAE,MAAM;;GAuF7F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;;;;CAAA;;;GA+GpE"}
@@ -1,14 +1,31 @@
1
- import {createCookie}from'@remix-run/node';import {ConfigCollectionName,ConfigFragmentName,ConfigurationSchemaId}from'common';import {GetPageSettingsDocument}from'common/graphql';import {merge}from'lodash-es';import {print}from'graphql';import {config}from'../../config/env-config.js';import'../../config/defaultSettings.js';import'react';import'@cdm-logger/client';import {compareAndSaveSettingsDifferences}from'../../utils/settingsDifference.js';import {generateCdecodeUri,DEFAULT_CONTRIBUTION_TENANT_ID}from'@adminide-stack/core';const settingsCookie = createCookie('settings', {
1
+ import {createCookie}from'@remix-run/node';import {ConfigCollectionName,ConfigFragmentName,ConfigurationSchemaId}from'common';import {GetPageSettingsDocument}from'common/graphql';import {merge}from'lodash-es';import {print}from'graphql';import {parseEnvLayoutSettings}from'../../utils/parseEnvUiLayoutSettings.js';import {config}from'../../config/env-config.js';import'../../config/defaultSettings.js';import {generateCdecodeUri,DEFAULT_CONTRIBUTION_TENANT_ID}from'@adminide-stack/core';/**
2
+ * Cookie configuration for storing user settings
3
+ * - Max age: 30 days
4
+ * - Client-side accessible for dynamic UI updates
5
+ * - Domain-scoped in production for subdomain sharing
6
+ */
7
+ const settingsCookie = createCookie('settings', {
2
8
  maxAge: 60 * 60 * 24 * 30, // 1 month
3
9
  httpOnly: false, // Allow client-side access
4
10
  sameSite: 'lax',
5
11
  path: '/', // Ensure cookie is available for all paths
6
12
  domain: config.isProd ? config.APP_DOMAIN : undefined,
7
13
  });
8
- // Direct fetch-based implementation for fetching settings from GraphQL
9
- // Note: GraphQL backend already has Redis caching, so no need for additional caching here
14
+ /**
15
+ * Fetches page settings from GraphQL backend with device/route-specific overrides
16
+ *
17
+ * @param request - The incoming HTTP request (used for forwarding cookies and headers)
18
+ * @param overrideIdentifier - Optional override identifier (e.g., "[mobile]", "[desktop]", "[/dashboard][mobile]")
19
+ * @returns GraphQL query result containing merged settings with overrides applied
20
+ *
21
+ * @remarks
22
+ * - The GraphQL backend implements Redis caching for performance
23
+ * - Settings are returned in a flat structure with bracket notation for overrides
24
+ * - Example structure: { logo: '...', theme: '...', '[mobile]': { ... }, '[/dashboard][mobile]': { ... } }
25
+ */
10
26
  async function fetchPageSettingsWithFetch(request, overrideIdentifier) {
11
27
  console.log(`🔍 Fetching settings from GraphQL (Redis-cached backend)...`);
28
+ // Generate resource URI for the application settings
12
29
  const resource = generateCdecodeUri(DEFAULT_CONTRIBUTION_TENANT_ID, {
13
30
  resourceType: ConfigCollectionName.Applications,
14
31
  resourceId: config.APPLICATION_ID,
@@ -17,27 +34,26 @@ async function fetchPageSettingsWithFetch(request, overrideIdentifier) {
17
34
  const url = process.env.GRAPHQL_URL || 'http://localhost:8080/graphql';
18
35
  // Convert GraphQL DocumentNode to string
19
36
  const query = print(GetPageSettingsDocument);
20
- // Prepare options with optional overrides
37
+ // Prepare GraphQL query options
21
38
  const options = {
22
39
  schemaId: ConfigurationSchemaId.UiLayout,
23
40
  target: 2 /* ConfigurationTarget.APPLICATION */,
24
41
  configKey: 'uilayout',
25
42
  };
26
- // Add overrides if provided
43
+ // Add device/route overrides if provided
27
44
  if (overrideIdentifier) {
28
45
  options.overrides = {
46
+ strict: true,
29
47
  overrideIdentifier,
30
48
  };
31
49
  }
32
- // Add timestamp to force cache invalidation
33
50
  const variables = {
34
51
  resourceUri: resource,
35
52
  options,
36
- // _timestamp: Date.now(), // Force cache bust
37
53
  };
38
54
  console.log('🔍 Fetching settings with direct fetch to:', url);
39
55
  console.log('🔍 Query variables:', JSON.stringify(variables, null, 2));
40
- // Forward cookies from the incoming request
56
+ // Forward cookies and headers from the incoming request
41
57
  const headers = {
42
58
  'Content-Type': 'application/json',
43
59
  'Cache-Control': 'no-cache, no-store, must-revalidate',
@@ -78,85 +94,127 @@ async function fetchPageSettingsWithFetch(request, overrideIdentifier) {
78
94
  throw error;
79
95
  }
80
96
  }
97
+ /**
98
+ * Universal settings loader utility for both Remix loaders and actions
99
+ *
100
+ * @param params - Object containing request, context, and params
101
+ * @param params.request - The incoming HTTP request
102
+ * @param params.context - Optional Remix load context
103
+ * @param params.params - Optional route parameters
104
+ *
105
+ * @returns Object containing merged settings and cookie string
106
+ * @returns settings - Fully merged settings (GraphQL + env + cookies + request payload)
107
+ * @returns setCookie - Cookie string to set in response headers
108
+ *
109
+ * @remarks
110
+ * This utility handles both loader (GET) and action (POST/PUT/DELETE) requests:
111
+ * - **Loaders (GET)**: Fetches and merges settings from GraphQL, env, and cookies
112
+ * - **Actions (POST/PUT)**: Additionally processes request payload and updates cookies
113
+ *
114
+ * Settings merge order (later sources override earlier ones):
115
+ * 1. GraphQL backend settings (with device overrides)
116
+ * 2. Environment variable settings
117
+ * 3. Cookie settings (user preferences)
118
+ * 4. Request payload (only for actions)
119
+ *
120
+ * @example
121
+ * // In a Remix loader
122
+ * export const loader = async ({ request }) => {
123
+ * const { settings, setCookie } = await settingsLoaderUtil({ request });
124
+ * return json({ settings }, { headers: { 'Set-Cookie': setCookie } });
125
+ * };
126
+ *
127
+ * @example
128
+ * // In a Remix action
129
+ * export const action = async ({ request }) => {
130
+ * const { settings, setCookie } = await settingsLoaderUtil({ request });
131
+ * return json(settings, { headers: { 'Set-Cookie': setCookie } });
132
+ * };
133
+ */
81
134
  async function settingsLoaderUtil({ request, context, params }) {
82
- const cookieHeader = request.headers.get('Cookie');
83
- // Detect device type from User-Agent (simplified detection)
135
+ // 1. Detect device type from User-Agent header
84
136
  const userAgent = request.headers.get('User-Agent') || '';
85
137
  const isMobile = /mobile|android|iphone|ipad|ipod/i.test(userAgent);
86
138
  const deviceType = isMobile ? 'mobile' : 'desktop';
87
- // Fetch ALL settings for this device upfront (includes all route overrides)
88
- // Pass device-level override to get all route-specific overrides for this device
139
+ // 2. Fetch settings from GraphQL backend with device-specific overrides
140
+ // Override identifier format: "[desktop]" or "[mobile]"
89
141
  const overrideIdentifier = `[${deviceType}]`;
90
142
  const result = await fetchPageSettingsWithFetch(request, overrideIdentifier);
91
- console.log('RESULT=========>', JSON.stringify(result));
92
- const pageSettings = result?.data?.pageSettings?.settings
143
+ console.log('ddRESULT=========>', JSON.stringify(result));
144
+ const pageBackendSettings = result?.data?.pageSettings?.settings
93
145
  ? JSON.parse(JSON.stringify(result?.data?.pageSettings?.settings))
94
146
  : null;
95
- // pageSettings now contains flat structure:
96
- // {
97
- // logo: '...', theme: '...', ...base settings,
98
- // [desktop]: { overrides for desktop },
99
- // [/dashboard][mobile]: { overrides for /dashboard on mobile },
100
- // ... etc
101
- // }
102
- // Add required keys that might not be in backend
103
- let pageDefaultSettings = {
104
- ...pageSettings,
105
- };
106
- console.log('🔍 DEBUG - final pageDefaultSettings:', JSON.stringify(pageDefaultSettings, null, 2));
107
- // Fallback to config.LAYOUT_SETTINGS if backend returns empty
108
- const settingsKeys = Object.keys(pageDefaultSettings);
109
- const hasOnlyDefaultKeys = settingsKeys.length === 2 &&
110
- settingsKeys.includes('hiddenMenuKeys') &&
111
- settingsKeys.includes('hiddenMenuCategories');
112
- if (hasOnlyDefaultKeys && config.LAYOUT_SETTINGS) {
113
- const fallbackSettings = typeof config.LAYOUT_SETTINGS === 'string'
114
- ? JSON.parse(config.LAYOUT_SETTINGS)
115
- : { ...config.LAYOUT_SETTINGS };
116
- pageDefaultSettings = {
117
- ...fallbackSettings,
118
- };
147
+ // 3. Parse request payload (only available for POST/PUT requests in actions)
148
+ let requestPayload = {};
149
+ try {
150
+ // Clone request to avoid "body already read" errors
151
+ const clonedRequest = request.clone();
152
+ const contentType = request.headers.get('content-type');
153
+ // Only parse JSON for non-GET requests with JSON content-type
154
+ if (request.method !== 'GET' && contentType?.includes('application/json')) {
155
+ const jsonData = await clonedRequest.json();
156
+ requestPayload = jsonData?.config || {};
157
+ }
158
+ }
159
+ catch (error) {
160
+ // Expected for GET requests (loaders) - no payload to parse
161
+ console.log('ℹ️ No request payload (likely a loader call)');
162
+ requestPayload = {};
119
163
  }
120
- // Parse cookie settings
121
- let settings;
164
+ console.log('🔍 DEBUG - pageBackendSettings:', JSON.stringify(pageBackendSettings, null, 2));
165
+ // 4. Parse environment-based layout settings (fallback/default values)
166
+ const envLayoutSettings = parseEnvLayoutSettings();
167
+ // 5. Parse and validate existing cookie settings
168
+ const cookieHeader = request.headers.get('Cookie');
169
+ let existingCookieSettings;
170
+ let cookieUpdatedSettings;
122
171
  try {
123
- settings = await settingsCookie.parse(cookieHeader);
124
- // Remove any invalid numeric string keys from cookie
125
- if (settings && typeof settings === 'object') {
126
- Object.keys(settings).forEach((key) => {
172
+ existingCookieSettings = await settingsCookie.parse(cookieHeader);
173
+ // DEFENSIVE: Remove invalid numeric string keys (data corruption prevention)
174
+ if (existingCookieSettings && typeof existingCookieSettings === 'object') {
175
+ Object.keys(existingCookieSettings).forEach((key) => {
176
+ // Remove keys that are numeric strings (like "0", "1", etc.)
127
177
  if (/^\d+$/.test(key)) {
128
- delete settings[key];
178
+ console.warn(`⚠️ Removing invalid numeric key from cookie settings: "${key}" = ${JSON.stringify(existingCookieSettings[key])}`);
179
+ delete existingCookieSettings[key];
129
180
  }
130
181
  });
131
182
  }
183
+ // 6. Merge existing cookie settings with new request payload
184
+ cookieUpdatedSettings = merge({}, existingCookieSettings, requestPayload);
185
+ // Validate merge result - check for numeric key corruption
186
+ const numericKeysAfterMerge = Object.keys(cookieUpdatedSettings).filter((k) => /^\d+$/.test(k));
187
+ if (numericKeysAfterMerge.length > 0) {
188
+ console.error('❌ NUMERIC KEYS APPEARED AFTER MERGE!', numericKeysAfterMerge);
189
+ console.error('❌ Values:', numericKeysAfterMerge.map((k) => `${k}: ${JSON.stringify(cookieUpdatedSettings[k])}`));
190
+ }
132
191
  }
133
192
  catch (error) {
134
- settings = null;
193
+ // If cookie parsing fails, use only the request payload
194
+ console.error('Error parsing settings cookie:', error);
195
+ existingCookieSettings = null;
196
+ cookieUpdatedSettings = requestPayload;
135
197
  }
136
- // Generate default settings if no cookie exists
137
- if (!settings) {
138
- const fullSettings = merge({}, pageDefaultSettings, config.LAYOUT_SETTINGS);
139
- // Only store differences to keep cookie size small
140
- const diffSettings = await compareAndSaveSettingsDifferences(fullSettings, pageDefaultSettings);
141
- const cookie = await settingsCookie.serialize(diffSettings);
142
- return { settings: fullSettings, setCookie: cookie };
198
+ // 7. Merge all settings sources in priority order (later sources override earlier)
199
+ // Priority: GraphQL backend → Environment → Cookie + Request payload
200
+ const fullSettings = merge({}, pageBackendSettings, envLayoutSettings, cookieUpdatedSettings);
201
+ // 8. Validate final merged settings - detect and remove numeric key corruption
202
+ const numericKeysAfterFinalMerge = Object.keys(fullSettings).filter((k) => /^\d+$/.test(k));
203
+ if (numericKeysAfterFinalMerge.length > 0) {
204
+ console.error('❌ NUMERIC KEYS APPEARED AFTER FINAL MERGE!', numericKeysAfterFinalMerge);
205
+ console.error('❌ Values:', numericKeysAfterFinalMerge.map((k) => `${k}: ${JSON.stringify(fullSettings[k])}`));
143
206
  }
144
- // Extract base settings (non-bracket keys) from pageDefaultSettings
145
- const baseSettings = {};
146
- const bracketOverrides = {};
147
- Object.keys(pageDefaultSettings).forEach((key) => {
148
- if (key.startsWith('[') && key.endsWith(']')) {
149
- bracketOverrides[key] = pageDefaultSettings[key];
150
- }
151
- else {
152
- baseSettings[key] = pageDefaultSettings[key];
153
- }
154
- });
155
- // Merge: base settings + config + cookie overrides, then add bracket overrides
156
- const mergedBaseSettings = merge({}, baseSettings, config.LAYOUT_SETTINGS, settings);
157
- const fullSettings = merge({}, mergedBaseSettings, bracketOverrides);
158
- // Refresh the cookie to keep it active
159
- const cookie = await settingsCookie.serialize(settings);
160
- console.log('FULL_SETTINGS', fullSettings);
207
+ // 9. Final cleanup - remove any invalid numeric string keys before returning
208
+ if (fullSettings && typeof fullSettings === 'object') {
209
+ Object.keys(fullSettings).forEach((key) => {
210
+ if (/^\d+$/.test(key)) {
211
+ console.warn(`⚠️ Removing invalid numeric key from fullSettings: "${key}"`);
212
+ delete fullSettings[key];
213
+ }
214
+ });
215
+ }
216
+ // 10. Serialize cookie settings for response headers
217
+ const cookie = await settingsCookie.serialize(cookieUpdatedSettings);
218
+ console.log('✅ FULL_SETTINGS prepared:', Object.keys(fullSettings).length, 'keys');
161
219
  return { settings: fullSettings, setCookie: cookie };
162
220
  }export{fetchPageSettingsWithFetch,settingsCookie,settingsLoaderUtil};//# sourceMappingURL=UpdateSettings.server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UpdateSettings.server.js","sources":["../../../src/components/UpdateSettings/UpdateSettings.server.ts"],"sourcesContent":[null],"names":[],"mappings":"qhBAiHqE,MAAA,cAAA,GAAA,YAAA,CAAA,UAAA,EAAA;;;AAqGpE,IAAA,QAAA,EAAA,KAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"UpdateSettings.server.js","sources":["../../../src/components/UpdateSettings/UpdateSettings.server.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAyCG,IAAA,IAAA,EAAA,GAAA;AACH,IAAA,MAAA,EAAA,MAAA,CAAA,MAAsB,GAAA,MAAA,CAAA,UAAA,GAAA,SAA2B;;AAuFhD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCG,QAAA,WAAA,EAAA,QAAA;AACH,QAAA,OAAA;;;;AAAqE;;;AA+GpE,QAAA,eAAA,EAAA,qCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=UpdateSettings.server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpdateSettings.server.test.d.ts","sourceRoot":"","sources":["../../../src/components/UpdateSettings/UpdateSettings.server.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Parse LAYOUT_SETTINGS from config (which may be a JSON string from env variable)
3
+ * This is the single place where we handle the parsing logic
4
+ */
5
+ export declare function parseEnvLayoutSettings(): Record<string, any>;
6
+ //# sourceMappingURL=parseEnvUiLayoutSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseEnvUiLayoutSettings.d.ts","sourceRoot":"","sources":["../../src/utils/parseEnvUiLayoutSettings.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAwB5D"}
@@ -0,0 +1,27 @@
1
+ import {config}from'../config/env-config.js';import'../config/defaultSettings.js';/**
2
+ * Parse LAYOUT_SETTINGS from config (which may be a JSON string from env variable)
3
+ * This is the single place where we handle the parsing logic
4
+ */
5
+ function parseEnvLayoutSettings() {
6
+ try {
7
+ if (!config.LAYOUT_SETTINGS) {
8
+ return {};
9
+ }
10
+ // If it's already an object (parsed by envalid json validator), return it
11
+ if (typeof config.LAYOUT_SETTINGS === 'object' && !Array.isArray(config.LAYOUT_SETTINGS)) {
12
+ return config.LAYOUT_SETTINGS;
13
+ }
14
+ // If it's a string, parse it (this happens when envalid uses str validator)
15
+ if (typeof config.LAYOUT_SETTINGS === 'string') {
16
+ const parsed = JSON.parse(config.LAYOUT_SETTINGS);
17
+ return parsed || {};
18
+ }
19
+ console.warn('⚠️ config.LAYOUT_SETTINGS is unexpected type:', typeof config.LAYOUT_SETTINGS);
20
+ return {};
21
+ }
22
+ catch (error) {
23
+ console.error('❌ Error parsing LAYOUT_SETTINGS:', error);
24
+ console.error('❌ Value was:', config.LAYOUT_SETTINGS);
25
+ return {};
26
+ }
27
+ }export{parseEnvLayoutSettings};//# sourceMappingURL=parseEnvUiLayoutSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseEnvUiLayoutSettings.js","sources":["../../src/utils/parseEnvUiLayoutSettings.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAIG;AACH;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parseEnvUiLayoutSettings.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseEnvUiLayoutSettings.test.d.ts","sourceRoot":"","sources":["../../src/utils/parseEnvUiLayoutSettings.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"settingsDifference.d.ts","sourceRoot":"","sources":["../../src/utils/settingsDifference.ts"],"names":[],"mappings":"AAkLA;;;GAGG;AACH,eAAO,MAAM,iCAAiC,GAAI,iBAAiB,GAAG,EAAE,iBAAiB,GAAG,QAqD3F,CAAC"}
1
+ {"version":3,"file":"settingsDifference.d.ts","sourceRoot":"","sources":["../../src/utils/settingsDifference.ts"],"names":[],"mappings":"AAkLA;;;GAGG;AACH,eAAO,MAAM,iCAAiC,GAAI,iBAAiB,GAAG,EAAE,iBAAiB,GAAG,QA6D3F,CAAC"}
@@ -1,4 +1,4 @@
1
- import {cloneDeep,get,isObject,isEqual,transform}from'lodash-es';/**
1
+ import {cloneDeep,isObject,isEqual,transform}from'lodash-es';/**
2
2
  * Gets the deep differences between two objects
3
3
  * Returns only the values that differ from obj2
4
4
  */
@@ -63,84 +63,6 @@ const getDifference = (obj1, obj2) => {
63
63
  // Return undefined if the resulting object is empty
64
64
  return Object.keys(result).length > 0 ? result : undefined;
65
65
  };
66
- /**
67
- * Special handler for route settings differences with improved nested comparison
68
- */
69
- const getRouteSettingsDifferences = (currentRouteSettings, defaultRouteSettings) => {
70
- const differences = {};
71
- // Get the default route template (typically from '/')
72
- const defaultRouteTemplate = defaultRouteSettings['/'] || Object.values(defaultRouteSettings)[0];
73
- if (!defaultRouteTemplate) {
74
- console.warn('No default route template found for comparison');
75
- return currentRouteSettings;
76
- }
77
- // Compare each route's settings
78
- Object.keys(currentRouteSettings).forEach((route) => {
79
- const currentRouteConfig = currentRouteSettings[route];
80
- // Use the specific route config if it exists, otherwise use the default template
81
- const defaultRouteConfig = defaultRouteSettings[route] || defaultRouteTemplate;
82
- // Compare each section separately (layout, regions, etc)
83
- const routeDiff = {};
84
- Object.keys(currentRouteConfig).forEach((section) => {
85
- if (section === 'layout' || section === 'regions') {
86
- const sectionDiff = {};
87
- // Compare desktop and mobile separately
88
- ['desktop', 'mobile'].forEach((device) => {
89
- if (!currentRouteConfig[section][device]) {
90
- return;
91
- }
92
- // For regions section with header/footer/background
93
- if (section === 'regions') {
94
- const regionsDiff = {};
95
- ['header', 'footer', 'background'].forEach((region) => {
96
- if (!currentRouteConfig[section][device][region]) {
97
- return;
98
- }
99
- // Get default path for comparison
100
- const defaultRegionPath = `${section}.${device}.${region}`;
101
- const defaultRegion = get(defaultRouteConfig, defaultRegionPath);
102
- if (defaultRegion) {
103
- const regionDiff = getDifference(currentRouteConfig[section][device][region], defaultRegion);
104
- if (regionDiff !== undefined &&
105
- (Array.isArray(regionDiff) || Object.keys(regionDiff).length > 0)) {
106
- regionsDiff[region] = regionDiff;
107
- }
108
- }
109
- });
110
- if (Object.keys(regionsDiff).length > 0) {
111
- sectionDiff[device] = regionsDiff;
112
- }
113
- }
114
- else {
115
- // For other sections (like layout)
116
- const defaultDevicePath = `${section}.${device}`;
117
- const defaultDevice = get(defaultRouteConfig, defaultDevicePath);
118
- if (defaultDevice) {
119
- const deviceDiff = getDifference(currentRouteConfig[section][device], defaultDevice);
120
- if (deviceDiff !== undefined && Object.keys(deviceDiff).length > 0) {
121
- sectionDiff[device] = deviceDiff;
122
- }
123
- }
124
- }
125
- });
126
- if (Object.keys(sectionDiff).length > 0) {
127
- routeDiff[section] = sectionDiff;
128
- }
129
- }
130
- else {
131
- const sectionDiff = getDifference(currentRouteConfig[section], defaultRouteConfig[section]);
132
- if (sectionDiff !== undefined && Object.keys(sectionDiff).length > 0) {
133
- routeDiff[section] = sectionDiff;
134
- }
135
- }
136
- });
137
- // Only include the route if there are actual differences
138
- if (Object.keys(routeDiff).length > 0) {
139
- differences[route] = routeDiff;
140
- }
141
- });
142
- return Object.keys(differences).length > 0 ? differences : undefined;
143
- };
144
66
  /**
145
67
  * Compares settings objects and saves only the differences
146
68
  * @returns An object containing only the differences, or an empty object on error
@@ -154,39 +76,46 @@ const compareAndSaveSettingsDifferences = (currentSettings, defaultSettings) =>
154
76
  // Make deep clones to avoid modifying the original objects
155
77
  const current = cloneDeep(currentSettings);
156
78
  const defaults = cloneDeep(defaultSettings);
157
- // Handle route settings separately
158
- const routeSettingsDiff = current.routeSettings
159
- ? getRouteSettingsDifferences(current.routeSettings, defaults?.routeSettings || {})
160
- : undefined;
161
- // Make a copy of settings without routeSettings to compare separately
162
- const currentWithoutRoutes = { ...current };
163
- const defaultWithoutRoutes = { ...defaults };
164
- delete currentWithoutRoutes.routeSettings;
165
- delete defaultWithoutRoutes.routeSettings;
166
- // Get differences for all other settings
167
- const otherSettingsDiff = getDifference(currentWithoutRoutes, defaultWithoutRoutes);
168
- // Combine the differences
79
+ // Extract overrides (bracket keys) from current settings
80
+ const overrides = {};
81
+ Object.keys(current).forEach((key) => {
82
+ if (key.startsWith('[') && key.endsWith(']')) {
83
+ overrides[key] = current[key];
84
+ }
85
+ });
86
+ // Get differences for non-override settings (base settings)
87
+ const currentBase = { ...current };
88
+ const defaultBase = { ...defaults };
89
+ // Remove all bracket keys from both objects
90
+ Object.keys(currentBase).forEach((key) => {
91
+ if (key.startsWith('[') && key.endsWith(']')) {
92
+ delete currentBase[key];
93
+ }
94
+ });
95
+ Object.keys(defaultBase).forEach((key) => {
96
+ if (key.startsWith('[') && key.endsWith(']')) {
97
+ delete defaultBase[key];
98
+ }
99
+ });
100
+ const baseSettingsDiff = getDifference(currentBase, defaultBase);
101
+ // Combine base settings differences with overrides
169
102
  const diffSettings = {};
170
- // Add other settings differences if any exist and are not empty objects
171
- if (otherSettingsDiff && Object.keys(otherSettingsDiff).length > 0) {
172
- Object.assign(diffSettings, otherSettingsDiff);
173
- }
174
- // Add route settings differences if any exist
175
- if (routeSettingsDiff && Object.keys(routeSettingsDiff).length > 0) {
176
- diffSettings.routeSettings = routeSettingsDiff;
103
+ // Add base settings differences if any exist
104
+ if (baseSettingsDiff && Object.keys(baseSettingsDiff).length > 0) {
105
+ Object.assign(diffSettings, baseSettingsDiff);
177
106
  }
107
+ // Add all overrides (they are always different from defaults)
108
+ Object.assign(diffSettings, overrides);
178
109
  // If there are no differences at all, return early
179
110
  if (Object.keys(diffSettings).length === 0) {
180
111
  return {};
181
112
  }
182
113
  // Remove empty objects from the diff
183
- // This helps prevent unnecessary properties in the payload
184
114
  const cleanDiffSettings = removeEmptyObjects(diffSettings);
185
115
  return cleanDiffSettings;
186
116
  }
187
117
  catch (error) {
188
118
  console.error('Error comparing settings differences:', error);
189
- // Return empty object instead of null to avoid downstream errors
190
119
  return {};
191
120
  }
192
121
  };
@@ -1 +1 @@
1
- {"version":3,"file":"settingsDifference.js","sources":["../../src/utils/settingsDifference.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAqLG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"settingsDifference.js","sources":["../../src/utils/settingsDifference.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAqLG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@admin-layout/client",
3
- "version": "12.0.16-alpha.59",
3
+ "version": "12.0.16-alpha.64",
4
4
  "description": "Sample client for higher packages to depend on",
5
5
  "license": "ISC",
6
6
  "author": "CDMBase LLC",
@@ -26,7 +26,7 @@
26
26
  "serialize-error": "^8.0.0"
27
27
  },
28
28
  "devDependencies": {
29
- "common": "12.0.16-alpha.59",
29
+ "common": "12.0.16-alpha.64",
30
30
  "rc-menu": "^9.16.1"
31
31
  },
32
32
  "peerDependencies": {
@@ -44,5 +44,5 @@
44
44
  "typescript": {
45
45
  "definition": "lib/index.d.ts"
46
46
  },
47
- "gitHead": "03aa1a41d438cdd8616b2d9a239728cc01dd9e45"
47
+ "gitHead": "506bff5baaa896802376e745517c2e8c295a9db8"
48
48
  }