@adobe/acc-js-sdk 1.1.61 → 1.2.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.
Files changed (62) hide show
  1. package/.cursor/commands/opsx-apply.md +152 -0
  2. package/.cursor/commands/opsx-archive.md +157 -0
  3. package/.cursor/commands/opsx-explore.md +173 -0
  4. package/.cursor/commands/opsx-propose.md +106 -0
  5. package/.cursor/skills/openspec-apply-change/SKILL.md +156 -0
  6. package/.cursor/skills/openspec-archive-change/SKILL.md +114 -0
  7. package/.cursor/skills/openspec-explore/SKILL.md +288 -0
  8. package/.cursor/skills/openspec-propose/SKILL.md +110 -0
  9. package/.eslintrc.js +2 -2
  10. package/.github/prompts/opsx-apply.prompt.md +149 -0
  11. package/.github/prompts/opsx-archive.prompt.md +154 -0
  12. package/.github/prompts/opsx-explore.prompt.md +170 -0
  13. package/.github/prompts/opsx-propose.prompt.md +103 -0
  14. package/.github/skills/openspec-apply-change/SKILL.md +156 -0
  15. package/.github/skills/openspec-archive-change/SKILL.md +114 -0
  16. package/.github/skills/openspec-explore/SKILL.md +288 -0
  17. package/.github/skills/openspec-propose/SKILL.md +110 -0
  18. package/.github/workflows/codeql-analysis.yml +5 -4
  19. package/.github/workflows/npm-publish.yml +3 -3
  20. package/AGENTS.md +117 -0
  21. package/CLAUDE.md +2 -0
  22. package/MIGRATION.md +10 -0
  23. package/README.md +6 -2
  24. package/ai-docs/coding-rules.md +95 -0
  25. package/ai-docs/tech-stack.md +43 -0
  26. package/babel.config.js +5 -0
  27. package/docs/changeLog.html +34 -0
  28. package/docs/checkList.html +2 -2
  29. package/docs/connectionParameters.html +5 -0
  30. package/docs/quickstart.html +2 -1
  31. package/docs/release.html +1 -1
  32. package/openspec/config.yaml +20 -0
  33. package/package-lock.json +7437 -3924
  34. package/package.json +9 -7
  35. package/src/AGENTS.md +98 -0
  36. package/src/CLAUDE.md +2 -0
  37. package/src/application.js +637 -637
  38. package/src/cache.js +133 -133
  39. package/src/cacheRefresher.js +190 -190
  40. package/src/campaign.js +532 -532
  41. package/src/client.js +1539 -1532
  42. package/src/crypto.js +52 -52
  43. package/src/domUtil.js +346 -346
  44. package/src/entityAccessor.js +61 -61
  45. package/src/index.js +83 -83
  46. package/src/methodCache.js +69 -69
  47. package/src/optionCache.js +26 -26
  48. package/src/soap.js +321 -322
  49. package/src/testUtil.js +13 -13
  50. package/src/transport.js +70 -70
  51. package/src/util.js +147 -147
  52. package/src/web/bundler.js +5 -5
  53. package/src/xtkCaster.js +258 -258
  54. package/src/xtkEntityCache.js +34 -34
  55. package/src/xtkJob.js +185 -185
  56. package/test/AGENTS.md +37 -0
  57. package/test/CLAUDE.md +2 -0
  58. package/test/cacheRefresher.test.js +7 -0
  59. package/test/client.test.js +123 -81
  60. package/test/jest.config.js +6 -0
  61. package/test/observability.test.js +6 -1
  62. package/test/xtkJob.test.js +2 -2
@@ -10,22 +10,22 @@ OF ANY KIND, either express or implied. See the License for the specific languag
10
10
  governing permissions and limitations under the License.
11
11
  */
