@superwall/server 0.1.1 → 0.1.3

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.
@@ -2,72 +2,72 @@ $ bun test
2
2
  bun test v1.3.11 (af24e281)
3
3
 
4
4
  src/requires.test.ts:
5
- (pass) sw.requires() > calls next() when entitled [8.75ms]
6
- (pass) sw.requires() > default 403 when not entitled [0.37ms]
7
- (pass) sw.requires() > fail-closed when no userId can be extracted [0.11ms]
8
- (pass) sw.requires() > allowAnonymous lets the handler decide [0.09ms]
9
- (pass) sw.requires() > onUnauthorized override [0.20ms]
10
- (pass) sw.requires() > per-route userId override wins [1.41ms]
11
- (pass) sw.requires() > network errors pass to next(err) [0.84ms]
12
- (pass) sw.requires() > multiple-AND spec rejects when any missing [0.39ms]
13
- (pass) sw.requires() > ANY spec passes when one active [0.21ms]
14
- (pass) sw.requires() > normalizes spec at registration time (fails loud) [0.37ms]
5
+ (pass) sw.requires() > calls next() when entitled [1.40ms]
6
+ (pass) sw.requires() > default 403 when not entitled [0.13ms]
7
+ (pass) sw.requires() > fail-closed when no userId can be extracted [0.06ms]
8
+ (pass) sw.requires() > allowAnonymous lets the handler decide [0.05ms]
9
+ (pass) sw.requires() > onUnauthorized override [1.02ms]
10
+ (pass) sw.requires() > per-route userId override wins [0.24ms]
11
+ (pass) sw.requires() > network errors pass to next(err) [0.14ms]
12
+ (pass) sw.requires() > multiple-AND spec rejects when any missing [0.07ms]
13
+ (pass) sw.requires() > ANY spec passes when one active [0.06ms]
14
+ (pass) sw.requires() > normalizes spec at registration time (fails loud) [0.04ms]
15
15
 
16
16
  src/cache.test.ts:
17
- (pass) InMemoryCache > get returns null on miss [0.02ms]
18
- (pass) InMemoryCache > set + get returns the entry [0.10ms]
19
- (pass) InMemoryCache > expired entry is dropped on read [0.03ms]
20
- (pass) InMemoryCache > delete removes the entry [0.15ms]
21
- (pass) InMemoryCache > clear empties the cache [0.08ms]
22
- (pass) InMemoryCache > LRU evicts oldest when maxEntries exceeded [0.17ms]
23
- (pass) InMemoryCache > read refreshes LRU position so recent reads survive eviction [0.18ms]
17
+ (pass) InMemoryCache > get returns null on miss
18
+ (pass) InMemoryCache > set + get returns the entry [0.08ms]
19
+ (pass) InMemoryCache > expired entry is dropped on read [0.04ms]
20
+ (pass) InMemoryCache > delete removes the entry [0.03ms]
21
+ (pass) InMemoryCache > clear empties the cache [0.03ms]
22
+ (pass) InMemoryCache > LRU evicts oldest when maxEntries exceeded [0.12ms]
23
+ (pass) InMemoryCache > read refreshes LRU position so recent reads survive eviction [0.04ms]
24
24
 
25
25
  src/superwall.test.ts:
