콘텐츠로 이동

deriveIdempotencyKey — @gj-kit/toss-payments

@gj-kit/toss-payments에서 공개하는 function입니다. package version 0.6.1의 release declaration을 그대로 표시합니다.

import { deriveIdempotencyKey } from '@gj-kit/toss-payments';
/**
* Deterministically derives an `Idempotency-Key` from a logical operation identity.
*
* Format: `<operation>:<part>:<part>…` (segments joined by `:`; with no `parts` the key is just
* `<operation>`), plus `#<attempt>` when `attempt` is given. Example:
* `subscription_renewal:sub_01:1756652400000` and, for a new attempt,
* `subscription_renewal:sub_01:1756652400000#7c9e…`. The same input always yields the same key,
* so a crash-recovered worker reproduces the key it submitted before and gets Toss's replay
* instead of a second execution.
*
* **The encoding is injective — distinct inputs never derive the same key.** Every segment
* (`operation`, each element of `parts`, `attempt`) must be non-empty (`reason: 'empty'`) and
* must consist of visible ASCII **excluding** the two delimiters `:` and `#`
* (`reason: 'bad-charset'`). Because no segment can contain a delimiter, a key contains `#`
* exactly once iff an attempt was given, and the prefix splits on `:` back into exactly
* `operation` + `parts`. Underscores, dots, `@`, `=`, `-` and the like are fine, so the ids the
* library already validates (`orderId`, `customerKey`, `cancelRequestId`, UUIDs, epoch strings)
* all pass unchanged; ISO timestamps with `:` do not — use an epoch or a date-only marker.
*
* The assembled key then runs through the public {@link idempotencyKey} parser so the provider
* length limit (1–300 chars, otherwise 400 `INVALID_IDEMPOTENCY_KEY` — `reason: 'too-long'`) and
* the header-safe charset are enforced in exactly one place: an `Ok` result is always sendable.
*
* This is an **explicit** helper: the library never derives keys behind your back, because a
* deterministic key combined with 4xx replay is a trap the caller must consciously manage with
* the `attempt` field.
*/
declare function deriveIdempotencyKey(input: DeriveIdempotencyKeyInput): Result<IdempotencyKey, InvalidInput<'idempotencyKey'>>;

이 선언은 매개변수, optionality, 제네릭, 반환값, 공개 union/type 계약의 정본입니다. 호출 전 필요한 환경·권한·오류 경계는 패키지 Golden path와 이 subpath의 import 조건을 함께 확인하세요.

  • 패키지: @gj-kit/toss-payments
  • 버전: 0.6.1
  • 공개 entry: .
  • 소스: GitHub

Deterministically derives an Idempotency-Key from a logical operation identity.

Format: <operation>:<part>:<part>… (segments joined by :; with no parts the key is just <operation>), plus #<attempt> when attempt is given. Example: subscription_renewal:sub_01:1756652400000 and, for a new attempt, subscription_renewal:sub_01:1756652400000#7c9e…. The same input always yields the same key, so a crash-recovered worker reproduces the key it submitted before and gets Toss’s replay instead of a second execution.

The encoding is injective — distinct inputs never derive the same key. Every segment (operation, each element of parts, attempt) must be non-empty (reason: 'empty') and must consist of visible ASCII excluding the two delimiters : and # (reason: 'bad-charset'). Because no segment can contain a delimiter, a key contains # exactly once iff an attempt was given, and the prefix splits on : back into exactly operation + parts. Underscores, dots, @, =, - and the like are fine, so the ids the library already validates (orderId, customerKey, cancelRequestId, UUIDs, epoch strings) all pass unchanged; ISO timestamps with : do not — use an epoch or a date-only marker.

The assembled key then runs through the public {@link idempotencyKey } parser so the provider length limit (1–300 chars, otherwise 400 INVALID_IDEMPOTENCY_KEYreason: 'too-long') and the header-safe charset are enforced in exactly one place: an Ok result is always sendable.

This is an explicit helper: the library never derives keys behind your back, because a deterministic key combined with 4xx replay is a trap the caller must consciously manage with the attempt field.