@hartl-services/medusa-base 0.3.0 → 0.4.0
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/.medusa/server/src/admin/index.js +741 -36
- package/.medusa/server/src/admin/index.mjs +743 -38
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/route.js +31 -0
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/runs/route.js +16 -0
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/route.js +14 -0
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/settings/route.js +22 -0
- package/.medusa/server/src/api/admin/plugin-features/route.js +6 -4
- package/.medusa/server/src/api/middlewares.js +22 -8
- package/.medusa/server/src/api/plugin-actions.js +221 -0
- package/.medusa/server/src/api/plugin-features-http.js +67 -8
- package/.medusa/server/src/modules/plugin-features/domain/plugin-action-runs.js +92 -0
- package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +213 -0
- package/.medusa/server/src/modules/plugin-features/domain/secret-box.js +56 -0
- package/.medusa/server/src/modules/plugin-features/migrations/Migration20260928205031.js +16 -0
- package/.medusa/server/src/modules/plugin-features/migrations/Migration20260928215428.js +17 -0
- package/.medusa/server/src/modules/plugin-features/models/plugin-action-run.js +43 -0
- package/.medusa/server/src/modules/plugin-features/models/plugin-setting-state.js +32 -0
- package/.medusa/server/src/modules/plugin-features/service.js +419 -17
- package/.medusa/server/src/public/action-progress.js +67 -0
- package/.medusa/server/src/public/descriptor.js +199 -2
- package/.medusa/server/src/public/effective-features.js +9 -5
- package/.medusa/server/src/public/enforcement.js +18 -8
- package/.medusa/server/src/public/index.js +10 -2
- package/.medusa/server/src/public/module-access.js +14 -0
- package/.medusa/server/src/public/settings.js +17 -0
- package/.medusa/server/src/public/shop-master-data.js +95 -0
- package/.medusa/server/src/utils/discover-complete-cart-participants.js +9 -2
- package/.medusa/server/src/utils/discover-plugin-features.js +47 -9
- package/.medusa/server/src/workflows/hooks/complete-cart-participants.js +28 -16
- package/README.md +393 -12
- package/dist/admin-components/features/plugin-features/components/PluginActionsSection.d.ts +6 -0
- package/dist/admin-components/features/plugin-features/components/PluginActionsSection.js +66 -0
- package/dist/admin-components/features/plugin-features/components/PluginDetailPage.d.ts +2 -0
- package/dist/admin-components/features/plugin-features/components/PluginDetailPage.js +9 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeatureGate.d.ts +22 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeatureGate.js +18 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeatureSections.d.ts +11 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeatureSections.js +19 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeaturesCard.d.ts +12 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeaturesCard.js +34 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.d.ts +5 -0
- package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.js +16 -0
- package/dist/admin-components/features/plugin-features/components/PluginHubCard.d.ts +7 -0
- package/dist/admin-components/features/plugin-features/components/PluginHubCard.js +21 -0
- package/dist/admin-components/features/plugin-features/components/PluginPageShell.d.ts +13 -0
- package/dist/admin-components/features/plugin-features/components/PluginPageShell.js +20 -0
- package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.d.ts +7 -0
- package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.js +39 -0
- package/dist/admin-components/features/plugin-features/components/PluginStatusChips.d.ts +5 -0
- package/dist/admin-components/features/plugin-features/components/PluginStatusChips.js +8 -0
- package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +114 -0
- package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.js +40 -0
- package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +392 -0
- package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.js +128 -0
- package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +93 -0
- package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.js +44 -0
- package/dist/admin-components/features/plugin-features/lib/action-runs.d.ts +19 -0
- package/dist/admin-components/features/plugin-features/lib/action-runs.js +74 -0
- package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +363 -0
- package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.js +9 -0
- package/dist/admin-components/features/plugin-features/lib/plugin-paths.d.ts +4 -0
- package/dist/admin-components/features/plugin-features/lib/plugin-paths.js +4 -0
- package/dist/admin-components/features/plugin-features/lib/settings-draft.d.ts +28 -0
- package/dist/admin-components/features/plugin-features/lib/settings-draft.js +86 -0
- package/dist/admin-components/features/plugin-features/queries/pluginFeatureKeys.d.ts +7 -0
- package/dist/admin-components/features/plugin-features/queries/pluginFeatureKeys.js +7 -0
- package/dist/admin-components/i18n/texts.d.ts +90 -0
- package/dist/admin-components/i18n/texts.js +90 -0
- package/dist/admin-components/index.d.ts +14 -0
- package/dist/admin-components/index.js +14 -0
- package/dist/admin-components/lib/errors.d.ts +6 -0
- package/dist/admin-components/lib/errors.js +27 -0
- package/dist/admin-components/lib/sdk.d.ts +2 -0
- package/dist/admin-components/lib/sdk.js +13 -0
- package/dist/public/action-progress.d.ts +25 -0
- package/dist/public/action-progress.js +66 -0
- package/dist/public/descriptor.d.ts +3 -2
- package/dist/public/descriptor.js +198 -1
- package/dist/public/effective-features.d.ts +2 -1
- package/dist/public/effective-features.js +8 -4
- package/dist/public/enforcement.d.ts +7 -0
- package/dist/public/enforcement.js +17 -7
- package/dist/public/index.d.ts +5 -2
- package/dist/public/index.js +9 -1
- package/dist/public/module-access.d.ts +3 -0
- package/dist/public/module-access.js +13 -0
- package/dist/public/settings.d.ts +11 -0
- package/dist/public/settings.js +16 -0
- package/dist/public/shop-master-data.d.ts +25 -0
- package/dist/public/shop-master-data.js +94 -0
- package/dist/public/types.d.ts +97 -1
- package/dist/utils/discover-plugin-features.d.ts +28 -0
- package/dist/utils/discover-plugin-features.js +96 -0
- package/package.json +7 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveBaseModule = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const constants_1 = require("./constants");
|
|
6
|
+
/** Resolves the base module or fails with a clear `UNEXPECTED_STATE`. */
|
|
7
|
+
const resolveBaseModule = (container) => {
|
|
8
|
+
if (!container.hasRegistration(constants_1.PLUGIN_FEATURES_MODULE)) {
|
|
9
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "@hartl-services/medusa-base ist nicht in medusa-config registriert.");
|
|
10
|
+
}
|
|
11
|
+
return container.resolve(constants_1.PLUGIN_FEATURES_MODULE);
|
|
12
|
+
};
|
|
13
|
+
exports.resolveBaseModule = resolveBaseModule;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MedusaContainer } from "@medusajs/framework/types";
|
|
2
|
+
import type { PluginFeatureDescriptor, PluginSettingsFallback, ResolvedPluginSettings } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Current settings of a plugin for server-side code (subscribers, workflow
|
|
5
|
+
* steps, jobs, scripts, module services via the global container). Secrets
|
|
6
|
+
* are DECRYPTED; never send the result to a client. Precedence per key:
|
|
7
|
+
* stored in the Admin > `fallback` (medusa-config) > declared default.
|
|
8
|
+
* A missing base plugin fails with `UNEXPECTED_STATE`; read failures
|
|
9
|
+
* propagate.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getPluginSettings<K extends string, S extends string, A extends string>(container: MedusaContainer, descriptor: PluginFeatureDescriptor<K, S, A>, fallback?: PluginSettingsFallback<S>): Promise<ResolvedPluginSettings<S>>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPluginSettings = getPluginSettings;
|
|
4
|
+
const module_access_1 = require("./module-access");
|
|
5
|
+
/**
|
|
6
|
+
* Current settings of a plugin for server-side code (subscribers, workflow
|
|
7
|
+
* steps, jobs, scripts, module services via the global container). Secrets
|
|
8
|
+
* are DECRYPTED; never send the result to a client. Precedence per key:
|
|
9
|
+
* stored in the Admin > `fallback` (medusa-config) > declared default.
|
|
10
|
+
* A missing base plugin fails with `UNEXPECTED_STATE`; read failures
|
|
11
|
+
* propagate.
|
|
12
|
+
*/
|
|
13
|
+
async function getPluginSettings(container, descriptor, fallback) {
|
|
14
|
+
const resolved = await (0, module_access_1.resolveBaseModule)(container).resolvePluginSettings(descriptor, fallback);
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MedusaContainer } from "@medusajs/framework/types";
|
|
2
|
+
import type { PluginSettingsFallback } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* The base's own descriptor: the shop's master data (Firmenangaben), edited
|
|
5
|
+
* on the generic plugin page like any plugin's settings. It cannot be
|
|
6
|
+
* switched off and declares no features.
|
|
7
|
+
*/
|
|
8
|
+
export declare const shopMasterDataDescriptor: import("./types").PluginFeatureDescriptor<string, "legal_name" | "address_line1" | "address_line2" | "postal_code" | "city" | "country_code" | "vat_number" | "email" | "phone" | "website" | "iban" | "bic" | "company_register_number" | "company_register_court", never>;
|
|
9
|
+
/** Keys of the shop master data settings. */
|
|
10
|
+
export type ShopMasterDataKey = "legal_name" | "address_line1" | "address_line2" | "postal_code" | "city" | "country_code" | "vat_number" | "email" | "phone" | "website" | "iban" | "bic" | "company_register_number" | "company_register_court";
|
|
11
|
+
/** Every key that has a value (stored > fallback). All values are strings. */
|
|
12
|
+
export type ShopMasterData = Partial<Record<ShopMasterDataKey, string>>;
|
|
13
|
+
export type ResolvedShopMasterData = {
|
|
14
|
+
values: ShopMasterData;
|
|
15
|
+
/** Every required field has a value. */
|
|
16
|
+
configured: boolean;
|
|
17
|
+
/** Required keys without a value. */
|
|
18
|
+
missing: ShopMasterDataKey[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The shop's master data for server-side code. Precedence per key: stored in
|
|
22
|
+
* the Admin > `fallback` (e.g. a plugin's own medusa-config option). A
|
|
23
|
+
* missing base plugin fails with `UNEXPECTED_STATE`; read failures propagate.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getShopMasterData(container: MedusaContainer, fallback?: PluginSettingsFallback<ShopMasterDataKey>): Promise<ResolvedShopMasterData>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shopMasterDataDescriptor = void 0;
|
|
4
|
+
exports.getShopMasterData = getShopMasterData;
|
|
5
|
+
const descriptor_1 = require("./descriptor");
|
|
6
|
+
const settings_1 = require("./settings");
|
|
7
|
+
/**
|
|
8
|
+
* The base's own descriptor: the shop's master data (Firmenangaben), edited
|
|
9
|
+
* on the generic plugin page like any plugin's settings. It cannot be
|
|
10
|
+
* switched off and declares no features.
|
|
11
|
+
*/
|
|
12
|
+
exports.shopMasterDataDescriptor = (0, descriptor_1.definePluginFeatures)({
|
|
13
|
+
plugin_key: "shop",
|
|
14
|
+
label: "Shop-Stammdaten",
|
|
15
|
+
description: "Firmenangaben des Shops für Rechnungen, Dokumente und Steuerprüfungen.",
|
|
16
|
+
switchable: false,
|
|
17
|
+
features: [],
|
|
18
|
+
settings: [
|
|
19
|
+
{ key: "legal_name", label: "Firmenname", type: "string", required: true },
|
|
20
|
+
{ key: "address_line1", label: "Adresse", type: "string", required: true },
|
|
21
|
+
{ key: "address_line2", label: "Adresszusatz", type: "string" },
|
|
22
|
+
{ key: "postal_code", label: "Postleitzahl", type: "string", required: true },
|
|
23
|
+
{ key: "city", label: "Ort", type: "string", required: true },
|
|
24
|
+
{
|
|
25
|
+
key: "country_code",
|
|
26
|
+
label: "Land",
|
|
27
|
+
type: "select",
|
|
28
|
+
required: true,
|
|
29
|
+
// EU-27 plus CH, GB, NO, IS, LI (ISO 3166-1 alpha-2, lowercase),
|
|
30
|
+
// sorted by German label.
|
|
31
|
+
options: [
|
|
32
|
+
{ value: "be", label: "Belgien" },
|
|
33
|
+
{ value: "bg", label: "Bulgarien" },
|
|
34
|
+
{ value: "dk", label: "Dänemark" },
|
|
35
|
+
{ value: "de", label: "Deutschland" },
|
|
36
|
+
{ value: "ee", label: "Estland" },
|
|
37
|
+
{ value: "fi", label: "Finnland" },
|
|
38
|
+
{ value: "fr", label: "Frankreich" },
|
|
39
|
+
{ value: "gr", label: "Griechenland" },
|
|
40
|
+
{ value: "ie", label: "Irland" },
|
|
41
|
+
{ value: "is", label: "Island" },
|
|
42
|
+
{ value: "it", label: "Italien" },
|
|
43
|
+
{ value: "hr", label: "Kroatien" },
|
|
44
|
+
{ value: "lv", label: "Lettland" },
|
|
45
|
+
{ value: "li", label: "Liechtenstein" },
|
|
46
|
+
{ value: "lt", label: "Litauen" },
|
|
47
|
+
{ value: "lu", label: "Luxemburg" },
|
|
48
|
+
{ value: "mt", label: "Malta" },
|
|
49
|
+
{ value: "nl", label: "Niederlande" },
|
|
50
|
+
{ value: "no", label: "Norwegen" },
|
|
51
|
+
{ value: "at", label: "Österreich" },
|
|
52
|
+
{ value: "pl", label: "Polen" },
|
|
53
|
+
{ value: "pt", label: "Portugal" },
|
|
54
|
+
{ value: "ro", label: "Rumänien" },
|
|
55
|
+
{ value: "se", label: "Schweden" },
|
|
56
|
+
{ value: "ch", label: "Schweiz" },
|
|
57
|
+
{ value: "sk", label: "Slowakei" },
|
|
58
|
+
{ value: "si", label: "Slowenien" },
|
|
59
|
+
{ value: "es", label: "Spanien" },
|
|
60
|
+
{ value: "cz", label: "Tschechien" },
|
|
61
|
+
{ value: "hu", label: "Ungarn" },
|
|
62
|
+
{ value: "gb", label: "Vereinigtes Königreich" },
|
|
63
|
+
{ value: "cy", label: "Zypern" },
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
{ key: "vat_number", label: "UID-Nummer", type: "string", required: true },
|
|
67
|
+
{ key: "email", label: "E-Mail", type: "string" },
|
|
68
|
+
{ key: "phone", label: "Telefon", type: "string" },
|
|
69
|
+
{ key: "website", label: "Website", type: "url" },
|
|
70
|
+
{ key: "iban", label: "IBAN", type: "string" },
|
|
71
|
+
{ key: "bic", label: "BIC", type: "string" },
|
|
72
|
+
{ key: "company_register_number", label: "Firmenbuchnummer", type: "string" },
|
|
73
|
+
{ key: "company_register_court", label: "Firmenbuchgericht", type: "string" },
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* The shop's master data for server-side code. Precedence per key: stored in
|
|
78
|
+
* the Admin > `fallback` (e.g. a plugin's own medusa-config option). A
|
|
79
|
+
* missing base plugin fails with `UNEXPECTED_STATE`; read failures propagate.
|
|
80
|
+
*/
|
|
81
|
+
async function getShopMasterData(container, fallback) {
|
|
82
|
+
const resolved = await (0, settings_1.getPluginSettings)(container, exports.shopMasterDataDescriptor, fallback);
|
|
83
|
+
const values = {};
|
|
84
|
+
for (const [key, value] of Object.entries(resolved.values)) {
|
|
85
|
+
if (typeof value === "string") {
|
|
86
|
+
values[key] = value;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
values,
|
|
91
|
+
configured: resolved.configured,
|
|
92
|
+
missing: resolved.missing,
|
|
93
|
+
};
|
|
94
|
+
}
|
package/dist/public/types.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/** Options of the base plugin (`plugins: [{ resolve, options }]`). */
|
|
2
|
+
export type BasePluginOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* Key material for stored secret settings; set it from an environment
|
|
5
|
+
* variable of the shop. Defaults to `projectConfig.http.cookieSecret`.
|
|
6
|
+
* Changing it makes stored secrets undecryptable ("nicht gesetzt").
|
|
7
|
+
*/
|
|
8
|
+
readonly settingsSecret?: string;
|
|
9
|
+
};
|
|
1
10
|
export type PluginFeatureDefinition<K extends string = string> = {
|
|
2
11
|
readonly key: K;
|
|
3
12
|
readonly label: string;
|
|
@@ -5,17 +14,75 @@ export type PluginFeatureDefinition<K extends string = string> = {
|
|
|
5
14
|
readonly default_enabled: boolean;
|
|
6
15
|
readonly parent_key?: K;
|
|
7
16
|
};
|
|
8
|
-
export type
|
|
17
|
+
export type PluginSettingType = "string" | "url" | "number" | "boolean" | "secret" | "select";
|
|
18
|
+
/** One allowed value of a `"select"` setting. */
|
|
19
|
+
export type PluginSettingOption = {
|
|
20
|
+
readonly value: string;
|
|
21
|
+
readonly label: string;
|
|
22
|
+
};
|
|
23
|
+
export type PluginSettingValue = string | number | boolean;
|
|
24
|
+
export type PluginSettingDefinition<S extends string = string> = {
|
|
25
|
+
readonly key: S;
|
|
26
|
+
readonly label: string;
|
|
27
|
+
readonly description?: string;
|
|
28
|
+
readonly type: PluginSettingType;
|
|
29
|
+
/** `false` when omitted. */
|
|
30
|
+
readonly required?: boolean;
|
|
31
|
+
/** Never for `"secret"`; must match `type` (and `options`/`min`/`max`). */
|
|
32
|
+
readonly default?: PluginSettingValue;
|
|
33
|
+
/** Required for `"select"` (non-empty, unique values); only there. */
|
|
34
|
+
readonly options?: readonly PluginSettingOption[];
|
|
35
|
+
/** Inclusive lower bound; only for `"number"`. */
|
|
36
|
+
readonly min?: number;
|
|
37
|
+
/** Inclusive upper bound; only for `"number"`. */
|
|
38
|
+
readonly max?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Secret settings of the same plugin whose stored values are deleted when
|
|
41
|
+
* this setting's stored value changes (also when it is cleared), e.g. an
|
|
42
|
+
* API key that must not be sent to a new URL.
|
|
43
|
+
*/
|
|
44
|
+
readonly invalidates?: readonly S[];
|
|
45
|
+
};
|
|
46
|
+
export type PluginActionMode = "sync" | "background";
|
|
47
|
+
export type PluginActionDefinition<A extends string = string> = {
|
|
48
|
+
readonly key: A;
|
|
49
|
+
readonly label: string;
|
|
50
|
+
readonly description?: string;
|
|
51
|
+
/** Registered workflow the base runs for this action. */
|
|
52
|
+
readonly workflow_id: string;
|
|
53
|
+
readonly mode: PluginActionMode;
|
|
54
|
+
/** Confirmation text shown before running. */
|
|
55
|
+
readonly confirm?: string;
|
|
56
|
+
};
|
|
57
|
+
export type PluginFeatureDescriptor<K extends string = string, S extends string = string, A extends string = string> = {
|
|
9
58
|
readonly plugin_key: string;
|
|
10
59
|
readonly label: string;
|
|
11
60
|
readonly description?: string;
|
|
12
61
|
/** Plugin switch default, `true` when omitted. */
|
|
13
62
|
readonly default_enabled?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* `false`: the plugin cannot be switched off. The Admin shows no plugin
|
|
65
|
+
* switch and `enabled` is always `true`. `true` when omitted.
|
|
66
|
+
*/
|
|
67
|
+
readonly switchable?: boolean;
|
|
14
68
|
readonly features: readonly PluginFeatureDefinition<K>[];
|
|
69
|
+
readonly settings?: readonly PluginSettingDefinition<S>[];
|
|
70
|
+
readonly actions?: readonly PluginActionDefinition<A>[];
|
|
71
|
+
/**
|
|
72
|
+
* The plugin's own Admin page, relative to the Admin root; the hub's
|
|
73
|
+
* "Öffnen" links there. Starts with `/settings/hartl-services/`, never with
|
|
74
|
+
* `/settings/hartl-services/plugin/` (the base's generic page, used when
|
|
75
|
+
* omitted).
|
|
76
|
+
*/
|
|
77
|
+
readonly admin_page?: string;
|
|
15
78
|
};
|
|
79
|
+
/** Values a plugin received from medusa-config; the base shows them as source "config". */
|
|
80
|
+
export type PluginSettingsFallback<S extends string = string> = Partial<Record<S, PluginSettingValue | null | undefined>>;
|
|
16
81
|
/** Implemented by a plugin's module service so the base can discover it. */
|
|
17
82
|
export interface PluginFeatureProvider {
|
|
18
83
|
readonly pluginFeatures: PluginFeatureDescriptor;
|
|
84
|
+
/** Optional medusa-config fallback for the declared settings. */
|
|
85
|
+
readonly pluginSettingsFallback?: PluginSettingsFallback;
|
|
19
86
|
}
|
|
20
87
|
export type EffectivePluginFeatures = {
|
|
21
88
|
plugin_key: string;
|
|
@@ -27,3 +94,32 @@ export type StoredPluginFeatures = {
|
|
|
27
94
|
enabled: boolean;
|
|
28
95
|
features: Record<string, boolean>;
|
|
29
96
|
};
|
|
97
|
+
/**
|
|
98
|
+
* Settings for server-side consumers. Secrets are decrypted. `values` holds
|
|
99
|
+
* every setting that has a value (stored > config > default).
|
|
100
|
+
*/
|
|
101
|
+
export type ResolvedPluginSettings<S extends string = string> = {
|
|
102
|
+
values: Partial<Record<S, PluginSettingValue>>;
|
|
103
|
+
/** Every required setting has a value. */
|
|
104
|
+
configured: boolean;
|
|
105
|
+
/** Keys of required settings without a value. */
|
|
106
|
+
missing: S[];
|
|
107
|
+
};
|
|
108
|
+
/** Input the base passes to an action's workflow. */
|
|
109
|
+
export type PluginActionWorkflowInput = {
|
|
110
|
+
plugin_key: string;
|
|
111
|
+
action_key: string;
|
|
112
|
+
/** Admin user id that triggered the action. */
|
|
113
|
+
triggered_by: string;
|
|
114
|
+
/** Recorded run; pass it to `reportPluginActionProgress`. */
|
|
115
|
+
run_id: string;
|
|
116
|
+
};
|
|
117
|
+
/** Progress a running action reports through `reportPluginActionProgress`. */
|
|
118
|
+
export type PluginActionProgressInput = {
|
|
119
|
+
/** Items (or pages) done so far; a non-negative integer. */
|
|
120
|
+
current: number;
|
|
121
|
+
/** Expected total; `null`/omitted = unknown. */
|
|
122
|
+
total?: number | null;
|
|
123
|
+
/** Short human-readable status, e.g. "Produkte: Seite 3". */
|
|
124
|
+
label?: string | null;
|
|
125
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MedusaContainer } from "@medusajs/framework/types";
|
|
2
|
+
import type { PluginFeatureDescriptor, PluginSettingsFallback } from "../public/types";
|
|
3
|
+
export type RegisteredModule = {
|
|
4
|
+
key: string;
|
|
5
|
+
service: unknown;
|
|
6
|
+
};
|
|
7
|
+
/** A discovered declaring module service. */
|
|
8
|
+
export type PluginFeatureProviderEntry = {
|
|
9
|
+
module_key: string;
|
|
10
|
+
descriptor: PluginFeatureDescriptor;
|
|
11
|
+
service: unknown;
|
|
12
|
+
};
|
|
13
|
+
/** Every module listed in medusa-config that is registered in the container. */
|
|
14
|
+
export declare function listRegisteredModules(container: MedusaContainer): RegisteredModule[];
|
|
15
|
+
/**
|
|
16
|
+
* Finds every registered module whose service declares `pluginFeatures`.
|
|
17
|
+
* Fails closed: an invalid or duplicate declaration is `UNEXPECTED_STATE`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function discoverPluginFeatureDescriptors(container: MedusaContainer): PluginFeatureDescriptor[];
|
|
20
|
+
/** Like `discoverPluginFeatureDescriptors`, with the declaring service. */
|
|
21
|
+
export declare function discoverPluginFeatureProviders(container: MedusaContainer): PluginFeatureProviderEntry[];
|
|
22
|
+
export declare function findPluginFeatureDescriptor(container: MedusaContainer, pluginKey: string): PluginFeatureDescriptor | undefined;
|
|
23
|
+
export declare function findPluginFeatureProvider(container: MedusaContainer, pluginKey: string): PluginFeatureProviderEntry | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* The medusa-config fallback a provider exposes as `pluginSettingsFallback`.
|
|
26
|
+
* Read on every call, since a service may compute it lazily.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readPluginSettingsFallback(provider: PluginFeatureProviderEntry): PluginSettingsFallback | undefined;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listRegisteredModules = listRegisteredModules;
|
|
4
|
+
exports.discoverPluginFeatureDescriptors = discoverPluginFeatureDescriptors;
|
|
5
|
+
exports.discoverPluginFeatureProviders = discoverPluginFeatureProviders;
|
|
6
|
+
exports.findPluginFeatureDescriptor = findPluginFeatureDescriptor;
|
|
7
|
+
exports.findPluginFeatureProvider = findPluginFeatureProvider;
|
|
8
|
+
exports.readPluginSettingsFallback = readPluginSettingsFallback;
|
|
9
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
10
|
+
const descriptor_1 = require("../public/descriptor");
|
|
11
|
+
// Keyed by the app's config object: stable for the process lifetime, unlike
|
|
12
|
+
// `req.scope`, which is a new scope per request.
|
|
13
|
+
const discovered = new WeakMap();
|
|
14
|
+
const registeredModules = (container, configModule) => Object.keys(configModule.modules ?? {})
|
|
15
|
+
.filter((moduleKey) => container.hasRegistration(moduleKey))
|
|
16
|
+
.map((moduleKey) => ({
|
|
17
|
+
key: moduleKey,
|
|
18
|
+
service: container.resolve(moduleKey),
|
|
19
|
+
}));
|
|
20
|
+
/** Every module listed in medusa-config that is registered in the container. */
|
|
21
|
+
function listRegisteredModules(container) {
|
|
22
|
+
return registeredModules(container, container.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE));
|
|
23
|
+
}
|
|
24
|
+
const readDescriptor = (service) => service !== null && typeof service === "object" && "pluginFeatures" in service
|
|
25
|
+
? service.pluginFeatures
|
|
26
|
+
: undefined;
|
|
27
|
+
const discover = (container) => {
|
|
28
|
+
const configModule = container.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
29
|
+
const memo = discovered.get(configModule);
|
|
30
|
+
if (memo) {
|
|
31
|
+
return memo;
|
|
32
|
+
}
|
|
33
|
+
const byPluginKey = new Map();
|
|
34
|
+
for (const { key: moduleKey, service } of registeredModules(container, configModule)) {
|
|
35
|
+
const candidate = readDescriptor(service);
|
|
36
|
+
if (candidate === undefined) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const descriptor = candidate;
|
|
40
|
+
try {
|
|
41
|
+
(0, descriptor_1.validatePluginFeatureDescriptor)(descriptor);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Modul "${moduleKey}" deklariert ungültige Funktionsschalter: ${error instanceof Error ? error.message : String(error)}`);
|
|
45
|
+
}
|
|
46
|
+
if (byPluginKey.has(descriptor.plugin_key)) {
|
|
47
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Plugin-Key "${descriptor.plugin_key}" wird von mehreren Modulen deklariert.`);
|
|
48
|
+
}
|
|
49
|
+
byPluginKey.set(descriptor.plugin_key, {
|
|
50
|
+
module_key: moduleKey,
|
|
51
|
+
descriptor,
|
|
52
|
+
service,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const providers = [...byPluginKey.values()].sort((left, right) => left.descriptor.plugin_key.localeCompare(right.descriptor.plugin_key));
|
|
56
|
+
const result = {
|
|
57
|
+
providers,
|
|
58
|
+
descriptors: providers.map((provider) => provider.descriptor),
|
|
59
|
+
};
|
|
60
|
+
discovered.set(configModule, result);
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Finds every registered module whose service declares `pluginFeatures`.
|
|
65
|
+
* Fails closed: an invalid or duplicate declaration is `UNEXPECTED_STATE`.
|
|
66
|
+
*/
|
|
67
|
+
function discoverPluginFeatureDescriptors(container) {
|
|
68
|
+
return discover(container).descriptors;
|
|
69
|
+
}
|
|
70
|
+
/** Like `discoverPluginFeatureDescriptors`, with the declaring service. */
|
|
71
|
+
function discoverPluginFeatureProviders(container) {
|
|
72
|
+
return discover(container).providers;
|
|
73
|
+
}
|
|
74
|
+
function findPluginFeatureDescriptor(container, pluginKey) {
|
|
75
|
+
return findPluginFeatureProvider(container, pluginKey)?.descriptor;
|
|
76
|
+
}
|
|
77
|
+
function findPluginFeatureProvider(container, pluginKey) {
|
|
78
|
+
return discover(container).providers.find((provider) => provider.descriptor.plugin_key === pluginKey);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The medusa-config fallback a provider exposes as `pluginSettingsFallback`.
|
|
82
|
+
* Read on every call, since a service may compute it lazily.
|
|
83
|
+
*/
|
|
84
|
+
function readPluginSettingsFallback(provider) {
|
|
85
|
+
const service = provider.service;
|
|
86
|
+
if (service === null ||
|
|
87
|
+
typeof service !== "object" ||
|
|
88
|
+
!("pluginSettingsFallback" in service)) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const fallback = service
|
|
92
|
+
.pluginSettingsFallback;
|
|
93
|
+
return fallback !== null && typeof fallback === "object"
|
|
94
|
+
? fallback
|
|
95
|
+
: undefined;
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hartl-services/medusa-base",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Base plugin for Hartl Services Medusa shops: per-plugin feature toggles with a generic Admin settings page, a Store endpoint for storefronts, enforcement helpers, the complete-cart hook composition, and the Sentry logger wrapper.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"import": "./dist/public/sentry-logger.js",
|
|
34
34
|
"require": "./dist/public/sentry-logger.js"
|
|
35
35
|
},
|
|
36
|
+
"./admin-components": {
|
|
37
|
+
"types": "./dist/admin-components/index.d.ts",
|
|
38
|
+
"import": "./dist/admin-components/index.js"
|
|
39
|
+
},
|
|
36
40
|
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
37
41
|
"./.medusa/server/src/*": "./.medusa/server/src/*",
|
|
38
42
|
"./admin": {
|
|
@@ -52,7 +56,7 @@
|
|
|
52
56
|
"react-router-dom": "^7.18.2"
|
|
53
57
|
},
|
|
54
58
|
"dependencies": {
|
|
55
|
-
"@hartl-services/medusa-food-supplements-contracts": "^0.
|
|
59
|
+
"@hartl-services/medusa-food-supplements-contracts": "^0.12.0"
|
|
56
60
|
},
|
|
57
61
|
"devDependencies": {
|
|
58
62
|
"@medusajs/admin-sdk": "2.19.0",
|
|
@@ -85,7 +89,7 @@
|
|
|
85
89
|
}
|
|
86
90
|
},
|
|
87
91
|
"scripts": {
|
|
88
|
-
"build": "medusa plugin:build && tsc -p tsconfig.public.json",
|
|
92
|
+
"build": "medusa plugin:build && tsc -p tsconfig.public.json && tsc -p tsconfig.admin-components.json",
|
|
89
93
|
"dev": "medusa plugin:develop",
|
|
90
94
|
"typecheck": "tsc --noEmit",
|
|
91
95
|
"pretest:unit": "pnpm --filter @hartl-services/medusa-food-supplements-contracts build",
|