@adobe/spacecat-shared-tokowaka-client 1.5.8 → 1.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 CHANGED
@@ -1,3 +1,10 @@
1
+ # [@adobe/spacecat-shared-tokowaka-client-v1.6.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.5.8...@adobe/spacecat-shared-tokowaka-client-v1.6.0) (2026-01-29)
2
+
3
+
4
+ ### Features
5
+
6
+ * new flag opted added in edgeoptimizeconfig ([#1294](https://github.com/adobe/spacecat-shared/issues/1294)) ([8386e38](https://github.com/adobe/spacecat-shared/commit/8386e3805e9e67c18e4569428bef7ac5723eb991))
7
+
1
8
  # [@adobe/spacecat-shared-tokowaka-client-v1.5.8](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.5.7...@adobe/spacecat-shared-tokowaka-client-v1.5.8) (2026-01-27)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-tokowaka-client",
3
- "version": "1.5.8",
3
+ "version": "1.6.0",
4
4
  "description": "Tokowaka Client for SpaceCat - Edge optimization config management",
5
5
  "type": "module",
6
6
  "engines": {
package/src/index.js CHANGED
@@ -290,7 +290,7 @@ class TokowakaClient {
290
290
  * @param {boolean} options.enhancements - Whether to enable enhancements (default: true)
291
291
  * @returns {Promise<Object>} - Object with s3Path and metaconfig
292
292
  */
293
- async createMetaconfig(url, siteId, options = {}) {
293
+ async createMetaconfig(url, siteId, options = {}, metadata = {}) {
294
294
  if (!hasText(url)) {
295
295
  throw this.#createError('URL is required', HTTP_BAD_REQUEST);
296
296
  }
@@ -316,8 +316,7 @@ class TokowakaClient {
316
316
  patches: {},
317
317
  };
318
318
 
319
- const s3Path = await this.uploadMetaconfig(url, metaconfig);
320
-
319
+ const s3Path = await this.uploadMetaconfig(url, metaconfig, metadata);
321
320
  this.log.info(`Created new Tokowaka metaconfig for ${normalizedHostName} at ${s3Path}`);
322
321
 
323
322
  return metaconfig;
@@ -331,7 +330,7 @@ class TokowakaClient {
331
330
  * @param {Object} options - Optional configuration
332
331
  * @returns {Promise<Object>} - Object with s3Path and metaconfig
333
332
  */
334
- async updateMetaconfig(url, siteId, options = {}) {
333
+ async updateMetaconfig(url, siteId, options = {}, metadata = {}) {
335
334
  if (!hasText(url)) {
336
335
  throw this.#createError('URL is required', HTTP_BAD_REQUEST);
337
336
  }
@@ -371,8 +370,7 @@ class TokowakaClient {
371
370
  ...(hasPrerender && { prerender }),
372
371
  };
373
372
 
374
- const s3Path = await this.uploadMetaconfig(url, metaconfig);
375
-
373
+ const s3Path = await this.uploadMetaconfig(url, metaconfig, metadata);
376
374
  this.log.info(`Updated Tokowaka metaconfig for ${normalizedHostName} at ${s3Path}`);
377
375
 
378
376
  return metaconfig;
@@ -382,9 +380,10 @@ class TokowakaClient {
382
380
  * Uploads domain-level metaconfig to S3
383
381
  * @param {string} url - Full URL (used to extract domain)
384
382
  * @param {Object} metaconfig - Metaconfig object (siteId, apiKeys, prerender)
383
+ * @param {Object} metadata - Optional S3 user-defined metadata (key-value pairs)
385
384
  * @returns {Promise<string>} - S3 key of uploaded metaconfig
386
- */
387
- async uploadMetaconfig(url, metaconfig) {
385
+ */
386
+ async uploadMetaconfig(url, metaconfig, metadata = {}) {
388
387
  if (!hasText(url)) {
389
388
  throw this.#createError('URL is required', HTTP_BAD_REQUEST);
390
389
  }
@@ -397,12 +396,19 @@ class TokowakaClient {
397
396
  const bucketName = this.deployBucketName;
398
397
 
399
398
  try {
400
- const command = new PutObjectCommand({
399
+ const putObjectParams = {
401
400
  Bucket: bucketName,
402
401
  Key: s3Path,
403
402
  Body: JSON.stringify(metaconfig, null, 2),
404
403
  ContentType: 'application/json',
405
- });
404
+ };
405
+
406
+ // Add user-defined metadata if provided
407
+ if (isNonEmptyObject(metadata)) {
408
+ putObjectParams.Metadata = metadata;
409
+ }
410
+
411
+ const command = new PutObjectCommand(putObjectParams);
406
412
 
407
413
  await this.s3Client.send(command);
408
414
  this.log.info(`Successfully uploaded metaconfig to s3://${bucketName}/${s3Path}`);
@@ -454,6 +454,43 @@ describe('TokowakaClient', () => {
454
454
  expect(error.status).to.equal(500);
455
455
  }
456
456
  });
457
+
458
+ it('should upload metaconfig with user-defined metadata when provided', async () => {
459
+ const metaconfig = {
460
+ siteId: 'site-123',
461
+ prerender: true,
462
+ };
463
+ const metadata = {
464
+ 'last-modified-by': 'john@example.com',
465
+ 'created-by': 'admin',
466
+ };
467
+
468
+ const s3Path = await client.uploadMetaconfig('https://example.com/page1', metaconfig, metadata);
469
+
470
+ expect(s3Path).to.equal('opportunities/example.com/config');
471
+
472
+ const command = s3Client.send.firstCall.args[0];
473
+ expect(command.input.Bucket).to.equal('test-bucket');
474
+ expect(command.input.Key).to.equal('opportunities/example.com/config');
475
+ expect(command.input.ContentType).to.equal('application/json');
476
+ expect(JSON.parse(command.input.Body)).to.deep.equal(metaconfig);
477
+ expect(command.input.Metadata).to.deep.equal(metadata);
478
+ });
479
+
480
+ it('should upload metaconfig without Metadata field when metadata is empty object', async () => {
481
+ const metaconfig = {
482
+ siteId: 'site-123',
483
+ prerender: true,
484
+ };
485
+
486
+ const s3Path = await client.uploadMetaconfig('https://example.com/page1', metaconfig, {});
487
+
488
+ expect(s3Path).to.equal('opportunities/example.com/config');
489
+
490
+ const command = s3Client.send.firstCall.args[0];
491
+ expect(command.input.Bucket).to.equal('test-bucket');
492
+ expect(command.input.Metadata).to.be.undefined;
493
+ });
457
494
  });
458
495
 
459
496
  describe('createMetaconfig', () => {
@@ -567,6 +604,50 @@ describe('TokowakaClient', () => {
567
604
  const command = s3Client.send.firstCall.args[0];
568
605
  expect(command.input.Key).to.equal('opportunities/example.com/config');
569
606
  });
607
+
608
+ it('should include user-defined metadata when metadata is provided', async () => {
609
+ const siteId = 'site-123';
610
+ const url = 'https://www.example.com/page1';
611
+ const noSuchKeyError = new Error('NoSuchKey');
612
+ noSuchKeyError.name = 'NoSuchKey';
613
+ s3Client.send.onFirstCall().rejects(noSuchKeyError);
614
+
615
+ await client.createMetaconfig(url, siteId, {}, { 'last-modified-by': 'john@example.com' });
616
+
617
+ // Second call is the uploadMetaconfig
618
+ const uploadCommand = s3Client.send.secondCall.args[0];
619
+ expect(uploadCommand.input.Metadata).to.deep.equal({
620
+ 'last-modified-by': 'john@example.com',
621
+ });
622
+ });
623
+
624
+ it('should not include metadata when metadata is empty object', async () => {
625
+ const siteId = 'site-123';
626
+ const url = 'https://www.example.com/page1';
627
+ const noSuchKeyError = new Error('NoSuchKey');
628
+ noSuchKeyError.name = 'NoSuchKey';
629
+ s3Client.send.onFirstCall().rejects(noSuchKeyError);
630
+
631
+ await client.createMetaconfig(url, siteId, {}, {});
632
+
633
+ // Second call is the uploadMetaconfig
634
+ const uploadCommand = s3Client.send.secondCall.args[0];
635
+ expect(uploadCommand.input.Metadata).to.be.undefined;
636
+ });
637
+
638
+ it('should not include metadata when metadata is not provided', async () => {
639
+ const siteId = 'site-123';
640
+ const url = 'https://www.example.com/page1';
641
+ const noSuchKeyError = new Error('NoSuchKey');
642
+ noSuchKeyError.name = 'NoSuchKey';
643
+ s3Client.send.onFirstCall().rejects(noSuchKeyError);
644
+
645
+ await client.createMetaconfig(url, siteId);
646
+
647
+ // Second call is the uploadMetaconfig
648
+ const uploadCommand = s3Client.send.secondCall.args[0];
649
+ expect(uploadCommand.input.Metadata).to.be.undefined;
650
+ });
570
651
  });
571
652
 
572
653
  describe('updateMetaconfig', () => {
@@ -1308,6 +1389,47 @@ describe('TokowakaClient', () => {
1308
1389
  expect(result).to.have.property('prerender');
1309
1390
  expect(result.prerender).to.deep.equal(prerenderConfig);
1310
1391
  });
1392
+
1393
+ it('should include user-defined metadata when metadata is provided', async () => {
1394
+ const siteId = 'site-456';
1395
+ const url = 'https://www.example.com';
1396
+
1397
+ await client.updateMetaconfig(url, siteId, {
1398
+ tokowakaEnabled: true,
1399
+ }, { 'last-modified-by': 'jane@example.com' });
1400
+
1401
+ // Second call is the uploadMetaconfig
1402
+ const uploadCommand = s3Client.send.secondCall.args[0];
1403
+ expect(uploadCommand.input.Metadata).to.deep.equal({
1404
+ 'last-modified-by': 'jane@example.com',
1405
+ });
1406
+ });
1407
+
1408
+ it('should not include metadata when metadata is empty object', async () => {
1409
+ const siteId = 'site-456';
1410
+ const url = 'https://www.example.com';
1411
+
1412
+ await client.updateMetaconfig(url, siteId, {
1413
+ tokowakaEnabled: true,
1414
+ }, {});
1415
+
1416
+ // Second call is the uploadMetaconfig
1417
+ const uploadCommand = s3Client.send.secondCall.args[0];
1418
+ expect(uploadCommand.input.Metadata).to.be.undefined;
1419
+ });
1420
+
1421
+ it('should not include metadata when metadata is not provided', async () => {
1422
+ const siteId = 'site-456';
1423
+ const url = 'https://www.example.com';
1424
+
1425
+ await client.updateMetaconfig(url, siteId, {
1426
+ tokowakaEnabled: true,
1427
+ });
1428
+
1429
+ // Second call is the uploadMetaconfig
1430
+ const uploadCommand = s3Client.send.secondCall.args[0];
1431
+ expect(uploadCommand.input.Metadata).to.be.undefined;
1432
+ });
1311
1433
  });
1312
1434
 
1313
1435
  describe('uploadConfig', () => {