12
12
  (function () {
13
- "use strict";
13
+ "use strict";
14
14
 
15
- const { DomUtil } = require("./domUtil.js");
16
- const XtkCaster = require('./xtkCaster.js').XtkCaster;
17
- const { Cache } = require('./cache.js');
18
- const { CampaignException } = require('./campaign.js');
15
+ const { DomUtil } = require("./domUtil.js");
16
+ const XtkCaster = require('./xtkCaster.js').XtkCaster;
17
+ const { Cache } = require('./cache.js');
18
+ const { CampaignException } = require('./campaign.js');
19
19
 
20
- /**
20
+ /**
21
21
  * @private
22
22
  * @class
23
23
  * @constructor
24
24
  * @memberof Campaign
25
25
  */
26
- class RefresherStateCache extends Cache {
26
+ class RefresherStateCache extends Cache {
27
27
 
28
- /**
28
+ /**
29
29
  * A cache to store state of the refresher. Not intended to be used directly,
30
30
  * but an internal cache for the Campaign.Client object
31
31
  *
@@ -37,33 +37,33 @@ governing permissions and limitations under the License.
37
37
  * @param {string} rootKey is an optional root key to use for the storage object
38
38
  * @param {number} ttl is the TTL for objects in ms. Defaults to 5 mins
39
39
  */
40
- constructor(storage, rootKey, ttl) {
41
- super(storage, rootKey, ttl);
42
- }
40
+ constructor(storage, rootKey, ttl) {
41
+ super(storage, rootKey, ttl);
42
+ }
43
43
 
44
- /**
44
+ /**
45
45
  * Cache a property of the refresh (buildNumber, last refresh time) and its value
46
46
  *
47
47
  * @param {string} name is the propertie name
48
48
  * @param {string} rawValue string value
49
49
  */
50
- async put(name, rawValue) {
51
- return super.put(name, { value: rawValue });
52
- }
50
+ async put(name, rawValue) {
51
+ return super.put(name, { value: rawValue });
52
+ }
53
53
 
54
- /**
54
+ /**
55
55
  * Get the value of a property of the refresh (buildNumber, last refresh time)
56
56
  *
57
57
  * @param {string} name the propertie name
58
58
  * @returns {*} the value
59
59
  */
60
- async get(name) {
61
- const option = await super.get(name);
62
- return option ? option.value : undefined;
63
- }
60
+ async get(name) {
61
+ const option = await super.get(name);
62
+ return option ? option.value : undefined;
64
63
  }
64
+ }
65
65
 
66
- /**
66
+ /**
67
67
  * A class to refresh regulary a Cache every n seconds, by sending a query to get the last modified entities.
68
68
  * The refresh mechanism can be activated by calling client.startRefreshCaches().
69
69
  * This mechanism depends on the xtk:session:GetModifiedEntities API which is introduced in ACC 8.4 and above.
@@ -76,200 +76,200 @@ governing permissions and limitations under the License.
76
76
  * @param {string} cacheSchemaId is the id of the schema present in the cache to be refreshed every 10 seconds
77
77
  * @param {string} rootKey is used as the root key of cache items in the refresher state cache
78
78
  */
79
- class CacheRefresher {
79
+ class CacheRefresher {
80
80
 
81
- constructor(cache, client, cacheSchemaId, rootKey) {
82
- const connectionParameters = client._connectionParameters;
83
- this._cache = cache;
84
- this._client = client;
85
- this._connectionParameters = connectionParameters;
86
- this._cacheSchemaId = cacheSchemaId;
81
+ constructor(cache, client, cacheSchemaId, rootKey) {
82
+ const connectionParameters = client._connectionParameters;
83
+ this._cache = cache;
84
+ this._client = client;
85
+ this._connectionParameters = connectionParameters;
86
+ this._cacheSchemaId = cacheSchemaId;
87
87
 
88
- this._storage = connectionParameters._options._storage;
89
- this._refresherStateCache = new RefresherStateCache(this._storage, `${rootKey}.RefresherStateCache`, 1000*3600);
88
+ this._storage = connectionParameters._options._storage;
89
+ this._refresherStateCache = new RefresherStateCache(this._storage, `${rootKey}.RefresherStateCache`, 1000*3600);
90
90
 
91
- this._lastTime = undefined;
92
- this._buildNumber = undefined;
93
- this._intervalId = null;
94
- this._running = false;
95
- }
91
+ this._lastTime = undefined;
92
+ this._buildNumber = undefined;
93
+ this._intervalId = null;
94
+ this._running = false;
95
+ }
96
96
 
97
- /**
97
+ /**
98
98
  * Start auto refresh
99
99
  * @param {integer} refreshFrequency frequency of the refresh in ms (default value is 10,000 ms)
100
100
  */
101
- startAutoRefresh(refreshFrequency) {
102
- this._client._trackEvent('CACHE_REFRESHER//start', undefined, {
103
- cacheSchemaId: this._cacheSchemaId,
104
- refreshFrequency: refreshFrequency
105
- });
106
- if (this._intervalId != null) {
107
- clearInterval(this._intervalId);
108
- }
109
- this._intervalId = setInterval(() => {
110
- this._safeCallAndRefresh();
111
- }, refreshFrequency || 10000); // every 10 seconds by default
112
- }
101
+ startAutoRefresh(refreshFrequency) {
102
+ this._client._trackEvent('CACHE_REFRESHER//start', undefined, {
103
+ cacheSchemaId: this._cacheSchemaId,
104
+ refreshFrequency: refreshFrequency
105
+ });
106
+ if (this._intervalId != null) {
107
+ clearInterval(this._intervalId);
108
+ }
109
+ this._intervalId = setInterval(() => {
110
+ this._safeCallAndRefresh();
111
+ }, refreshFrequency || 10000); // every 10 seconds by default
112
+ }
113
113
 
114
- // Protect _callAndRefresh from reentrance
115
- async _safeCallAndRefresh() {
116
- if (this._running) {
117
- // This call is already running and maybe taking a long time to complete. Do not make things
118
- // harder and just skip this run
119
- this._client._trackEvent('CACHE_REFRESHER//skip', undefined, {
120
- cacheSchemaId: this._cacheSchemaId,
121
- });
122
- return;
123
- }
124
- this._running = true;
125
- try {
126
- await this._callAndRefresh();
127
- } catch(ex) {
128
- if (ex.errorCode === "SDK-000010") {
129
- // client is not logged, this is not an error.
130
- this._client._trackEvent('CACHE_REFRESHER//loggedOff', undefined, {
131
- cacheSchemaId: this._cacheSchemaId,
132
- });
133
- return;
134
- }
135
- this._client._trackEvent('CACHE_REFRESHER//error', undefined, {
136
- cacheSchemaId: this._cacheSchemaId,
137
- error: ex,
138
- });
139
- console.warn(`Failed to refresh cache for ${this._cacheSchemaId}`, ex);
140
- }
141
- finally {
142
- this._running = false;
143
- }
114
+ // Protect _callAndRefresh from reentrance
115
+ async _safeCallAndRefresh() {
116
+ if (this._running) {
117
+ // This call is already running and maybe taking a long time to complete. Do not make things
118
+ // harder and just skip this run
119
+ this._client._trackEvent('CACHE_REFRESHER//skip', undefined, {
120
+ cacheSchemaId: this._cacheSchemaId,
121
+ });
122
+ return;
123
+ }
124
+ this._running = true;
125
+ try {
126
+ await this._callAndRefresh();
127
+ } catch(ex) {
128
+ if (ex.errorCode === "SDK-000010") {
129
+ // client is not logged, this is not an error.
130
+ this._client._trackEvent('CACHE_REFRESHER//loggedOff', undefined, {
131
+ cacheSchemaId: this._cacheSchemaId,
132
+ });
133
+ return;
144
134
  }
135
+ this._client._trackEvent('CACHE_REFRESHER//error', undefined, {
136
+ cacheSchemaId: this._cacheSchemaId,
137
+ error: ex,
138
+ });
139
+ console.warn(`Failed to refresh cache for ${this._cacheSchemaId}`, ex);
140
+ }
141
+ finally {
142
+ this._running = false;
143
+ }
144
+ }
145
145
 
146
- // Get last modified entities for the Campaign server and remove from cache last modified entities
147
- async _callAndRefresh() {
148
- const that = this;
149
- const soapCall = this._client._prepareSoapCall("xtk:session", "GetModifiedEntities", true, true, this._connectionParameters._options.extraHttpHeaders);
146
+ // Get last modified entities for the Campaign server and remove from cache last modified entities
147
+ async _callAndRefresh() {
148
+ const that = this;
149
+ const soapCall = this._client._prepareSoapCall("xtk:session", "GetModifiedEntities", true, true, this._connectionParameters._options.extraHttpHeaders);
150
150
 
151
- if (this._lastTime === undefined) {
152
- const storedTime = await this._refresherStateCache.get("time");
153
- if (storedTime != undefined) {
154
- this._lastTime = storedTime;
155
- }
156
- }
157
- if (this._buildNumber === undefined) {
158
- const storedBuildNumber = await this._refresherStateCache.get("buildNumber");
159
- if (storedBuildNumber != undefined) {
160
- this._buildNumber = storedBuildNumber;
161
- }
162
- }
151
+ if (this._lastTime === undefined) {
152
+ const storedTime = await this._refresherStateCache.get("time");
153
+ if (storedTime != undefined) {
154
+ this._lastTime = storedTime;
155
+ }
156
+ }
157
+ if (this._buildNumber === undefined) {
158
+ const storedBuildNumber = await this._refresherStateCache.get("buildNumber");
159
+ if (storedBuildNumber != undefined) {
160
+ this._buildNumber = storedBuildNumber;
161
+ }
162
+ }
163
163
 
164
- // Extract namespace from the cacheSchemaId
165
- const namespace = this._cacheSchemaId.split(":")[0];
164
+ // Extract namespace from the cacheSchemaId
165
+ const namespace = this._cacheSchemaId.split(":")[0];
166
166
 
167
- // Use Json because xtk:schema does not work directly in DomUtil.parse(`<cache buildNumber="9469" time="2022-06-30T00:00:00.000"><xtk:schema xmlns:xtk="urn:xtk:schema"></xtk:schema></cache>`);
168
- // due to the colon character
169
- let jsonCache;
170
- if (this._lastTime === undefined || this._buildNumber === undefined) {
171
- jsonCache = {
172
- [this._cacheSchemaId]: {
173
- [`xmlns:${namespace}`]: `urn:${this._cacheSchemaId}`
174
- }
175
- };
176
- } else {
177
- jsonCache = {
178
- buildNumber: this._buildNumber,
179
- lastModified: this._lastTime,
180
- [this._cacheSchemaId]: {
181
- [`xmlns:${namespace}`]: `urn:${this._cacheSchemaId}`
182
- }
183
- };
184
- }
167
+ // Use Json because xtk:schema does not work directly in DomUtil.parse(`<cache buildNumber="9469" time="2022-06-30T00:00:00.000"><xtk:schema xmlns:xtk="urn:xtk:schema"></xtk:schema></cache>`);
168
+ // due to the colon character
169
+ let jsonCache;
170
+ if (this._lastTime === undefined || this._buildNumber === undefined) {
171
+ jsonCache = {
172
+ [this._cacheSchemaId]: {
173
+ [`xmlns:${namespace}`]: `urn:${this._cacheSchemaId}`
174
+ }
175
+ };
176
+ } else {
177
+ jsonCache = {
178
+ buildNumber: this._buildNumber,
179
+ lastModified: this._lastTime,
180
+ [this._cacheSchemaId]: {
181
+ [`xmlns:${namespace}`]: `urn:${this._cacheSchemaId}`
182
+ }
183
+ };
184
+ }
185
185
 
186
- const xmlDoc = DomUtil.fromJSON("cache", jsonCache, 'SimpleJson');
187
- soapCall.writeDocument("cacheEntities", xmlDoc);
186
+ const xmlDoc = DomUtil.fromJSON("cache", jsonCache, 'SimpleJson');
187
+ soapCall.writeDocument("cacheEntities", xmlDoc);
188
188
 
189
- // Client is not logged: do not attempt to refresh caches at all
190
- if (!this._client.isLogged())
191
- throw CampaignException.NOT_LOGGED_IN(soapCall, `Cannot call GetModifiedEntities: session not connected`);
189
+ // Client is not logged: do not attempt to refresh caches at all
190
+ if (!this._client.isLogged())
191
+ throw CampaignException.NOT_LOGGED_IN(soapCall, `Cannot call GetModifiedEntities: session not connected`);
192
192
 
193
- const event = this._client._trackEvent('CACHE_REFRESHER//tick', undefined, {
194
- cacheSchemaId: this._cacheSchemaId,
195
- lastTime: this._lastTime,
196
- buildNumber: this._buildNumber
197
- });
193
+ const event = this._client._trackEvent('CACHE_REFRESHER//tick', undefined, {
194
+ cacheSchemaId: this._cacheSchemaId,
195
+ lastTime: this._lastTime,
196
+ buildNumber: this._buildNumber
197
+ });
198
198
 
199
- // Do a soap call GetModifiedEntities instead of xtksession.GetModifiedEnties because we don't want to go through methodCache
200
- // which might not contain the method GetModifiedEntities just after a build updgrade from a old version of acc
201
- // This is an internal SOAP call that cannot be intercepted by observers onBeforeCall / onAfterCall
202
- try {
203
- await this._client._makeSoapCall(soapCall);
204
- let doc = soapCall.getNextDocument();
205
- soapCall.checkNoMoreArgs();
206
- doc = that._client._toRepresentation(doc, 'xml');
207
- that._lastTime = DomUtil.getAttributeAsString(doc, "time"); // save time to be able to send it as an attribute in the next soap call
208
- that._buildNumber = DomUtil.getAttributeAsString(doc, "buildNumber");
209
- await that._refresh(doc, event);
210
- await that._refresherStateCache.put("time", that._lastTime);
211
- await that._refresherStateCache.put("buildNumber", that._buildNumber);
212
- }
213
- catch(ex) {
214
- // if the method GetModifiedEntities is not found in this acc version we disable the autoresfresh of the cache
215
- if (soapCall.methodName == "GetModifiedEntities" && ex.errorCode == "SOP-330006") {
216
- this._client._trackEvent('CACHE_REFRESHER//abort', undefined, {
217
- cacheSchemaId: this._cacheSchemaId,
218
- error: ex,
219
- });
220
- this.stopAutoRefresh();
221
- } else {
222
- throw ex;
223
- }
224
- }
199
+ // Do a soap call GetModifiedEntities instead of xtksession.GetModifiedEnties because we don't want to go through methodCache
200
+ // which might not contain the method GetModifiedEntities just after a build updgrade from a old version of acc
201
+ // This is an internal SOAP call that cannot be intercepted by observers onBeforeCall / onAfterCall
202
+ try {
203
+ await this._client._makeSoapCall(soapCall);
204
+ let doc = soapCall.getNextDocument();
205
+ soapCall.checkNoMoreArgs();
206
+ doc = that._client._toRepresentation(doc, 'xml');
207
+ that._lastTime = DomUtil.getAttributeAsString(doc, "time"); // save time to be able to send it as an attribute in the next soap call
208
+ that._buildNumber = DomUtil.getAttributeAsString(doc, "buildNumber");
209
+ await that._refresh(doc, event);
210
+ await that._refresherStateCache.put("time", that._lastTime);
211
+ await that._refresherStateCache.put("buildNumber", that._buildNumber);
212
+ }
213
+ catch(ex) {
214
+ // if the method GetModifiedEntities is not found in this acc version we disable the autoresfresh of the cache
215
+ if (soapCall.methodName == "GetModifiedEntities" && ex.errorCode == "SOP-330006") {
216
+ this._client._trackEvent('CACHE_REFRESHER//abort', undefined, {
217
+ cacheSchemaId: this._cacheSchemaId,
218
+ error: ex,
219
+ });
220
+ this.stopAutoRefresh();
221
+ } else {
222
+ throw ex;
225
223
  }
224
+ }
225
+ }
226
226
 
227
- // Refresh Cache : remove entities modified recently listed in xmlDoc
228
- async _refresh(xmlDoc, event) {
229
- const clearCache = XtkCaster.asBoolean(DomUtil.getAttributeAsString(xmlDoc, "emptyCache"));
230
- const evicted = [];
231
- if (clearCache == true) {
232
- await this._cache.clear();
233
- } else {
234
- var child = DomUtil.getFirstChildElement(xmlDoc, "entityCache");
235
- while (child) {
236
- const pkSchemaId = DomUtil.getAttributeAsString(child, "pk");
237
- const schemaId = DomUtil.getAttributeAsString(child, "schema");
238
- if (schemaId === this._cacheSchemaId) {
239
- evicted.push(schemaId);
240
- await this._cache.remove(pkSchemaId);
241
- // Notify listeners to refresh in SchemaCache
242
- if (schemaId === "xtk:schema") {
243
- const schemaIds = pkSchemaId.split("|");
244
- this._client._notifyCacheChangeListeners(schemaIds[1]);
245
- }
246
- }
247
- child = DomUtil.getNextSiblingElement(child);
248
- }
227
+ // Refresh Cache : remove entities modified recently listed in xmlDoc
228
+ async _refresh(xmlDoc, event) {
229
+ const clearCache = XtkCaster.asBoolean(DomUtil.getAttributeAsString(xmlDoc, "emptyCache"));
230
+ const evicted = [];
231
+ if (clearCache == true) {
232
+ await this._cache.clear();
233
+ } else {
234
+ var child = DomUtil.getFirstChildElement(xmlDoc, "entityCache");
235
+ while (child) {
236
+ const pkSchemaId = DomUtil.getAttributeAsString(child, "pk");
237
+ const schemaId = DomUtil.getAttributeAsString(child, "schema");
238
+ if (schemaId === this._cacheSchemaId) {
239
+ evicted.push(schemaId);
240
+ await this._cache.remove(pkSchemaId);
241
+ // Notify listeners to refresh in SchemaCache
242
+ if (schemaId === "xtk:schema") {
243
+ const schemaIds = pkSchemaId.split("|");
244
+ this._client._notifyCacheChangeListeners(schemaIds[1]);
249
245
  }
250
-
251
- this._client._trackEvent('CACHE_REFRESHER//response', event, {
252
- cacheSchemaId: this._cacheSchemaId,
253
- clearCache: clearCache,
254
- evicted: evicted
255
- });
246
+ }
247
+ child = DomUtil.getNextSiblingElement(child);
256
248
  }
249
+ }
250
+
251
+ this._client._trackEvent('CACHE_REFRESHER//response', event, {
252
+ cacheSchemaId: this._cacheSchemaId,
253
+ clearCache: clearCache,
254
+ evicted: evicted
255
+ });
256
+ }
257
257
 
258
- /**
258
+ /**
259
259
  * Stop auto refreshing the cache
260
260
  */
261
- stopAutoRefresh() {
262
- if (this._intervalId) {
263
- this._client._trackEvent('CACHE_REFRESHER//stop', undefined, {
264
- cacheSchemaId: this._cacheSchemaId,
265
- });
266
- }
267
- clearInterval(this._intervalId);
268
- this._intervalId = null;
269
- }
261
+ stopAutoRefresh() {
262
+ if (this._intervalId) {
263
+ this._client._trackEvent('CACHE_REFRESHER//stop', undefined, {
264
+ cacheSchemaId: this._cacheSchemaId,
265
+ });
266
+ }
267
+ clearInterval(this._intervalId);
268
+ this._intervalId = null;
270
269
  }
270
+ }
271
271
 
272
- // Public exports
273
- exports.CacheRefresher = CacheRefresher;
272
+ // Public exports
273
+ exports.CacheRefresher = CacheRefresher;
274
274
 
275
275
  })();