Skip to content

feat(spacecat-shared-utils): SITES-40623 - add token grant config and exports#1420

Merged
sandsinh merged 7 commits intomainfrom
SITES-40623-spacecat-shared-utils
Mar 19, 2026
Merged

feat(spacecat-shared-utils): SITES-40623 - add token grant config and exports#1420
sandsinh merged 7 commits intomainfrom
SITES-40623-spacecat-shared-utils

Conversation

@sandsinh
Copy link
Copy Markdown
Contributor

@sandsinh sandsinh commented Mar 10, 2026

Summary

Add shared token grant configuration to spacecat-shared-utils for suggestion token types (CWV, broken backlinks, alt text). Services can use this to enforce tokens-per-cycle and resolve the current grant cycle consistently.

Changes

  • TOKEN_GRANT_CONFIG – Frozen map of token types (grant_cwv, grant_broken_backlinks, grant_alt_text) with:
    • tokensPerCycle (e.g. 3)
    • cycleFormat (e.g. 'YYYY-MM')
  • getTokenGrantConfig(tokenType) – Returns the config for a token type with a computed currentCycle (UTC-based, e.g. '2026-03').
  • getCurrentCycle(cycleFormat) – Computes the current cycle string from UTC (supports YYYY, MM placeholders).

Please ensure your pull request adheres to the following guidelines:

  • make sure to link the related issues in this description
  • when merging / squashing, make sure the fixed issue references are visible in the commits, for easy compilation of release notes

Related Issues

Thanks for contributing!

@github-actions
Copy link
Copy Markdown

This PR will trigger a minor release when merged.

@Kanishkavijay39
Copy link
Copy Markdown
Contributor

Overview

Adds shared token grant configuration for suggestion token types (CWV, broken backlinks, alt text) to spacecat-shared-utils. Provides two config maps
(OPPORTUNITY_GRANT_CONFIG, TOKEN_GRANT_CONFIG) and helper functions to resolve the current grant cycle.


Code Quality & Design

Strengths:

  • Clean separation between OPPORTUNITY_GRANT_CONFIG (keyed by opportunity name) and TOKEN_GRANT_CONFIG (keyed by token type) — good for different call-site
    conventions
  • Object.freeze() applied consistently to prevent accidental mutation
  • TOKEN_GRANT_CONFIG auto-derived from OPPORTUNITY_GRANT_CONFIG avoids duplication
  • The "consider migrating to DB" comment is a useful forward-looking note
  • TypeScript declarations are complete and accurate

Issues:

  1. getCurrentCycle is not deterministic in tests — the tests compare getCurrentCycle('YYYY-MM') against new Date() inline. If the test runs at a UTC midnight boundary
    (e.g., end of month/year), both calls to new Date() could return different months, causing a flaky test. The test should either mock Date or compare the result
    against a regex pattern like /^\d{4}-\d{2}$/.
  2. getTokenGrantConfigByOpportunity calls getCurrentCycle via getTokenGrantConfig indirectly — but it doesn't. It spreads OPPORTUNITY_GRANT_CONFIG[opportunityName]
    and calls getCurrentCycle directly. This duplicates the logic from getTokenGrantConfig. Consider delegating:
    export function getTokenGrantConfigByOpportunity(opportunityName) {
    const tokenType = getTokenTypeForOpportunity(opportunityName);
    const config = getTokenGrantConfig(tokenType);
    if (!config) return undefined;
    return { ...config, tokenType };
    }
  3. This avoids the duplication and ensures both functions stay in sync.
  4. getTokenGrantConfig and getTokenGrantConfigByOpportunity return undefined when called with no argument — this works but relies on TOKEN_GRANT_CONFIG[undefined] and
    OPPORTUNITY_GRANT_CONFIG[undefined] both being undefined. It's fragile and the behavior isn't explicitly guarded. A simple if (!tokenType) return undefined; guard
    would be clearer (and the tests for the no-argument case would then be testing an explicit code path rather than an implicit JS behavior).
  5. Token type naming inconsistency in PR description vs. code — the PR description uses monthly_suggestion_cwv but the code uses grant_cwv. Minor, but the description
    should match the implementation.
  6. cycle: 'monthly' is unused — getCurrentCycle is driven entirely by cycleFormat. The cycle field is stored but never consumed by any logic in this file. If it's
    only for documentation/display, that should be noted; if it's meant to drive cycle computation, the implementation doesn't use it.
  7. No input validation on getCurrentCycle — passing null or undefined would throw a TypeError (.replace on non-string). Low risk since it's internal, but worth a
    note.

Tests

  • Good coverage: freeze checks, unknown keys, no-arg cases, mutation guard
  • Missing: the flaky boundary issue noted above
  • Missing: explicit test for TOKEN_GRANT_CONFIG frozen entries matching OPPORTUNITY_GRANT_CONFIG entries (the auto-derivation logic could silently break)
  • The it('is frozen...') check on TOKEN_GRANT_CONFIG.grant_cwv is actually testing Object.freeze on a shared reference from OPPORTUNITY_GRANT_CONFIG — correct, but
    worth a comment

@sandsinh sandsinh merged commit a14e001 into main Mar 19, 2026
7 checks passed
@sandsinh sandsinh deleted the SITES-40623-spacecat-shared-utils branch March 19, 2026 10:47
solaris007 pushed a commit that referenced this pull request Mar 19, 2026
## [@adobe/spacecat-shared-utils-v1.105.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.104.0...@adobe/spacecat-shared-utils-v1.105.0) (2026-03-19)

### Features

* **spacecat-shared-utils:** SITES-40623 - add token grant config and exports ([#1420](#1420)) ([a14e001](a14e001))
@solaris007
Copy link
Copy Markdown
Member

🎉 This PR is included in version @adobe/spacecat-shared-utils-v1.105.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants