@endora-commerce/mod-custom-fields 0.0.0-stage → 0.100.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/LICENSE +21 -0
- package/README.md +58 -2
- package/dist/admin/api/custom-fields-client.d.ts +10 -0
- package/dist/admin/api/custom-fields-client.d.ts.map +1 -0
- package/dist/admin/api/custom-fields-client.js +11 -0
- package/dist/admin/api/custom-fields-client.js.map +1 -0
- package/dist/admin/index.d.ts +44 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +51 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/CustomFieldsPage.d.ts +10 -0
- package/dist/admin/pages/CustomFieldsPage.d.ts.map +1 -0
- package/dist/admin/pages/CustomFieldsPage.js +118 -0
- package/dist/admin/pages/CustomFieldsPage.js.map +1 -0
- package/dist/backend/commands/definition-commands.d.ts +22 -0
- package/dist/backend/commands/definition-commands.d.ts.map +1 -0
- package/dist/backend/commands/definition-commands.js +115 -0
- package/dist/backend/commands/definition-commands.js.map +1 -0
- package/dist/backend/entities/custom-field-definition.entity.d.ts +37 -0
- package/dist/backend/entities/custom-field-definition.entity.d.ts.map +1 -0
- package/dist/backend/entities/custom-field-definition.entity.js +98 -0
- package/dist/backend/entities/custom-field-definition.entity.js.map +1 -0
- package/dist/backend/entities/custom-field-option.entity.d.ts +25 -0
- package/dist/backend/entities/custom-field-option.entity.d.ts.map +1 -0
- package/dist/backend/entities/custom-field-option.entity.js +79 -0
- package/dist/backend/entities/custom-field-option.entity.js.map +1 -0
- package/dist/backend/index.d.ts +79 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +94 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +14 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +179 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/services/custom-field-definition-apply.d.ts +63 -0
- package/dist/backend/services/custom-field-definition-apply.d.ts.map +1 -0
- package/dist/backend/services/custom-field-definition-apply.js +221 -0
- package/dist/backend/services/custom-field-definition-apply.js.map +1 -0
- package/dist/backend/services/custom-field-definition.service.d.ts +68 -0
- package/dist/backend/services/custom-field-definition.service.d.ts.map +1 -0
- package/dist/backend/services/custom-field-definition.service.js +205 -0
- package/dist/backend/services/custom-field-definition.service.js.map +1 -0
- package/dist/backend/services/custom-field-definitions-cache.d.ts +46 -0
- package/dist/backend/services/custom-field-definitions-cache.d.ts.map +1 -0
- package/dist/backend/services/custom-field-definitions-cache.js +82 -0
- package/dist/backend/services/custom-field-definitions-cache.js.map +1 -0
- package/dist/backend/services/custom-field-read-port.d.ts +61 -0
- package/dist/backend/services/custom-field-read-port.d.ts.map +1 -0
- package/dist/backend/services/custom-field-read-port.js +82 -0
- package/dist/backend/services/custom-field-read-port.js.map +1 -0
- package/dist/backend/services/custom-field-registry.d.ts +41 -0
- package/dist/backend/services/custom-field-registry.d.ts.map +1 -0
- package/dist/backend/services/custom-field-registry.js +24 -0
- package/dist/backend/services/custom-field-registry.js.map +1 -0
- package/dist/backend/services/custom-field-value.service.d.ts +56 -0
- package/dist/backend/services/custom-field-value.service.d.ts.map +1 -0
- package/dist/backend/services/custom-field-value.service.js +175 -0
- package/dist/backend/services/custom-field-value.service.js.map +1 -0
- package/dist/manifest.d.ts +177 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +130 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260718T200338_custom_fields_init.d.ts +20 -0
- package/dist/migrations/20260718T200338_custom_fields_init.d.ts.map +1 -0
- package/dist/migrations/20260718T200338_custom_fields_init.js +60 -0
- package/dist/migrations/20260718T200338_custom_fields_init.js.map +1 -0
- package/dist/migrations/index.d.ts +27 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +29 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/ports/index.d.ts +123 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +2 -0
- package/dist/ports/index.js.map +1 -0
- package/i18n/en.json +15 -0
- package/i18n/pl.json +15 -0
- package/package.json +99 -3
- package/tailwind.css +14 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { type ModuleUninstallHook } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Custom Fields module — manifest (feature 055).
|
|
4
|
+
*
|
|
5
|
+
* Owns the entity-agnostic custom-field definition/option registry and the
|
|
6
|
+
* value-validation service consumed by host modules. Platform-global; values
|
|
7
|
+
* live on host rows and inherit the host's tenant scope (Principle XI).
|
|
8
|
+
* Definition/option mutations run through the Command Bus (Principle XIII).
|
|
9
|
+
*/
|
|
10
|
+
export declare const manifest: {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
version: string;
|
|
14
|
+
dependencies: string[];
|
|
15
|
+
description?: string | undefined;
|
|
16
|
+
acknowledgedDependencies?: {
|
|
17
|
+
moduleId: string;
|
|
18
|
+
port: string;
|
|
19
|
+
reason: string;
|
|
20
|
+
}[] | undefined;
|
|
21
|
+
nonBindingDependencies?: {
|
|
22
|
+
moduleId: string;
|
|
23
|
+
name: string;
|
|
24
|
+
kind: "contributes-to" | "degrades-without" | "refuses-without";
|
|
25
|
+
reason: string;
|
|
26
|
+
whenAbsent?: string | undefined;
|
|
27
|
+
}[] | undefined;
|
|
28
|
+
activation?: {
|
|
29
|
+
settingCode: string;
|
|
30
|
+
default: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
nonDeactivatable: true;
|
|
33
|
+
reason: string;
|
|
34
|
+
} | undefined;
|
|
35
|
+
settings?: {
|
|
36
|
+
moduleCode: string;
|
|
37
|
+
groups: {
|
|
38
|
+
code: string;
|
|
39
|
+
name: string;
|
|
40
|
+
salesChannelCodes?: string[] | undefined;
|
|
41
|
+
isSystemProtected?: boolean | undefined;
|
|
42
|
+
}[];
|
|
43
|
+
settings: {
|
|
44
|
+
code: string;
|
|
45
|
+
name: string;
|
|
46
|
+
valueType: "string" | "number" | "boolean" | "json" | "string_list" | "secret" | "credential_ref";
|
|
47
|
+
defaultValue: unknown;
|
|
48
|
+
description?: string | undefined;
|
|
49
|
+
groupCode?: string | undefined;
|
|
50
|
+
previousDefaultValues?: unknown[] | undefined;
|
|
51
|
+
salesChannelCodes?: string[] | undefined;
|
|
52
|
+
enumOptions?: string[] | undefined;
|
|
53
|
+
configurationType?: string | undefined;
|
|
54
|
+
hidden?: boolean | undefined;
|
|
55
|
+
}[];
|
|
56
|
+
} | undefined;
|
|
57
|
+
i18n?: {
|
|
58
|
+
bundlesDir: string;
|
|
59
|
+
} | undefined;
|
|
60
|
+
docs?: false | {
|
|
61
|
+
dir: string;
|
|
62
|
+
} | undefined;
|
|
63
|
+
demo?: false | {
|
|
64
|
+
summary: string;
|
|
65
|
+
seed: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoSeedResult>;
|
|
66
|
+
reset: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoResetResult>;
|
|
67
|
+
after?: readonly string[] | undefined;
|
|
68
|
+
package?: string | undefined;
|
|
69
|
+
} | undefined;
|
|
70
|
+
actions?: {
|
|
71
|
+
id: string;
|
|
72
|
+
labelKey: string;
|
|
73
|
+
icon: "Plus" | "Sparkles" | "Settings" | "Search" | "Boxes" | "Layers" | "Menu" | "PlusCircle" | "PlusSquare" | "FilePlus" | "FolderPlus" | "Upload" | "FileUp" | "CloudUpload" | "Download" | "FileDown" | "FileText" | "BookOpen" | "Rss" | "Package" | "Tag" | "ShoppingCart" | "Receipt" | "CreditCard" | "Users" | "UserPlus" | "Inbox" | "ListChecks" | "ClipboardList" | "Image" | "Video" | "LayoutDashboard" | "PanelLeft" | "KeyRound" | "ShieldCheck" | "Edit" | "Archive" | "Box" | "Truck" | "CircleDollarSign" | "Activity" | "LineChart" | "Smartphone" | "Webhook" | "Scale" | "PlugZap" | "PercentDiamond" | "Newspaper" | "Languages" | "Eraser" | "Warehouse" | "TrendingDown" | "Bell" | "PackageOpen" | "Building2" | "Store" | "ClipboardCheck";
|
|
74
|
+
targetRoute: string;
|
|
75
|
+
keywords: string[];
|
|
76
|
+
weight: number;
|
|
77
|
+
descriptionKey?: string | undefined;
|
|
78
|
+
requiredPermission?: string | undefined;
|
|
79
|
+
}[] | undefined;
|
|
80
|
+
permissions?: {
|
|
81
|
+
code: string;
|
|
82
|
+
label: string;
|
|
83
|
+
module?: string | undefined;
|
|
84
|
+
description?: string | undefined;
|
|
85
|
+
requires?: string[] | undefined;
|
|
86
|
+
}[] | undefined;
|
|
87
|
+
transactionalEmails?: {
|
|
88
|
+
code: string;
|
|
89
|
+
name: string;
|
|
90
|
+
variables: {
|
|
91
|
+
key: string;
|
|
92
|
+
label: string;
|
|
93
|
+
sampleValue?: string | undefined;
|
|
94
|
+
description?: string | undefined;
|
|
95
|
+
}[];
|
|
96
|
+
description?: string | undefined;
|
|
97
|
+
group?: string | undefined;
|
|
98
|
+
}[] | undefined;
|
|
99
|
+
capabilities?: string[] | undefined;
|
|
100
|
+
exclusiveCapabilities?: {
|
|
101
|
+
key: string;
|
|
102
|
+
errorCode: string;
|
|
103
|
+
}[] | undefined;
|
|
104
|
+
errorCodes?: {
|
|
105
|
+
code: string;
|
|
106
|
+
tokens?: string[] | undefined;
|
|
107
|
+
}[] | undefined;
|
|
108
|
+
blocks?: {
|
|
109
|
+
name: string;
|
|
110
|
+
labelKey: string;
|
|
111
|
+
category: string;
|
|
112
|
+
contexts: ("invoice" | "email" | "cms" | "newsletter")[];
|
|
113
|
+
fields: Record<string, {
|
|
114
|
+
type: "number" | "object" | "array" | "text" | "textarea" | "select" | "radio" | "external" | "uuid" | "richtext";
|
|
115
|
+
label?: string | undefined;
|
|
116
|
+
required?: boolean | undefined;
|
|
117
|
+
options?: {
|
|
118
|
+
label: string;
|
|
119
|
+
value: string | number;
|
|
120
|
+
}[] | undefined;
|
|
121
|
+
refKind?: string | undefined;
|
|
122
|
+
}>;
|
|
123
|
+
descriptionKey?: string | undefined;
|
|
124
|
+
defaultProps?: Record<string, unknown> | undefined;
|
|
125
|
+
responsiveFields?: string[] | undefined;
|
|
126
|
+
previewIcon?: string | undefined;
|
|
127
|
+
weight?: number | undefined;
|
|
128
|
+
}[] | undefined;
|
|
129
|
+
blockCategories?: {
|
|
130
|
+
key: string;
|
|
131
|
+
titleKey: string;
|
|
132
|
+
contexts: ("invoice" | "email" | "cms" | "newsletter")[];
|
|
133
|
+
weight?: number | undefined;
|
|
134
|
+
visible?: boolean | undefined;
|
|
135
|
+
}[] | undefined;
|
|
136
|
+
env?: {
|
|
137
|
+
name: string;
|
|
138
|
+
describes: {
|
|
139
|
+
en: string;
|
|
140
|
+
pl: string;
|
|
141
|
+
};
|
|
142
|
+
requirement: {
|
|
143
|
+
kind: "required";
|
|
144
|
+
} | {
|
|
145
|
+
kind: "requiredWhen";
|
|
146
|
+
input: string;
|
|
147
|
+
equals: string;
|
|
148
|
+
} | {
|
|
149
|
+
kind: "optional";
|
|
150
|
+
without: {
|
|
151
|
+
en: string;
|
|
152
|
+
pl: string;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
secret: boolean;
|
|
156
|
+
generable: boolean;
|
|
157
|
+
owner: {
|
|
158
|
+
kind: "platform";
|
|
159
|
+
} | {
|
|
160
|
+
kind: "application";
|
|
161
|
+
application: "admin" | "backend" | "storefront";
|
|
162
|
+
} | {
|
|
163
|
+
kind: "module";
|
|
164
|
+
moduleId: string;
|
|
165
|
+
};
|
|
166
|
+
consumers: ("admin" | "backend" | "storefront")[];
|
|
167
|
+
addressOf: "admin" | "backend" | "storefront" | null;
|
|
168
|
+
}[] | undefined;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Hard-uninstall cleanup (feature 055). A soft uninstall keeps definitions so a
|
|
172
|
+
* re-install restores them; a hard uninstall drops all definitions (options
|
|
173
|
+
* cascade via FK). Host `custom_field_values` columns are owned by their host
|
|
174
|
+
* modules and removed with them, so nothing dangles either way.
|
|
175
|
+
*/
|
|
176
|
+
export declare const uninstallHook: ModuleUninstallHook;
|
|
177
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG5F;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyGnB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,mBAO3B,CAAC"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { defineModuleManifest } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Custom Fields module — manifest (feature 055).
|
|
4
|
+
*
|
|
5
|
+
* Owns the entity-agnostic custom-field definition/option registry and the
|
|
6
|
+
* value-validation service consumed by host modules. Platform-global; values
|
|
7
|
+
* live on host rows and inherit the host's tenant scope (Principle XI).
|
|
8
|
+
* Definition/option mutations run through the Command Bus (Principle XIII).
|
|
9
|
+
*/
|
|
10
|
+
export const manifest = defineModuleManifest({
|
|
11
|
+
id: 'custom_fields',
|
|
12
|
+
name: 'Custom Fields',
|
|
13
|
+
description: 'Entity-agnostic runtime custom fields for core entities.',
|
|
14
|
+
version: '1.0.0',
|
|
15
|
+
// `auth` owns the `requireAdmin` port the admin routes are gated by.
|
|
16
|
+
dependencies: ['auth'],
|
|
17
|
+
i18n: { bundlesDir: 'i18n' },
|
|
18
|
+
/**
|
|
19
|
+
* The `CUSTOM_FIELD_*` family — D-129's remaining sweep, Tier A
|
|
20
|
+
* (`specs/090-module-owned-error-codes/d129-sweep.md` §5.2, Appendix A;
|
|
21
|
+
* MR 3).
|
|
22
|
+
*
|
|
23
|
+
* All five were declared by `_i18n` until this merge request, not because
|
|
24
|
+
* anybody judged them the platform's but because the deleted prefix chain
|
|
25
|
+
* had no rule for them and its last line was `return 'core'`. **D-121 T1
|
|
26
|
+
* puts them here**: the noun in every one of them is a custom field — its
|
|
27
|
+
* definition, its key, its option set or a value being written against it —
|
|
28
|
+
* and this module owns the definition registry, the option rows and the
|
|
29
|
+
* validation service that decides all five refusals.
|
|
30
|
+
*
|
|
31
|
+
* **`CUSTOM_FIELD_VALUE_INVALID` is the one a raise-site count gets wrong,
|
|
32
|
+
* and it is the reason the family is declared as a family.** Five modules
|
|
33
|
+
* raise it — `catalog`, `customers`, `orders`, `organizations` and
|
|
34
|
+
* `quote_requests` — and not one of them decides it: each calls this
|
|
35
|
+
* module's validation seam over its own host rows and re-answers the
|
|
36
|
+
* failures it gets back. The judgement, the rules it is made against and the
|
|
37
|
+
* definitions those rules come from are all here, so T1 puts the code here
|
|
38
|
+
* and T2's "sole thrower" question never arises. `d129-sweep.md` §2.3 flags
|
|
39
|
+
* it by name for exactly that reason. `CUSTOM_FIELD_HOST_MANAGED` is the
|
|
40
|
+
* mirror image: it is raised only here, and it refuses a definition whose
|
|
41
|
+
* entity type another module manages — the marker is read
|
|
42
|
+
* entity-agnostically, so the refusal is about this registry rather than
|
|
43
|
+
* about whichever module happens to be named in it.
|
|
44
|
+
*
|
|
45
|
+
* **No sentence moves with them.** None of the five has a sentence in either
|
|
46
|
+
* language anywhere in the tree; all five were already on
|
|
47
|
+
* `UNTRANSLATED_ERROR_CODES` under `_i18n` and move to this module's group
|
|
48
|
+
* there, so the bundle this module already ships gains no key.
|
|
49
|
+
*
|
|
50
|
+
* **`tokens` is derived from the raise sites, not from the bundle**
|
|
51
|
+
* (runbook §5), and there are none to declare. `CUSTOM_FIELD_VALUE_INVALID`
|
|
52
|
+
* is the one that carries `details`, and it is the Zod-shaped
|
|
53
|
+
* `{ path, issue }[]` array, which `refusalToken` reads as no token at all
|
|
54
|
+
* (`packages/platform/src/http/error-envelope.ts`); the other four are bare
|
|
55
|
+
* `HttpError(status, code, message)`.
|
|
56
|
+
*/
|
|
57
|
+
errorCodes: [
|
|
58
|
+
{ code: 'CUSTOM_FIELD_DEFINITION_INVALID' },
|
|
59
|
+
{ code: 'CUSTOM_FIELD_HOST_MANAGED' },
|
|
60
|
+
{ code: 'CUSTOM_FIELD_KEY_CONFLICT' },
|
|
61
|
+
{ code: 'CUSTOM_FIELD_NOT_FOUND' },
|
|
62
|
+
{ code: 'CUSTOM_FIELD_VALUE_INVALID' },
|
|
63
|
+
],
|
|
64
|
+
permissions: [
|
|
65
|
+
{ code: 'custom_fields:read', label: 'View custom fields' },
|
|
66
|
+
{ code: 'custom_fields:write', label: 'Manage custom fields (definitions and options)' },
|
|
67
|
+
],
|
|
68
|
+
actions: [
|
|
69
|
+
{
|
|
70
|
+
id: 'open-custom-fields',
|
|
71
|
+
labelKey: 'actions.openCustomFields.label',
|
|
72
|
+
descriptionKey: 'actions.openCustomFields.description',
|
|
73
|
+
icon: 'Layers',
|
|
74
|
+
targetRoute: '/custom-fields',
|
|
75
|
+
requiredPermission: 'custom_fields:read',
|
|
76
|
+
keywords: ['custom fields', 'attributes', 'pola', 'niestandardowe'],
|
|
77
|
+
weight: 240,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
// Feature 074 (Constitution XVII), test C3 — platform primitive. The flag
|
|
81
|
+
// used to rest on `organizations` declaring this module; ruling 2 withdraws
|
|
82
|
+
// a dependent's authority to impose the lock, so the ground is now this
|
|
83
|
+
// module's own. It is Principle XIV's extensibility mechanism: the answer
|
|
84
|
+
// the platform gives to "add a field" instead of a bespoke column. Switching
|
|
85
|
+
// it off does not remove a capability a client chose, it makes the values
|
|
86
|
+
// already stored against every host entity unreachable.
|
|
87
|
+
/**
|
|
88
|
+
* Nothing to demonstrate of its own (feature 113, T224 — contract §1.2).
|
|
89
|
+
*
|
|
90
|
+
* The demo shop does have seven product-host custom-field definitions, and
|
|
91
|
+
* they are not this module's demo data: a product attribute is one of those
|
|
92
|
+
* definitions paired 1:1 with a `catalog` extension row and written in one
|
|
93
|
+
* call (feature 061), so it is two modules' rows in one statement and belongs
|
|
94
|
+
* to whoever owns the instance (§5.1). It is a step of
|
|
95
|
+
* `backend/src/seeds/demo-composition.ts`, guarded on both modules, and this
|
|
96
|
+
* module does not declare `catalog` — §2.3's rule that `demo` may not become a
|
|
97
|
+
* way of acquiring a dependency.
|
|
98
|
+
*
|
|
99
|
+
* That is a **correction to §3.3**, which proposed that this module seed the
|
|
100
|
+
* definitions and `catalog` seed the extensions behind an advisory `after`
|
|
101
|
+
* edge. `catalog` would then have had to read `custom_field_definitions` to
|
|
102
|
+
* find the id its extension row references, which §2.2 forbids, so the split
|
|
103
|
+
* has no implementation.
|
|
104
|
+
*
|
|
105
|
+
* `false` rather than absent, because the two are different states: this is a
|
|
106
|
+
* decision that the module owes nothing, not a module nobody has looked at.
|
|
107
|
+
*/
|
|
108
|
+
demo: false,
|
|
109
|
+
activation: {
|
|
110
|
+
nonDeactivatable: true,
|
|
111
|
+
reason: 'The platform\'s extensibility mechanism; the custom values already stored against ' +
|
|
112
|
+
'every host entity become unreachable without it.',
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* Hard-uninstall cleanup (feature 055). A soft uninstall keeps definitions so a
|
|
117
|
+
* re-install restores them; a hard uninstall drops all definitions (options
|
|
118
|
+
* cascade via FK). Host `custom_field_values` columns are owned by their host
|
|
119
|
+
* modules and removed with them, so nothing dangles either way.
|
|
120
|
+
*/
|
|
121
|
+
export const uninstallHook = async (ctx) => {
|
|
122
|
+
if (!ctx.hard)
|
|
123
|
+
return;
|
|
124
|
+
const em = ctx.em;
|
|
125
|
+
await em
|
|
126
|
+
.getConnection()
|
|
127
|
+
.execute('truncate table "custom_field_options", "custom_field_definitions" cascade');
|
|
128
|
+
ctx.log.info('custom_fields: removed all custom-field definitions on hard uninstall');
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAA4B,MAAM,4BAA4B,CAAC;AAG5F;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,oBAAoB,CAAC;IAC3C,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,0DAA0D;IACvE,OAAO,EAAE,OAAO;IAChB,qEAAqE;IACrE,YAAY,EAAE,CAAC,MAAM,CAAC;IACtB,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACH,UAAU,EAAE;QACV,EAAE,IAAI,EAAE,iCAAiC,EAAE;QAC3C,EAAE,IAAI,EAAE,2BAA2B,EAAE;QACrC,EAAE,IAAI,EAAE,2BAA2B,EAAE;QACrC,EAAE,IAAI,EAAE,wBAAwB,EAAE;QAClC,EAAE,IAAI,EAAE,4BAA4B,EAAE;KACvC;IACD,WAAW,EAAE;QACX,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,oBAAoB,EAAE;QAC3D,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,gDAAgD,EAAE;KACzF;IACD,OAAO,EAAE;QACP;YACE,EAAE,EAAE,oBAAoB;YACxB,QAAQ,EAAE,gCAAgC;YAC1C,cAAc,EAAE,sCAAsC;YACtD,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,gBAAgB;YAC7B,kBAAkB,EAAE,oBAAoB;YACxC,QAAQ,EAAE,CAAC,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,gBAAgB,CAAC;YACnE,MAAM,EAAE,GAAG;SACZ;KACF;IACD,0EAA0E;IAC1E,4EAA4E;IAC5E,wEAAwE;IACxE,0EAA0E;IAC1E,6EAA6E;IAC7E,0EAA0E;IAC1E,wDAAwD;IACxD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,IAAI,EAAE,KAAK;IACX,UAAU,EAAE;QACV,gBAAgB,EAAE,IAAI;QACtB,MAAM,EACJ,oFAAoF;YACpF,kDAAkD;KACrD;CACF,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAwB,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9D,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO;IACtB,MAAM,EAAE,GAAG,GAAG,CAAC,EAAmB,CAAC;IACnC,MAAM,EAAE;SACL,aAAa,EAAE;SACf,OAAO,CAAC,2EAA2E,CAAC,CAAC;IACxF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;AACxF,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* Feature 055 — Custom Fields Layer (init).
|
|
4
|
+
*
|
|
5
|
+
* Creates the two entity-agnostic module tables:
|
|
6
|
+
* - `custom_field_definitions` — operator-defined typed fields per host
|
|
7
|
+
* entity type (unique `(entity_type, key)`), with per-locale label +
|
|
8
|
+
* fallback, value type, required flag, ordering, and an opaque `config`
|
|
9
|
+
* JSONB for host-capability opt-in the generic core never interprets.
|
|
10
|
+
* - `custom_field_options` — select/multiselect option lists (unique
|
|
11
|
+
* `(definition_id, value)`, FK ON DELETE CASCADE).
|
|
12
|
+
*
|
|
13
|
+
* The per-host `custom_field_values` JSONB columns are added additively by the
|
|
14
|
+
* host modules (migrations 092–096). `product_attributes` is untouched (FR-011).
|
|
15
|
+
*/
|
|
16
|
+
export declare class Migration20260718T200338CustomFieldsInit extends Migration {
|
|
17
|
+
up(): Promise<void>;
|
|
18
|
+
down(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=20260718T200338_custom_fields_init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260718T200338_custom_fields_init.d.ts","sourceRoot":"","sources":["../../src/migrations/20260718T200338_custom_fields_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,qBAAa,wCAAyC,SAAQ,SAAS;IACtD,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAIrC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* Feature 055 — Custom Fields Layer (init).
|
|
4
|
+
*
|
|
5
|
+
* Creates the two entity-agnostic module tables:
|
|
6
|
+
* - `custom_field_definitions` — operator-defined typed fields per host
|
|
7
|
+
* entity type (unique `(entity_type, key)`), with per-locale label +
|
|
8
|
+
* fallback, value type, required flag, ordering, and an opaque `config`
|
|
9
|
+
* JSONB for host-capability opt-in the generic core never interprets.
|
|
10
|
+
* - `custom_field_options` — select/multiselect option lists (unique
|
|
11
|
+
* `(definition_id, value)`, FK ON DELETE CASCADE).
|
|
12
|
+
*
|
|
13
|
+
* The per-host `custom_field_values` JSONB columns are added additively by the
|
|
14
|
+
* host modules (migrations 092–096). `product_attributes` is untouched (FR-011).
|
|
15
|
+
*/
|
|
16
|
+
export class Migration20260718T200338CustomFieldsInit extends Migration {
|
|
17
|
+
async up() {
|
|
18
|
+
this.addSql(`
|
|
19
|
+
create table "custom_field_definitions" (
|
|
20
|
+
"id" uuid not null,
|
|
21
|
+
"entity_type" varchar(32) not null,
|
|
22
|
+
"key" varchar(64) not null,
|
|
23
|
+
"label" jsonb not null default '{}',
|
|
24
|
+
"label_default" varchar(200) not null,
|
|
25
|
+
"value_type" varchar(16) not null,
|
|
26
|
+
"required" boolean not null default false,
|
|
27
|
+
"sort_order" int not null default 0,
|
|
28
|
+
"config" jsonb not null default '{}',
|
|
29
|
+
"created_at" timestamptz not null,
|
|
30
|
+
"updated_at" timestamptz not null,
|
|
31
|
+
constraint "custom_field_definitions_pkey" primary key ("id")
|
|
32
|
+
);
|
|
33
|
+
`);
|
|
34
|
+
this.addSql(`alter table "custom_field_definitions" add constraint "custom_field_definitions_entity_key_unique" unique ("entity_type", "key");`);
|
|
35
|
+
this.addSql(`create index "custom_field_definitions_entity_type_idx" on "custom_field_definitions" ("entity_type");`);
|
|
36
|
+
this.addSql(`
|
|
37
|
+
create table "custom_field_options" (
|
|
38
|
+
"id" uuid not null,
|
|
39
|
+
"definition_id" uuid not null,
|
|
40
|
+
"value" varchar(200) not null,
|
|
41
|
+
"label" jsonb not null default '{}',
|
|
42
|
+
"label_default" varchar(200) not null,
|
|
43
|
+
"is_default" boolean not null default false,
|
|
44
|
+
"sort_order" int not null default 0,
|
|
45
|
+
"created_at" timestamptz not null,
|
|
46
|
+
"updated_at" timestamptz not null,
|
|
47
|
+
constraint "custom_field_options_pkey" primary key ("id")
|
|
48
|
+
);
|
|
49
|
+
`);
|
|
50
|
+
this.addSql(`alter table "custom_field_options" add constraint "custom_field_options_definition_value_unique" unique ("definition_id", "value");`);
|
|
51
|
+
this.addSql(`create index "custom_field_options_definition_idx" on "custom_field_options" ("definition_id");`);
|
|
52
|
+
this.addSql(`alter table "custom_field_options" add constraint "custom_field_options_definition_fk" ` +
|
|
53
|
+
`foreign key ("definition_id") references "custom_field_definitions" ("id") on delete cascade;`);
|
|
54
|
+
}
|
|
55
|
+
async down() {
|
|
56
|
+
this.addSql(`drop table if exists "custom_field_options" cascade;`);
|
|
57
|
+
this.addSql(`drop table if exists "custom_field_definitions" cascade;`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=20260718T200338_custom_fields_init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260718T200338_custom_fields_init.js","sourceRoot":"","sources":["../../src/migrations/20260718T200338_custom_fields_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,wCAAyC,SAAQ,SAAS;IAC5D,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;KAeX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CACT,mIAAmI,CACpI,CAAC;QACF,IAAI,CAAC,MAAM,CACT,wGAAwG,CACzG,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;KAaX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CACT,qIAAqI,CACtI,CAAC;QACF,IAAI,CAAC,MAAM,CACT,iGAAiG,CAClG,CAAC;QACF,IAAI,CAAC,MAAM,CACT,yFAAyF;YACvF,+FAA+F,CAClG,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,sDAAsD,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,CAAC,0DAA0D,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `./migrations` subpath — every migration class this module owns, as one
|
|
3
|
+
* ordered `migrations` array.
|
|
4
|
+
*
|
|
5
|
+
* The array is what the platform reads when this module is **installed**:
|
|
6
|
+
* `src/packages/package-runtime.ts` takes `exported['migrations']` and refuses
|
|
7
|
+
* the package outright when it is absent (D-168).
|
|
8
|
+
*
|
|
9
|
+
* Listed in ascending timestamp, which is the order of this module's own
|
|
10
|
+
* migrations and of nothing else (feature 081): a manifest `dependencies` array
|
|
11
|
+
* is the only thing ordering this block against another module's.
|
|
12
|
+
*
|
|
13
|
+
* The **named** exports stay beside the array, and the asymmetry with
|
|
14
|
+
* `./backend` — which publishes an array and no named class (D-168) — is
|
|
15
|
+
* deliberate. `db/migrations-registry.generated.ts` imports each class by name
|
|
16
|
+
* from this specifier, and a migration class name is contract in a way an entity
|
|
17
|
+
* class name is not: `mikro_orm_migrations` persists it, so it is a string every
|
|
18
|
+
* already-migrated database holds.
|
|
19
|
+
*
|
|
20
|
+
* A class that is in neither the array nor the barrel is a migration that does
|
|
21
|
+
* not run: `migration:pending` reports nothing pending and the first symptom is
|
|
22
|
+
* a query against a table nobody created.
|
|
23
|
+
*/
|
|
24
|
+
import { Migration20260718T200338CustomFieldsInit } from './20260718T200338_custom_fields_init.js';
|
|
25
|
+
export declare const migrations: (typeof Migration20260718T200338CustomFieldsInit)[];
|
|
26
|
+
export { Migration20260718T200338CustomFieldsInit, };
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AAEnG,eAAO,MAAM,UAAU,qDAEtB,CAAC;AAEF,OAAO,EACL,wCAAwC,GACzC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `./migrations` subpath — every migration class this module owns, as one
|
|
3
|
+
* ordered `migrations` array.
|
|
4
|
+
*
|
|
5
|
+
* The array is what the platform reads when this module is **installed**:
|
|
6
|
+
* `src/packages/package-runtime.ts` takes `exported['migrations']` and refuses
|
|
7
|
+
* the package outright when it is absent (D-168).
|
|
8
|
+
*
|
|
9
|
+
* Listed in ascending timestamp, which is the order of this module's own
|
|
10
|
+
* migrations and of nothing else (feature 081): a manifest `dependencies` array
|
|
11
|
+
* is the only thing ordering this block against another module's.
|
|
12
|
+
*
|
|
13
|
+
* The **named** exports stay beside the array, and the asymmetry with
|
|
14
|
+
* `./backend` — which publishes an array and no named class (D-168) — is
|
|
15
|
+
* deliberate. `db/migrations-registry.generated.ts` imports each class by name
|
|
16
|
+
* from this specifier, and a migration class name is contract in a way an entity
|
|
17
|
+
* class name is not: `mikro_orm_migrations` persists it, so it is a string every
|
|
18
|
+
* already-migrated database holds.
|
|
19
|
+
*
|
|
20
|
+
* A class that is in neither the array nor the barrel is a migration that does
|
|
21
|
+
* not run: `migration:pending` reports nothing pending and the first symptom is
|
|
22
|
+
* a query against a table nobody created.
|
|
23
|
+
*/
|
|
24
|
+
import { Migration20260718T200338CustomFieldsInit } from './20260718T200338_custom_fields_init.js';
|
|
25
|
+
export const migrations = [
|
|
26
|
+
Migration20260718T200338CustomFieldsInit,
|
|
27
|
+
];
|
|
28
|
+
export { Migration20260718T200338CustomFieldsInit, };
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AAEnG,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,wCAAwC;CACzC,CAAC;AAEF,OAAO,EACL,wCAAwC,GACzC,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The port interfaces `custom_fields` publishes, and **nothing that exists at
|
|
3
|
+
* runtime** (feature 080, T053(b); D-169, D-171).
|
|
4
|
+
*
|
|
5
|
+
* `tsc` compiles this file to `export {};`. That is the property D-171 makes
|
|
6
|
+
* the boundary decision on — *a subpath is contract surface iff the module it
|
|
7
|
+
* resolves to exports no runtime binding* — and it is why this declaration has
|
|
8
|
+
* its own file rather than sitting on top of `custom-field-definition.service.ts`,
|
|
9
|
+
* which exports the service class and an error class beside it. A consumer
|
|
10
|
+
* naming that file names the owner's implementation, whatever `import type`
|
|
11
|
+
* erases; a consumer naming this one names a declaration and can name nothing
|
|
12
|
+
* else.
|
|
13
|
+
*
|
|
14
|
+
* **This is not yet a supported specifier and the ledger still counts it.**
|
|
15
|
+
* `custom_fields` is not a workspace package, so there is no `exports` map for
|
|
16
|
+
* this to be a subpath of, and `check:module-boundary` reads `catalog`'s
|
|
17
|
+
* relative import exactly as it read the old one — D-171 says so in as many
|
|
18
|
+
* words: `resolveModulePackage` returns `null` for any specifier starting with
|
|
19
|
+
* `.`, so an unconverted reach has no subpath for the exemption to apply to,
|
|
20
|
+
* and reaching the exempt state takes three separable edits (package the owner,
|
|
21
|
+
* publish the interface, rewrite the specifier). This file is the second of
|
|
22
|
+
* those three, taken early because it is the one that does not need the module
|
|
23
|
+
* to move: when `custom_fields` is packaged, this directory becomes the
|
|
24
|
+
* package's `./ports` and the consumer's edit is one specifier.
|
|
25
|
+
*
|
|
26
|
+
* No entity class leaves by this door, type-only included (D-168).
|
|
27
|
+
*/
|
|
28
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
29
|
+
import type { CreateCustomFieldDefinitionRequest, CustomFieldDefinitionRecord, CustomFieldOptionDto, CustomFieldOptionRecord, SupportedEntityType, UpdateCustomFieldDefinitionRequest } from '@endora-commerce/contracts';
|
|
30
|
+
/**
|
|
31
|
+
* Container name: `customFieldDefinitionService`. Owner: `custom_fields`.
|
|
32
|
+
*
|
|
33
|
+
* Transactional apply seam for host modules (feature 061,
|
|
34
|
+
* contracts/custom-fields-product-host.md §3). Every `apply*` call runs inside
|
|
35
|
+
* the CALLER's transactional EM (a host Command's `run({ em })`), performs the
|
|
36
|
+
* same invariants as the public CRUD, and does NO command dispatch, NO audit
|
|
37
|
+
* (the host command audits the composite operation), and NO cache publish.
|
|
38
|
+
* The caller MUST invoke {@link CustomFieldDefinitionApplyApi.publishInvalidate}
|
|
39
|
+
* after its transaction commits.
|
|
40
|
+
*
|
|
41
|
+
* **Which transaction it runs in, said on this side too** (D-77). The caller's:
|
|
42
|
+
* a host Command's `run({ em })`, the same `EntityManager` the host writes its
|
|
43
|
+
* own row on. That is not a convenience — `fk_product_attributes_custom_field_definition`
|
|
44
|
+
* is `on delete restrict` with a `unique` on the same column, so the child
|
|
45
|
+
* insert must see its parent inside one transaction, and a second transaction
|
|
46
|
+
* cannot satisfy a foreign key against a row it cannot see. The seam is
|
|
47
|
+
* therefore permanent, declared, and named on both sides; what would retire it
|
|
48
|
+
* is F4's package entry points, or dropping the constraint.
|
|
49
|
+
*
|
|
50
|
+
* **The `EntityManager` is a required parameter on every `apply*` method and
|
|
51
|
+
* never an optional one** (D-169). Open Mercato's `transactionalEm?` is
|
|
52
|
+
* optional on the context *and* in the handler, so a caller may hand a
|
|
53
|
+
* transaction to a handler that ignores it and receive a silently non-atomic
|
|
54
|
+
* write. Do not relax this to match it.
|
|
55
|
+
*
|
|
56
|
+
* **This shape may not live in `@endora-commerce/contracts`**, which is the whole
|
|
57
|
+
* reason it is declared here: `admin` and `storefront` both compile that
|
|
58
|
+
* package, so it holds zero `@mikro-orm` imports and FR-034 keeps it that way.
|
|
59
|
+
* The qualifying test D-171 states is not *"is this a real published port"* but
|
|
60
|
+
* *"does this signature stop the interface living in `packages/contracts`"*,
|
|
61
|
+
* and seven of these eight methods do.
|
|
62
|
+
*
|
|
63
|
+
* **The returns are published records, not live entities** (D-77's first
|
|
64
|
+
* narrowing). A host reads `id`, `sortOrder`, `labelDefault` and the rest off
|
|
65
|
+
* what comes back; handing it a managed entity also handed it the ability to
|
|
66
|
+
* mutate a definition outside the seam, and the ability to persist that change
|
|
67
|
+
* on the transaction it happens to be holding.
|
|
68
|
+
*
|
|
69
|
+
* **The definition *read* is not here** and is not a seventh `apply*`. It is
|
|
70
|
+
* `CustomFieldDefinitionReadPort.getById` in `@endora-commerce/contracts`, under the
|
|
71
|
+
* container name `customFieldDefinitionReadPort`: a read handed an
|
|
72
|
+
* `EntityManager` is a write seam re-opened to serve a read (D-169), and until
|
|
73
|
+
* T053(b) this interface was where `catalog` got it, typed as a record and
|
|
74
|
+
* answered with the owner's two managed entities.
|
|
75
|
+
*
|
|
76
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
77
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`, so nothing
|
|
78
|
+
* half-executes. Whether `custom_fields` has an off state at all is its
|
|
79
|
+
* manifest's `activation` to say, not this line's: a module declaring
|
|
80
|
+
* `nonDeactivatable` never enters one.
|
|
81
|
+
*/
|
|
82
|
+
export interface CustomFieldDefinitionApplyApi {
|
|
83
|
+
applyCreate(em: EntityManager, input: CreateCustomFieldDefinitionRequest): Promise<CustomFieldDefinitionRecord>;
|
|
84
|
+
applyUpdate(em: EntityManager, id: string, patch: UpdateCustomFieldDefinitionRequest): Promise<CustomFieldDefinitionRecord>;
|
|
85
|
+
applyDelete(em: EntityManager, id: string): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Rename a definition's key — the one path by which a key changes after
|
|
88
|
+
* create, and **not** an edit: {@link applyUpdate}'s patch omits `key`
|
|
89
|
+
* deliberately, because every host stores its values under the key and an
|
|
90
|
+
* ordinary rename would orphan them (`specs/134-paid-module-extraction/`
|
|
91
|
+
* research D12).
|
|
92
|
+
*
|
|
93
|
+
* The caller is expected to rename the host's values **in the same
|
|
94
|
+
* transaction** — for `product`, through `catalog`'s value-key seam on
|
|
95
|
+
* `@endora-commerce/mod-catalog/ports` — and to call
|
|
96
|
+
* {@link publishInvalidate} after it commits.
|
|
97
|
+
*
|
|
98
|
+
* `expectedKey` is the key the caller planned from: a definition whose key
|
|
99
|
+
* has moved since is refused (`key_changed`) rather than renamed from a
|
|
100
|
+
* state the caller never saw. A key held by another definition of the same
|
|
101
|
+
* entity type is refused (`duplicate_key`), and so is one outside the key
|
|
102
|
+
* grammar (`invalid_key`). Flushes before it returns, so a two-phase rename
|
|
103
|
+
* (park every key, then move it) runs its statements in the order written.
|
|
104
|
+
*/
|
|
105
|
+
applyRenameKey(em: EntityManager, id: string, expectedKey: string, newKey: string): Promise<CustomFieldDefinitionRecord>;
|
|
106
|
+
applyCreateOption(em: EntityManager, definitionId: string, input: CustomFieldOptionDto): Promise<CustomFieldOptionRecord>;
|
|
107
|
+
applyUpdateOption(em: EntityManager, definitionId: string, optionId: string, patch: Partial<Pick<CustomFieldOptionDto, 'label' | 'labelDefault' | 'isDefault' | 'sortOrder'>>): Promise<CustomFieldOptionRecord>;
|
|
108
|
+
applyDeleteOption(em: EntityManager, definitionId: string, optionId: string): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Post-commit responsibility of the caller, and the one method here that
|
|
111
|
+
* takes no `EntityManager` — by construction, since it must run **after** the
|
|
112
|
+
* caller's transaction commits.
|
|
113
|
+
*
|
|
114
|
+
* It stays on the apply seam rather than moving to the read port with
|
|
115
|
+
* `getById`, because it is a step of this seam's protocol and not a question
|
|
116
|
+
* anybody else has: D-97.1 refused to publish the cache mechanism to
|
|
117
|
+
* consumers at all, and answers the reader's real question with
|
|
118
|
+
* `CustomFieldDefinitionReadPort.listForEntityFresh` instead. Only a caller
|
|
119
|
+
* that has just written through `apply*` owes this call.
|
|
120
|
+
*/
|
|
121
|
+
publishInvalidate(entityType: SupportedEntityType): Promise<void>;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,kCAAkC,EAClC,2BAA2B,EAC3B,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,kCAAkC,EACnC,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CACT,EAAE,EAAE,aAAa,EACjB,KAAK,EAAE,kCAAkC,GACxC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACxC,WAAW,CACT,EAAE,EAAE,aAAa,EACjB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,kCAAkC,GACxC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D;;;;;;;;;;;;;;;;;;OAkBG;IACH,cAAc,CACZ,EAAE,EAAE,aAAa,EACjB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACxC,iBAAiB,CACf,EAAE,EAAE,aAAa,EACjB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACpC,iBAAiB,CACf,EAAE,EAAE,aAAa,EACjB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,cAAc,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC,GAC/F,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACpC,iBAAiB,CAAC,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ports/index.ts"],"names":[],"mappings":""}
|
package/i18n/en.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"customFields.title": "Custom Fields",
|
|
3
|
+
"customFields.description": "Define runtime typed fields on core entities without a code change or migration.",
|
|
4
|
+
"customFields.entity.category": "Category",
|
|
5
|
+
"customFields.entity.order": "Order",
|
|
6
|
+
"customFields.entity.organization": "Organization",
|
|
7
|
+
"customFields.entity.customer": "Customer",
|
|
8
|
+
"customFields.entity.quoteRequest": "Quote request",
|
|
9
|
+
"customFields.entity.product": "Product",
|
|
10
|
+
"customFields.managedBy.catalogAttributes": "Managed on Catalog → Attributes",
|
|
11
|
+
"customFields.managedBy.notice": "Definitions for this entity type are managed by another module and are read-only here.",
|
|
12
|
+
"actions.openCustomFields.label": "Custom fields",
|
|
13
|
+
"actions.openCustomFields.description": "Define runtime fields on core entities.",
|
|
14
|
+
"nav.customFields.label": "Custom Fields"
|
|
15
|
+
}
|
package/i18n/pl.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"customFields.title": "Pola niestandardowe",
|
|
3
|
+
"customFields.description": "Definiuj typowane pola na kluczowych encjach bez zmiany kodu i migracji.",
|
|
4
|
+
"customFields.entity.category": "Kategoria",
|
|
5
|
+
"customFields.entity.order": "Zamówienie",
|
|
6
|
+
"customFields.entity.organization": "Organizacja",
|
|
7
|
+
"customFields.entity.customer": "Klient",
|
|
8
|
+
"customFields.entity.quoteRequest": "Zapytanie ofertowe",
|
|
9
|
+
"customFields.entity.product": "Produkt",
|
|
10
|
+
"customFields.managedBy.catalogAttributes": "Zarządzane w Katalog → Atrybuty",
|
|
11
|
+
"customFields.managedBy.notice": "Definicje dla tego typu encji są zarządzane przez inny moduł i są tutaj tylko do odczytu.",
|
|
12
|
+
"actions.openCustomFields.label": "Pola niestandardowe",
|
|
13
|
+
"actions.openCustomFields.description": "Definiuj pola na kluczowych encjach.",
|
|
14
|
+
"nav.customFields.label": "Pola niestandardowe"
|
|
15
|
+
}
|