75 lines · 3.1 KB · TypeScript
RawDownload
import * as NodeCrypto from "node:crypto"; import { describe, expect, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as Redacted from "effect/Redacted";import * as Schema from "effect/Schema"; import * as ApnsProviderTokens from "./ApnsProviderTokens.ts"; const { privateKey } = NodeCrypto.generateKeyPairSync("ec", {  namedCurve: "prime256v1",  privateKeyEncoding: { type: "pkcs8", format: "pem" },  publicKeyEncoding: { type: "spki", format: "pem" },}); const signingInput = {  teamId: "team-1",  keyId: "key-1",  privateKey: Redacted.make(privateKey),}; const WINDOW = ApnsProviderTokens.APNS_JWT_REUSE_SECONDS; const decodeJwtPayload = Schema.decodeEffect(  Schema.fromJsonString(Schema.Struct({ iat: Schema.Number })),); describe("ApnsProviderTokens", () => {  it.effect("derives the byte-identical token across isolates within a window", () => {    ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();    return Effect.gen(function* () {      const tokens = yield* ApnsProviderTokens.ApnsProviderTokens;      const first = yield* tokens.getJwt({ ...signingInput, issuedAtUnixSeconds: WINDOW + 10 });       // A fresh isolate has no cache; deterministic signing plus quantized      // iat must still reproduce the exact same JWT for the same window.      ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();      const second = yield* tokens.getJwt({        ...signingInput,        issuedAtUnixSeconds: WINDOW * 2 - 1,      });      expect(second).toBe(first);       const payload = yield* decodeJwtPayload(        Buffer.from(first.split(".")[1]!, "base64url").toString("utf8"),      );      expect(payload.iat).toBe(WINDOW);      ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();    }).pipe(Effect.provide(ApnsProviderTokens.layer));  });   it.effect("rolls to a new token at the window boundary", () => {    ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();    return Effect.gen(function* () {      const tokens = yield* ApnsProviderTokens.ApnsProviderTokens;      const first = yield* tokens.getJwt({ ...signingInput, issuedAtUnixSeconds: WINDOW + 10 });      const next = yield* tokens.getJwt({ ...signingInput, issuedAtUnixSeconds: WINDOW * 2 });      expect(next).not.toBe(first);      ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();    }).pipe(Effect.provide(ApnsProviderTokens.layer));  });   it.effect("serves repeat pushes from the isolate cache without re-signing", () => {    ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();    return Effect.gen(function* () {      const tokens = yield* ApnsProviderTokens.ApnsProviderTokens;      const first = yield* tokens.getJwt({ ...signingInput, issuedAtUnixSeconds: WINDOW + 10 });      const again = yield* tokens.getJwt({ ...signingInput, issuedAtUnixSeconds: WINDOW + 500 });      // Deterministic signing makes equality hold either way; toBe on the      // exact string documents the cache contract.      expect(again).toBe(first);      ApnsProviderTokens.__resetApnsProviderTokenCacheForTest();    }).pipe(Effect.provide(ApnsProviderTokens.layer));  });});