@adobe/spacecat-shared-data-access 4.4.0 → 4.6.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/CHANGELOG.md +12 -0
- package/CLAUDE.md +2 -1
- package/package.json +1 -1
- package/src/models/plg-onboarding/plg-onboarding.schema.js +1 -0
- package/src/models/site/config.js +1 -3
- package/src/models/suggestion/derive-status.js +97 -51
- package/src/models/suggestion/index.d.ts +5 -1
- package/src/models/suggestion/index.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [@adobe/spacecat-shared-data-access-v4.6.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.5.0...@adobe/spacecat-shared-data-access-v4.6.0) (2026-07-12)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* added non prod domain in plg onboarding steps ([#1750](https://github.com/adobe/spacecat-shared/issues/1750)) ([3f56508](https://github.com/adobe/spacecat-shared/commit/3f56508a47ffd4b92584c424fcb7876bddd48838))
|
|
6
|
+
|
|
7
|
+
## [@adobe/spacecat-shared-data-access-v4.5.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.4.0...@adobe/spacecat-shared-data-access-v4.5.0) (2026-07-10)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **data-access:** generalize deriveSuggestionStatus bubble-up + classifyStatus (SITES-47285) ([#1797](https://github.com/adobe/spacecat-shared/issues/1797)) ([732f647](https://github.com/adobe/spacecat-shared/commit/732f647724d1922f70d32b42fedd46824b0c1bde))
|
|
12
|
+
|
|
1
13
|
## [@adobe/spacecat-shared-data-access-v4.4.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.3.1...@adobe/spacecat-shared-data-access-v4.4.0) (2026-07-09)
|
|
2
14
|
|
|
3
15
|
### Features
|
package/CLAUDE.md
CHANGED
|
@@ -237,7 +237,8 @@ Rollout intent: ship `warn` to surface today's illegal transitions in logs for
|
|
|
237
237
|
**APIs** (exported from the package root):
|
|
238
238
|
- `setStatus(value)` / `transitionStatus(to)` on `Suggestion` and `FixEntity` — both guard the transition; `transitionStatus` is the intention-revealing alias for new code.
|
|
239
239
|
- `isAllowedFixTransition(from, to)` / `isAllowedSuggestionTransition(from, to)` + the `FIX_ENTITY_TRANSITIONS` / `SUGGESTION_TRANSITIONS` tables (a null/undefined `from` means entity creation).
|
|
240
|
-
- `deriveSuggestionStatus(
|
|
240
|
+
- `deriveSuggestionStatus(outcomes, issues = [], currentStatus = null)` — derives a Suggestion status from a per-suggestion list of **outcome signals**. Each entry is a FixEntity, `{status}`, or a status string from **either** vocabulary: FixEntity statuses (`DEPLOYED`/`PUBLISHED`→FIXED, `FAILED`→ERROR, `PENDING`→IN_PROGRESS, `ROLLED_BACK`/`REJECTED`→SKIPPED) **or** explicit Suggestion-status outcomes a handler asserts for no-fix cases (e.g. consciously skipped → `'SKIPPED'`, not-actionable → `'NEW'`). Signals are classified via `classifyStatus` and collapsed **first-match-wins by severity: ERROR > IN_PROGRESS > FIXED > SKIPPED**; all-NEUTRAL (e.g. only `NEW`) → `NEW`; no recognized signals → `currentStatus` (default null, so a derive call never clobbers a status set elsewhere). **Throws** if a non-empty `issues` array is passed — the CWV multi-issue bubble-up is deferred (SITES-47285): the per-issue codefix vocabulary (`PATCH_*`/`GUIDANCE_GENERATED`, written by mystique into the overloaded `issue.status` field) is not yet reconciled with the JS layer.
|
|
241
|
+
- `classifyStatus(token)` — maps a fix- or suggestion-status token to its severity class (`ERROR`/`IN_PROGRESS`/`FIXED`/`SKIPPED`/`NEUTRAL`) or `null`. The shared building block behind the bubble-up; consumers building custom collapses should reuse it rather than re-encode the mapping.
|
|
241
242
|
|
|
242
243
|
Notes: the `FixEntity` table is the canonical one from the ADR; the `Suggestion`
|
|
243
244
|
table is intentionally **permissive in V1** (tune it from the warn-log findings
|
package/package.json
CHANGED
|
@@ -69,6 +69,7 @@ const schema = new SchemaBuilder(PlgOnboarding, PlgOnboardingCollection)
|
|
|
69
69
|
entitlementFailed: { type: 'boolean' },
|
|
70
70
|
orgResolutionFailed: { type: 'boolean' },
|
|
71
71
|
preOnboarded: { type: 'boolean' },
|
|
72
|
+
nonProdCheckBypassed: { type: 'boolean' },
|
|
72
73
|
},
|
|
73
74
|
})
|
|
74
75
|
.addAttribute('error', {
|
|
@@ -477,9 +477,7 @@ export const configSchema = Joi.object({
|
|
|
477
477
|
storeCode: Joi.string().required(),
|
|
478
478
|
storeViewCode: Joi.string().required(),
|
|
479
479
|
hostName: Joi.string().optional(),
|
|
480
|
-
|
|
481
|
-
magentoAPIKey: Joi.string().optional(),
|
|
482
|
-
}),
|
|
480
|
+
}).options({ stripUnknown: true }),
|
|
483
481
|
).optional(),
|
|
484
482
|
contentAiConfig: Joi.object({
|
|
485
483
|
index: Joi.string().optional(),
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Suggestion
|
|
14
|
+
* Suggestion status literals (return values).
|
|
15
15
|
*
|
|
16
|
-
* Duplicated from the model
|
|
17
|
-
* Keep in sync if
|
|
16
|
+
* Duplicated from the model enum to keep this a dependency-light pure module.
|
|
17
|
+
* Keep in sync if the enum changes. (Same pattern as suggestion.data-schemas.js.)
|
|
18
18
|
*/
|
|
19
19
|
const SUGGESTION = {
|
|
20
20
|
NEW: 'NEW',
|
|
@@ -24,89 +24,135 @@ const SUGGESTION = {
|
|
|
24
24
|
ERROR: 'ERROR',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Severity classes for the bubble-up (ADR adobe/mysticat-architecture#174).
|
|
29
|
+
* Highest severity first-match-wins; NEUTRAL never contributes to severity
|
|
30
|
+
* (a suggestion whose only signals are NEUTRAL resolves to NEW).
|
|
31
|
+
*/
|
|
32
|
+
const CLASS = {
|
|
33
|
+
ERROR: 'ERROR',
|
|
34
|
+
IN_PROGRESS: 'IN_PROGRESS',
|
|
35
|
+
FIXED: 'FIXED',
|
|
36
|
+
SKIPPED: 'SKIPPED',
|
|
37
|
+
NEUTRAL: 'NEUTRAL',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Maps a status token to its severity class. Covers BOTH vocabularies so a
|
|
42
|
+
* caller can pass FixEntity statuses (DEPLOYED/FAILED/PENDING/ROLLED_BACK/...)
|
|
43
|
+
* and/or explicit Suggestion-status outcomes (FIXED/ERROR/SKIPPED/NEW/...) for
|
|
44
|
+
* cases with no fix entity (e.g. a consciously-skipped or not-actionable
|
|
45
|
+
* suggestion). `REJECTED` collapses to SKIPPED in either vocabulary. Unknown
|
|
46
|
+
* tokens are ignored (null).
|
|
47
|
+
*/
|
|
48
|
+
const CLASS_BY_STATUS = {
|
|
49
|
+
// ERROR-class
|
|
50
|
+
FAILED: CLASS.ERROR, // fix
|
|
51
|
+
ERROR: CLASS.ERROR, // suggestion
|
|
52
|
+
// IN_PROGRESS-class
|
|
53
|
+
PENDING: CLASS.IN_PROGRESS, // fix
|
|
54
|
+
IN_PROGRESS: CLASS.IN_PROGRESS, // suggestion
|
|
55
|
+
// FIXED-class
|
|
56
|
+
DEPLOYED: CLASS.FIXED, // fix
|
|
57
|
+
PUBLISHED: CLASS.FIXED, // fix
|
|
58
|
+
FIXED: CLASS.FIXED, // suggestion
|
|
59
|
+
// SKIPPED-class
|
|
60
|
+
ROLLED_BACK: CLASS.SKIPPED, // fix
|
|
61
|
+
REJECTED: CLASS.SKIPPED, // fix / suggestion
|
|
62
|
+
SKIPPED: CLASS.SKIPPED, // suggestion
|
|
63
|
+
// NEUTRAL — present but non-severity; all-NEUTRAL resolves to NEW
|
|
64
|
+
NEW: CLASS.NEUTRAL,
|
|
65
|
+
OUTDATED: CLASS.NEUTRAL,
|
|
66
|
+
APPROVED: CLASS.NEUTRAL,
|
|
67
|
+
PENDING_VALIDATION: CLASS.NEUTRAL,
|
|
33
68
|
};
|
|
34
69
|
|
|
35
70
|
/**
|
|
36
|
-
*
|
|
71
|
+
* Classifies a status token into its bubble-up severity class, or null if the
|
|
72
|
+
* token is unknown.
|
|
73
|
+
*
|
|
74
|
+
* @param {string|null|undefined} token
|
|
75
|
+
* @returns {'ERROR'|'IN_PROGRESS'|'FIXED'|'SKIPPED'|'NEUTRAL'|null}
|
|
76
|
+
*/
|
|
77
|
+
export const classifyStatus = (token) => (
|
|
78
|
+
Object.prototype.hasOwnProperty.call(CLASS_BY_STATUS, token)
|
|
79
|
+
? CLASS_BY_STATUS[token]
|
|
80
|
+
: null
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Normalizes an outcome entry to its status string. Accepts a FixEntity model
|
|
37
85
|
* instance (`getStatus()`), a plain `{ status }` object, or a status string.
|
|
38
86
|
*/
|
|
39
|
-
const toStatus = (
|
|
40
|
-
if (typeof
|
|
41
|
-
return
|
|
87
|
+
const toStatus = (outcome) => {
|
|
88
|
+
if (typeof outcome === 'string') {
|
|
89
|
+
return outcome;
|
|
42
90
|
}
|
|
43
|
-
if (
|
|
44
|
-
return
|
|
91
|
+
if (outcome && typeof outcome.getStatus === 'function') {
|
|
92
|
+
return outcome.getStatus();
|
|
45
93
|
}
|
|
46
|
-
return
|
|
94
|
+
return outcome?.status;
|
|
47
95
|
};
|
|
48
96
|
|
|
49
97
|
/**
|
|
50
|
-
* Derives a Suggestion's status from
|
|
51
|
-
* bubble-up from ADR adobe/mysticat-architecture#174
|
|
52
|
-
* opportunities)":
|
|
98
|
+
* Derives a Suggestion's status from a per-suggestion list of outcome signals —
|
|
99
|
+
* the bubble-up from ADR adobe/mysticat-architecture#174.
|
|
53
100
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
101
|
+
* Each `outcomes` entry is a FixEntity, a `{ status }` object, or a status
|
|
102
|
+
* string, from EITHER vocabulary:
|
|
103
|
+
* - FixEntity statuses: DEPLOYED/PUBLISHED -> FIXED, FAILED -> ERROR,
|
|
104
|
+
* PENDING -> IN_PROGRESS, ROLLED_BACK/REJECTED -> SKIPPED.
|
|
105
|
+
* - explicit Suggestion-status outcomes for no-fix cases a handler asserts
|
|
106
|
+
* (e.g. a consciously skipped suggestion -> 'SKIPPED', a not-actionable one
|
|
107
|
+
* -> 'NEW').
|
|
59
108
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
109
|
+
* Signals are classified (`classifyStatus`) and collapsed **first-match-wins by
|
|
110
|
+
* severity**: ERROR > IN_PROGRESS > FIXED > SKIPPED. If signals are present but
|
|
111
|
+
* all NEUTRAL (e.g. only 'NEW') the result is NEW. If there are no recognized
|
|
112
|
+
* signals (empty / all-null / all-unknown) the result is `currentStatus`
|
|
113
|
+
* (default null), so a derive call never clobbers a status set elsewhere.
|
|
64
114
|
*
|
|
65
115
|
* The **CWV multi-issue** bubble-up is deliberately NOT implemented here: the
|
|
66
|
-
*
|
|
67
|
-
* / PATCH_FAILED_*)
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* SITES-47285. Passing a non-empty `issues` argument throws to prevent a caller
|
|
71
|
-
* from silently receiving an unimplemented CWV result.
|
|
116
|
+
* per-issue vocabulary (mystique's cwvIssueStatus = PATCH_GENERATED /
|
|
117
|
+
* GUIDANCE_* / PATCH_FAILED_*) is not yet reconciled with the JS layer
|
|
118
|
+
* (SITES-47285). Passing a non-empty `issues` argument throws to prevent a
|
|
119
|
+
* caller from silently receiving an unimplemented CWV result.
|
|
72
120
|
*
|
|
73
|
-
* @param {Array<object|string>}
|
|
121
|
+
* @param {Array<object|string>} outcomes - fix entities / `{status}` / status strings
|
|
74
122
|
* @param {Array<object>} [issues] - CWV per-issue data; MUST be empty for now
|
|
75
|
-
* @param {string|null} [currentStatus] -
|
|
76
|
-
*
|
|
77
|
-
* call never clobbers a status set elsewhere. Defaults to null (prior behavior).
|
|
78
|
-
* @returns {string|null} derived Suggestion status, or `currentStatus` when nothing is derivable
|
|
123
|
+
* @param {string|null} [currentStatus] - fallback when nothing is derivable
|
|
124
|
+
* @returns {string|null} derived Suggestion status, or `currentStatus`
|
|
79
125
|
* @throws {Error} if a non-empty `issues` array is supplied (CWV deferred)
|
|
80
126
|
*/
|
|
81
|
-
export const deriveSuggestionStatus = (
|
|
127
|
+
export const deriveSuggestionStatus = (outcomes, issues = [], currentStatus = null) => {
|
|
82
128
|
if (Array.isArray(issues) && issues.length > 0) {
|
|
83
129
|
throw new Error('deriveSuggestionStatus: CWV multi-issue bubble-up is not yet implemented (deferred to SITES-47285)');
|
|
84
130
|
}
|
|
85
131
|
|
|
86
|
-
if (!Array.isArray(
|
|
132
|
+
if (!Array.isArray(outcomes)) {
|
|
87
133
|
return currentStatus;
|
|
88
134
|
}
|
|
89
135
|
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (statuses.length === 0) {
|
|
136
|
+
// Classify each signal; drop unknown/null so one malformed entry cannot
|
|
137
|
+
// nullify an otherwise well-defined derivation.
|
|
138
|
+
const classes = outcomes.map(toStatus).map(classifyStatus).filter((c) => c != null);
|
|
139
|
+
if (classes.length === 0) {
|
|
95
140
|
return currentStatus;
|
|
96
141
|
}
|
|
97
142
|
|
|
98
|
-
if (
|
|
143
|
+
if (classes.includes(CLASS.ERROR)) {
|
|
99
144
|
return SUGGESTION.ERROR;
|
|
100
145
|
}
|
|
101
|
-
if (
|
|
146
|
+
if (classes.includes(CLASS.IN_PROGRESS)) {
|
|
102
147
|
return SUGGESTION.IN_PROGRESS;
|
|
103
148
|
}
|
|
104
|
-
if (
|
|
149
|
+
if (classes.includes(CLASS.FIXED)) {
|
|
105
150
|
return SUGGESTION.FIXED;
|
|
106
151
|
}
|
|
107
|
-
if (
|
|
152
|
+
if (classes.includes(CLASS.SKIPPED)) {
|
|
108
153
|
return SUGGESTION.SKIPPED;
|
|
109
154
|
}
|
|
110
155
|
|
|
111
|
-
|
|
156
|
+
// signals present but all NEUTRAL (e.g. only NEW/OUTDATED)
|
|
157
|
+
return SUGGESTION.NEW;
|
|
112
158
|
};
|
|
@@ -45,6 +45,10 @@ export declare function isAllowedSuggestionTransition(
|
|
|
45
45
|
to: string,
|
|
46
46
|
): boolean;
|
|
47
47
|
export declare function deriveSuggestionStatus(
|
|
48
|
-
|
|
48
|
+
outcomes: Array<FixEntity | { status?: string } | string>,
|
|
49
49
|
issues?: Array<object>,
|
|
50
|
+
currentStatus?: string | null,
|
|
50
51
|
): string | null;
|
|
52
|
+
export declare function classifyStatus(
|
|
53
|
+
token: string | null | undefined,
|
|
54
|
+
): 'ERROR' | 'IN_PROGRESS' | 'FIXED' | 'SKIPPED' | 'NEUTRAL' | null;
|