26
- (pass) Superwall() factory > rejects missing apiKey [0.04ms]
27
- (pass) Superwall() factory > getEntitlements returns parsed bucket [0.19ms]
28
- (pass) Superwall() factory > userHas (string) returns true when entitlement is active [0.08ms]
29
- (pass) Superwall() factory > userHas (string) returns false when entitlement is inactive [0.03ms]
30
- (pass) Superwall() factory > userHas (array) requires all [0.07ms]
31
- (pass) Superwall() factory > userHas ({ any }) returns true when any active [0.04ms]
32
- (pass) Superwall() factory > caches subsequent reads for the same userId [0.14ms]
33
- (pass) Superwall() factory > invalidate forces a refetch [0.26ms]
34
- (pass) Superwall() factory > invalidateAll clears every entry [0.24ms]
35
- (pass) Superwall() factory > TTL expiry forces a refetch [9.06ms]
36
- (pass) Superwall() factory > onRequest fires with cache hit info [1.30ms]
26
+ (pass) Superwall() factory > rejects missing apiKey [0.06ms]
27
+ (pass) Superwall() factory > getEntitlements returns parsed bucket [0.29ms]
28
+ (pass) Superwall() factory > userHas (string) returns true when entitlement is active [0.06ms]
29
+ (pass) Superwall() factory > userHas (string) returns false when entitlement is inactive
30
+ (pass) Superwall() factory > userHas (array) requires all [0.15ms]
31
+ (pass) Superwall() factory > userHas ({ any }) returns true when any active [0.11ms]
32
+ (pass) Superwall() factory > caches subsequent reads for the same userId [0.05ms]
33
+ (pass) Superwall() factory > invalidate forces a refetch [0.09ms]
34
+ (pass) Superwall() factory > invalidateAll clears every entry [0.09ms]
35
+ (pass) Superwall() factory > TTL expiry forces a refetch [5.91ms]
36
+ (pass) Superwall() factory > onRequest fires with cache hit info [0.15ms]
37
37
  (pass) Superwall() factory > onRequest throwing does not break the request [0.07ms]
38
38
 
39
39
  src/fetcher.test.ts:
40
- (pass) fetchEntitlements > parses customerInfo.entitlements envelope [0.34ms]
41
- (pass) fetchEntitlements > parses top-level entitlements array [0.15ms]
42
- (pass) fetchEntitlements > encodes the userId in the URL path [1.20ms]
43
- (pass) fetchEntitlements > includes Authorization and X-App-User-ID headers [0.46ms]
44
- (pass) fetchEntitlements > 401 → SuperwallAuthError [0.25ms]
45
- (pass) fetchEntitlements > 403 → SuperwallAuthError [0.73ms]
46
- (pass) fetchEntitlements > 404 → SuperwallNotFoundError [0.09ms]
47
- (pass) fetchEntitlements > 500 → SuperwallNetworkError with status [0.19ms]
48
- (pass) fetchEntitlements > fetch throw → SuperwallNetworkError [0.28ms]
49
- (pass) fetchEntitlements > AbortError → SuperwallTimeoutError [6.79ms]
50
- (pass) fetchEntitlements > malformed JSON → SuperwallDecodingError [0.21ms]
51
- (pass) fetchEntitlements > uses the configured environment for the host [0.16ms]
40
+ (pass) fetchEntitlements > parses customerInfo.entitlements envelope [0.28ms]
41
+ (pass) fetchEntitlements > parses top-level entitlements array [0.10ms]
42
+ (pass) fetchEntitlements > encodes the userId in the URL path [0.16ms]
43
+ (pass) fetchEntitlements > includes Authorization and X-App-User-ID headers [0.25ms]
44
+ (pass) fetchEntitlements > 401 → SuperwallAuthError [0.14ms]
45
+ (pass) fetchEntitlements > 403 → SuperwallAuthError [0.10ms]
46
+ (pass) fetchEntitlements > 404 → SuperwallNotFoundError [0.07ms]
47
+ (pass) fetchEntitlements > 500 → SuperwallNetworkError with status [0.13ms]
48
+ (pass) fetchEntitlements > fetch throw → SuperwallNetworkError [0.12ms]
49
+ (pass) fetchEntitlements > AbortError → SuperwallTimeoutError [6.50ms]
50
+ (pass) fetchEntitlements > malformed JSON → SuperwallDecodingError [0.16ms]
51
+ (pass) fetchEntitlements > uses the configured environment for the host [0.05ms]
52
52
 
53
53
  src/spec.test.ts:
54
54
  (pass) normalizeSpec > string [0.02ms]
55
55
  (pass) normalizeSpec > array → all
