feat: add settings module (#13175)

* feat: add view_configurations feature flag

  - Add feature flag provider and hooks to admin dashboard
  - Add backend API endpoint for feature flags
  - Create view_configurations feature flag (disabled by default)
  - Update order list table to use legacy version when flag is disabled
  - Can be enabled with MEDUSA_FF_VIEW_CONFIGURATIONS=true env var

* fix: naming

* fix: feature flags unauthenticated

* fix: add test

* feat: add settings module

* fix: deps

* fix: cleanup

* fix: add more tetsts

* fix: rm changelog

* fix: deps

* fix: add settings module to default modules list

* fix: pr comments

* fix: deps,build

* fix: alias

* fix: tests

* fix: update snapshots
This commit is contained in:
Sebastian Rindom authored and GitHub committed 2025-08-15 10:59:54 +02:00
1 parent 9b37a2c9f4
commit f7fc05307f
28 files changed
+1736

No files matched your search

@@ -219,6 +219,17 @@ export const ModulesDefinition: {
scope: MODULE_SCOPE.INTERNAL,
},
},
[Modules.SETTINGS]: {
key: Modules.SETTINGS,
defaultPackage: false,
label: upperCaseFirst(Modules.SETTINGS),
isRequired: false,
isQueryable: true,
dependencies: [ContainerRegistrationKeys.LOGGER],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
},
},
[Modules.STORE]: {
key: Modules.STORE,
defaultPackage: false,
+1
View File
@@ -26,6 +26,7 @@ export * as PromotionTypes from "./promotion"
export * as RegionTypes from "./region"
export * as SalesChannelTypes from "./sales-channel"
export * as SearchTypes from "./search"
export * as SettingsTypes from "./settings"
export * as StockLocationTypes from "./stock-location"
export * as StoreTypes from "./store"
export * as TaxTypes from "./tax"
+1
View File
@@ -34,6 +34,7 @@ export * from "./promotion"
export * from "./region"
export * from "./sales-channel"
export * from "./search"
export * from "./settings"
export * from "./shared-context"
export * from "./stock-location"
export * from "./store"
+161
View File
@@ -0,0 +1,161 @@
import { BaseFilterable } from "../dal"
/**
* The view configuration data model.
*/
export interface ViewConfigurationDTO {
/**
* The ID of the configuration.
*/
id: string
/**
* The entity this configuration is for.
*/
entity: string
/**
* The name of the configuration.
*/
name: string
/**
* The user ID this configuration belongs to.
*/
user_id: string | null
/**
* Whether this is a system default configuration.
*/
is_system_default: boolean
/**
* The configuration data.
*/
configuration: {
/**
* The visible columns.
*/
visible_columns: string[]
/**
* The column order.
*/
column_order: string[]
/**
* The column widths.
*/
column_widths?: Record<string, number>
/**
* The filters to apply.
*/
filters?: Record<string, any>
/**
* The sorting configuration.
*/
sorting?: { id: string; desc: boolean } | null
/**
* The search string.
*/
search?: string
}
/**
* The date the configuration was created.
*/
created_at: Date
/**
* The date the configuration was last updated.
*/
updated_at: Date
}
/**
* The user preference data model.
*/
export interface UserPreferenceDTO {
/**
* The ID of the preference.
*/
id: string
/**
* The user ID.
*/
user_id: string
/**
* The preference key.
*/
key: string
/**
* The preference value.
*/
value: any
/**
* The date the preference was created.
*/
created_at: Date
/**
* The date the preference was last updated.
*/
updated_at: Date
}
/**
* The filters to apply on the retrieved view configurations.
*/
export interface FilterableViewConfigurationProps extends BaseFilterable<ViewConfigurationDTO> {
/**
* The IDs to filter by.
*/
id?: string | string[]
/**
* Filter by entity name.
*/
entity?: string | string[]
/**
* Filter by user ID.
*/
user_id?: string | string[] | null
/**
* Filter by system default flag.
*/
is_system_default?: boolean
/**
* Filter by name.
*/
name?: string | string[]
}
/**
* The filters to apply on the retrieved user preferences.
*/
export interface FilterableUserPreferenceProps extends BaseFilterable<UserPreferenceDTO> {
/**
* The IDs to filter by.
*/
id?: string | string[]
/**
* Filter by user ID.
*/
user_id?: string | string[]
/**
* Filter by preference key.
*/
key?: string | string[]
}
@@ -0,0 +1,3 @@
export * from "./common"
export * from "./mutations"
export * from "./service"
@@ -0,0 +1,134 @@
/**
* The view configuration to be created.
*/
export interface CreateViewConfigurationDTO {
/**
* The entity this configuration is for.
*/
entity: string
/**
* The name of the configuration.
*/
name: string
/**
* The user ID this configuration belongs to.
*/
user_id?: string
/**
* Whether this is a system default configuration.
*/
is_system_default?: boolean
/**
* The configuration data.
*/
configuration: {
/**
* The visible columns.
*/
visible_columns: string[]
/**
* The column order.
*/
column_order: string[]
/**
* The column widths.
*/
column_widths?: Record<string, number>
/**
* The filters to apply.
*/
filters?: Record<string, any>
/**
* The sorting configuration.
*/
sorting?: { id: string; desc: boolean } | null
/**
* The search string.
*/
search?: string
}
}
/**
* The attributes to update in the view configuration.
*/
export interface UpdateViewConfigurationDTO {
/**
* The name of the configuration.
*/
name?: string
/**
* The configuration data.
*/
configuration?: {
/**
* The visible columns.
*/
visible_columns?: string[]
/**
* The column order.
*/
column_order?: string[]
/**
* The column widths.
*/
column_widths?: Record<string, number>
/**
* The filters to apply.
*/
filters?: Record<string, any>
/**
* The sorting configuration.
*/
sorting?: { id: string; desc: boolean } | null
/**
* The search string.
*/
search?: string
}
}
/**
* The user preference to be created.
*/
export interface CreateUserPreferenceDTO {
/**
* The user ID.
*/
user_id: string
/**
* The preference key.
*/
key: string
/**
* The preference value.
*/
value: any
}
/**
* The attributes to update in the user preference.
*/
export interface UpdateUserPreferenceDTO {
/**
* The preference value.
*/
value: any
}
+117
View File
@@ -0,0 +1,117 @@
import { Context } from "../shared-context"
import { FindConfig } from "../common"
import { IModuleService } from "../modules-sdk"
import {
ViewConfigurationDTO,
UserPreferenceDTO,
FilterableViewConfigurationProps,
FilterableUserPreferenceProps,
} from "./common"
import {
CreateViewConfigurationDTO,
UpdateViewConfigurationDTO,
} from "./mutations"
export interface ISettingsModuleService extends IModuleService {
// View Configuration methods
retrieveViewConfiguration(
id: string,
config?: FindConfig<ViewConfigurationDTO>,
sharedContext?: Context
): Promise<ViewConfigurationDTO>
listViewConfigurations(
filters?: FilterableViewConfigurationProps,
config?: FindConfig<ViewConfigurationDTO>,
sharedContext?: Context
): Promise<ViewConfigurationDTO[]>
listAndCountViewConfigurations(
filters?: FilterableViewConfigurationProps,
config?: FindConfig<ViewConfigurationDTO>,
sharedContext?: Context
): Promise<[ViewConfigurationDTO[], number]>
createViewConfigurations(
data: CreateViewConfigurationDTO[],
sharedContext?: Context
): Promise<ViewConfigurationDTO[]>
createViewConfigurations(
data: CreateViewConfigurationDTO,
sharedContext?: Context
): Promise<ViewConfigurationDTO>
updateViewConfigurations(
idOrSelector: string,
data: UpdateViewConfigurationDTO,
sharedContext?: Context
): Promise<ViewConfigurationDTO>
updateViewConfigurations(
idOrSelector: FilterableViewConfigurationProps,
data: UpdateViewConfigurationDTO,
sharedContext?: Context
): Promise<ViewConfigurationDTO[]>
deleteViewConfigurations(
ids: string | string[],
sharedContext?: Context
): Promise<void>
// User Preference methods
retrieveUserPreference(
id: string,
config?: FindConfig<UserPreferenceDTO>,
sharedContext?: Context
): Promise<UserPreferenceDTO>
listUserPreferences(
filters?: FilterableUserPreferenceProps,
config?: FindConfig<UserPreferenceDTO>,
sharedContext?: Context
): Promise<UserPreferenceDTO[]>
getUserPreference(
userId: string,
key: string,
sharedContext?: Context
): Promise<UserPreferenceDTO | null>
setUserPreference(
userId: string,
key: string,
value: any,
sharedContext?: Context
): Promise<UserPreferenceDTO>
deleteUserPreferences(
ids: string | string[],
sharedContext?: Context
): Promise<void>
// Helper methods
getActiveViewConfiguration(
entity: string,
userId: string,
sharedContext?: Context
): Promise<ViewConfigurationDTO | null>
setActiveViewConfiguration(
entity: string,
userId: string,
viewConfigurationId: string,
sharedContext?: Context
): Promise<void>
getSystemDefaultViewConfiguration(
entity: string,
sharedContext?: Context
): Promise<ViewConfigurationDTO | null>
clearActiveViewConfiguration(
entity: string,
userId: string,
sharedContext?: Context
): Promise<void>
}
@@ -106,6 +106,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -270,6 +273,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -442,6 +448,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -615,6 +624,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -776,6 +788,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -940,6 +955,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -1132,6 +1150,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -1331,6 +1352,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -1546,6 +1570,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -1733,6 +1760,9 @@ describe("defineConfig", function () {
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"settings": {
"resolve": "@medusajs/medusa/settings",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location",
},
@@ -152,6 +152,7 @@ function resolveModules(
{ resolve: MODULE_PACKAGE_NAMES[Modules.CURRENCY] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.PAYMENT] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.ORDER] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.SETTINGS] },
{
resolve: MODULE_PACKAGE_NAMES[Modules.AUTH],
@@ -26,6 +26,7 @@ export const Modules = {
NOTIFICATION: "notification",
INDEX: "index",
LOCKING: "locking",
SETTINGS: "settings",
} as const
export const MODULE_PACKAGE_NAMES = {
@@ -56,6 +57,7 @@ export const MODULE_PACKAGE_NAMES = {
[Modules.NOTIFICATION]: "@medusajs/medusa/notification",
[Modules.INDEX]: "@medusajs/medusa/index-module",
[Modules.LOCKING]: "@medusajs/medusa/locking",
[Modules.SETTINGS]: "@medusajs/medusa/settings",
}
export const REVERSED_MODULE_PACKAGE_NAMES = Object.entries(