56
- (pass) normalizeSpec > { all }
57
- (pass) normalizeSpec > { any } [0.03ms]
58
- (pass) normalizeSpec > rejects empty string [0.02ms]
59
- (pass) normalizeSpec > rejects empty array
60
- (pass) normalizeSpec > rejects empty all
61
- (pass) normalizeSpec > rejects empty any
62
- (pass) normalizeSpec > rejects malformed object [0.05ms]
63
- (pass) findMissing (mode: all) > returns empty when all entitlements active [0.02ms]
56
+ (pass) normalizeSpec > { all } [0.02ms]
57
+ (pass) normalizeSpec > { any } [0.02ms]
58
+ (pass) normalizeSpec > rejects empty string [0.03ms]
59
+ (pass) normalizeSpec > rejects empty array [0.03ms]
60
+ (pass) normalizeSpec > rejects empty all [0.02ms]
61
+ (pass) normalizeSpec > rejects empty any [0.02ms]
62
+ (pass) normalizeSpec > rejects malformed object [0.04ms]
63
+ (pass) findMissing (mode: all) > returns empty when all entitlements active [0.07ms]
64
64
  (pass) findMissing (mode: all) > returns the missing entitlement
65
- (pass) findMissing (mode: all) > ignores extra active entitlements
66
- (pass) findMissing (mode: all) > inactive entitlements are not counted
67
- (pass) findMissing (mode: any) > returns empty when any one is active
68
- (pass) findMissing (mode: any) > returns all listed when none active
65
+ (pass) findMissing (mode: all) > ignores extra active entitlements [0.03ms]
66
+ (pass) findMissing (mode: all) > inactive entitlements are not counted [0.03ms]
67
+ (pass) findMissing (mode: any) > returns empty when any one is active [0.03ms]
68
+ (pass) findMissing (mode: any) > returns all listed when none active [0.02ms]
69
69
 
70
70
  56 pass
71
71
  0 fail
72
72
  84 expect() calls
73
- Ran 56 tests across 5 files. [107.00ms]
73
+ Ran 56 tests across 5 files. [42.00ms]
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # @superwall/server
2
+
3
+ Server-side entitlement enforcement for the Superwall web SDK. The browser's
4
+ subscription status is editable from devtools — this package gates real routes
5
+ server-to-server against Superwall's `/entitlements` endpoint, with caching.
6
+
7
+ Works on any runtime with `fetch` (Node 18+, Bun, Deno, Workers).
8
+
9
+ ```sh
10
+ bun add @superwall/server # or npm / pnpm / yarn
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ ```ts
16
+ import { Superwall } from "@superwall/server";
17
+
18
+ const sw = Superwall({
19
+ apiKey: process.env.SUPERWALL_API_KEY!, // required
20
+ userId: (req) => req.session?.userId ?? null, // how to read the user per request
21
+ // environment: "release",
22
+ // cache: { ttlMs: 60_000, maxEntries: 10_000 },
23
+ // timeoutMs: 5_000,
24
+ });
25
+ ```
26
+
27
+ ## Gate a route (Express-style middleware)
28
+
29
+ ```ts
30
+ app.get("/api/export", sw.requires("pro"), exportHandler);
31
+ // 403 if the user lacks the "pro" entitlement; calls next() if they have it.
32
+ ```
33
+
34
+ `requires(entitlement, options?)` returns `(req, res, next)`. Pass a per-call
35
+ `userId` extractor in `options` to override the default.
36
+
37
+ ## Check imperatively
38
+
39
+ ```ts
40
+ if (await sw.userHas(userId, "pro")) {
41
+ // grant access
42
+ }
43
+ ```
44
+
45
+ ## Offline verification
46
+
47
+ For per-request checks without a network round-trip, verify the signed
48
+ entitlements token the client holds (`sw.entitlementsToken` on the browser
49
+ SDK) with [`@superwall/verify`](https://www.npmjs.com/package/@superwall/verify).
50
+
51
+ ## License
52
+
53
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superwall/server",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "exports": {
@@ -20,8 +20,8 @@
20
20
  "clean": "rm -rf node_modules .turbo *.tsbuildinfo"
21
21
  },
22
22
  "dependencies": {
23
- "@superwall/core": "0.0.0",
24
- "@superwall/verify": "0.0.0"
23
+ "@superwall/core": "^0.1.3",
24
+ "@superwall/verify": "^0.1.3"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/bun": "latest",