@stigg/cache-runtime 2.0.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/dist/configuration.d.ts +31 -0
- package/dist/configuration.js +91 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +24 -0
- package/dist/services/cacheRuntime.d.ts +66 -0
- package/dist/services/cacheRuntime.js +80 -0
- package/dist/services/entitlementsService.d.ts +81 -0
- package/dist/services/entitlementsService.js +423 -0
- package/dist/services/entitlementsService.utils.d.ts +16 -0
- package/dist/services/entitlementsService.utils.js +3 -0
- package/dist/services/inMemoryEntitlementsService.d.ts +23 -0
- package/dist/services/inMemoryEntitlementsService.js +152 -0
- package/dist/services/inMemoryLruCacheService.d.ts +6 -0
- package/dist/services/inMemoryLruCacheService.js +20 -0
- package/dist/services/initializationStateTracker.d.ts +25 -0
- package/dist/services/initializationStateTracker.js +53 -0
- package/dist/services/loggerService.d.ts +27 -0
- package/dist/services/loggerService.js +65 -0
- package/dist/services/redisEntitlementsService.d.ts +16 -0
- package/dist/services/redisEntitlementsService.js +54 -0
- package/dist/services/runtimeErrorHandler.d.ts +43 -0
- package/dist/services/runtimeErrorHandler.js +91 -0
- package/dist/types/errors.d.ts +24 -0
- package/dist/types/errors.js +3 -0
- package/dist/types/transport.d.ts +152 -0
- package/dist/types/transport.js +3 -0
- package/dist/utils/entitlementQuery.d.ts +10 -0
- package/dist/utils/entitlementQuery.js +22 -0
- package/package.json +36 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { TransportErrorClassifier } from './errors';
|
|
2
|
+
import { EntitlementEvaluation } from '@stigg/entitlements-runtime';
|
|
3
|
+
import { AccessDeniedReason, CachedEntitlement, EntitlementQuery, EntitlementType, EntitlementsStateAccessDeniedReason, Maybe, UsageUpdateBehavior } from '@stigg/cache-core';
|
|
4
|
+
/**
|
|
5
|
+
* Structural stand-in for an observable. Declared here rather than imported so the
|
|
6
|
+
* package stays off `@apollo/client` — the workspace resolves two incompatible copies
|
|
7
|
+
* of it (js-client-sdk on 3.4.x, node-server-sdk on 3.14.x), and a port that names
|
|
8
|
+
* either one only fits one caller.
|
|
9
|
+
*/
|
|
10
|
+
export interface TransportSubscription {
|
|
11
|
+
unsubscribe(): void;
|
|
12
|
+
}
|
|
13
|
+
export interface TransportObservable<TValue> {
|
|
14
|
+
subscribe(onNext: (value: TValue) => void, onError: (error: any) => void): TransportSubscription;
|
|
15
|
+
}
|
|
16
|
+
/** The cache state a transport hands back, already unwrapped from its wire format. */
|
|
17
|
+
export type EntitlementsState<Input> = {
|
|
18
|
+
entitlements: Input[];
|
|
19
|
+
accessDeniedReason: Maybe<EntitlementsStateAccessDeniedReason>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Minimum an entitlement must expose for the read policy to reconcile freshness.
|
|
23
|
+
* Anything richer is the CacheMapper's business, not the policy's.
|
|
24
|
+
*/
|
|
25
|
+
export type CacheableInput = {
|
|
26
|
+
entitlementUpdatedAt?: string | null;
|
|
27
|
+
};
|
|
28
|
+
export type DimensionValue = string | number | boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Write inputs. Flat scalars plus one cache-owned enum, so the SDKs' published DTOs
|
|
31
|
+
* satisfy them as-is — an API enum member is implicitly assignable to the literal
|
|
32
|
+
* union, so nothing converts on the way in.
|
|
33
|
+
*/
|
|
34
|
+
export type UsageMeasurementInput = {
|
|
35
|
+
customerId: string;
|
|
36
|
+
resourceId?: string;
|
|
37
|
+
featureId: string;
|
|
38
|
+
value: number;
|
|
39
|
+
updateBehavior?: UsageUpdateBehavior;
|
|
40
|
+
createdAt?: Date;
|
|
41
|
+
dimensions?: Record<string, DimensionValue>;
|
|
42
|
+
idempotencyKey?: string;
|
|
43
|
+
};
|
|
44
|
+
export type UsageMeasurementBulkInput = {
|
|
45
|
+
usages: UsageMeasurementInput[];
|
|
46
|
+
};
|
|
47
|
+
/** Flat scalars, so both hosts' published event DTOs satisfy it as-is. */
|
|
48
|
+
export type UsageEventInput = {
|
|
49
|
+
eventName: string;
|
|
50
|
+
customerId: string;
|
|
51
|
+
idempotencyKey: string;
|
|
52
|
+
resourceId?: string;
|
|
53
|
+
dimensions?: Record<string, DimensionValue>;
|
|
54
|
+
timestamp?: Date;
|
|
55
|
+
};
|
|
56
|
+
export type CreditConsumptionInput = {
|
|
57
|
+
customerId: string;
|
|
58
|
+
currencyId: string;
|
|
59
|
+
amount: number;
|
|
60
|
+
idempotencyKey: string;
|
|
61
|
+
resourceId?: string;
|
|
62
|
+
createdAt?: Date;
|
|
63
|
+
dimensions?: Record<string, DimensionValue>;
|
|
64
|
+
};
|
|
65
|
+
/** Write-through payloads. Flat scalars, so a transport's own DTOs satisfy them as-is. */
|
|
66
|
+
export type UsageMeasurementResult = {
|
|
67
|
+
id: string;
|
|
68
|
+
featureId: string;
|
|
69
|
+
customerId: string;
|
|
70
|
+
resourceId?: string | null;
|
|
71
|
+
currentUsage?: number | null;
|
|
72
|
+
usagePeriodStart?: string | number | null;
|
|
73
|
+
usagePeriodEnd?: string | number | null;
|
|
74
|
+
timestamp: string | number;
|
|
75
|
+
credit?: (CreditBalanceResult & {
|
|
76
|
+
consumed: number;
|
|
77
|
+
}) | null;
|
|
78
|
+
};
|
|
79
|
+
export type CreditBalanceResult = {
|
|
80
|
+
currencyId: string;
|
|
81
|
+
currentUsage: number;
|
|
82
|
+
usagePeriodEnd?: string | number | null;
|
|
83
|
+
timestamp: string | number;
|
|
84
|
+
};
|
|
85
|
+
export type CreditConsumptionResult = {
|
|
86
|
+
customerId: string;
|
|
87
|
+
currencyId: string;
|
|
88
|
+
resourceId?: string | null;
|
|
89
|
+
amount: number;
|
|
90
|
+
timestamp: string | number;
|
|
91
|
+
credit?: (CreditBalanceResult & {
|
|
92
|
+
usageLimit: number;
|
|
93
|
+
}) | null;
|
|
94
|
+
};
|
|
95
|
+
/** The bulk read's answer: one evaluation per entitlement, plus the customer-level reason. */
|
|
96
|
+
export type CustomerEntitlementsEvaluation = {
|
|
97
|
+
entitlements: EntitlementEvaluation[];
|
|
98
|
+
accessDeniedReason: AccessDeniedReason | null;
|
|
99
|
+
};
|
|
100
|
+
/** Real-time events, in cache vocabulary. */
|
|
101
|
+
export type EntitlementsUpdatedEvent<Input> = EntitlementsState<Input> & {
|
|
102
|
+
customerId: string;
|
|
103
|
+
resourceId?: string | null;
|
|
104
|
+
};
|
|
105
|
+
export type UsageUpdatedEvent = {
|
|
106
|
+
customerId: string;
|
|
107
|
+
resourceId?: string | null;
|
|
108
|
+
entitlementReference: EntitlementQuery;
|
|
109
|
+
usage: {
|
|
110
|
+
currentUsage: number;
|
|
111
|
+
usagePeriodStart: number | null;
|
|
112
|
+
usagePeriodEnd: number | null;
|
|
113
|
+
usageUpdatedAt?: number | null;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* `affectsAllCustomers` is the only thing the read policy needs; `payload` is carried
|
|
118
|
+
* through untouched for the host's public event, which stays transport-shaped.
|
|
119
|
+
*/
|
|
120
|
+
export type PackagePublishedEvent<TPayload> = {
|
|
121
|
+
affectsAllCustomers: boolean;
|
|
122
|
+
payload: TPayload;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* What the read policy needs from a transport. Every member is in cache vocabulary —
|
|
126
|
+
* the wire format, its error envelope and its mapping are the transport's business.
|
|
127
|
+
*/
|
|
128
|
+
export interface EntitlementsTransport<Input, TPackagePublished = unknown> {
|
|
129
|
+
/** Classification is transport-specific knowledge, so the transport carries it. */
|
|
130
|
+
readonly classifier: TransportErrorClassifier;
|
|
131
|
+
/** Round-trips a cheap authenticated endpoint so a rejected key surfaces at startup, not on the first read. */
|
|
132
|
+
validateApiKey(): Promise<void>;
|
|
133
|
+
getEntitlementsState(customerId: string, resourceId: string | undefined, skipEdge?: boolean, timeout?: number): Promise<EntitlementsState<Input>>;
|
|
134
|
+
reportUsage(input: UsageMeasurementInput): Promise<UsageMeasurementResult>;
|
|
135
|
+
reportUsageBulk(input: UsageMeasurementBulkInput): Promise<UsageMeasurementResult[]>;
|
|
136
|
+
consumeCredits(input: CreditConsumptionInput): Promise<CreditConsumptionResult>;
|
|
137
|
+
reportEvent(events: UsageEventInput[]): Promise<unknown>;
|
|
138
|
+
consumeCreditsAsync(consumptions: CreditConsumptionInput[]): Promise<unknown>;
|
|
139
|
+
subscribeEntitlementsUpdated(): TransportObservable<EntitlementsUpdatedEvent<Input>>;
|
|
140
|
+
subscribeUsageUpdated(): TransportObservable<UsageUpdatedEvent>;
|
|
141
|
+
subscribePackagePublished(): TransportObservable<PackagePublishedEvent<TPackagePublished>>;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* How the read policy reports real-time updates to its host. The policy owns the cache
|
|
145
|
+
* handling — purge rules, timestamps, writes — and leaves public event payloads to the
|
|
146
|
+
* host, which is the only layer that knows their published shape.
|
|
147
|
+
*/
|
|
148
|
+
export interface EntitlementsRuntimeHooks<Input, TPackagePublished = unknown> {
|
|
149
|
+
onEntitlementsUpdated(event: EntitlementsUpdatedEvent<Input>): void;
|
|
150
|
+
onUsageUpdated(customerId: string, resourceId: Maybe<string>, entitlement: CachedEntitlement<EntitlementType.Feature>): void;
|
|
151
|
+
onPackagePublished(payload: TPackagePublished): void;
|
|
152
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R5cGVzL3RyYW5zcG9ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EntitlementQuery } from '@stigg/cache-core';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the unified feature-or-credit read params into a query. Exactly one of the two ids must
|
|
4
|
+
* be given; anything else is ambiguous and yields `undefined` for the caller to answer with a
|
|
5
|
+
* fallback.
|
|
6
|
+
*/
|
|
7
|
+
export declare function toEntitlementQuery(params: {
|
|
8
|
+
featureId?: string;
|
|
9
|
+
currencyId?: string;
|
|
10
|
+
}): EntitlementQuery | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toEntitlementQuery = toEntitlementQuery;
|
|
4
|
+
const cache_core_1 = require("@stigg/cache-core");
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the unified feature-or-credit read params into a query. Exactly one of the two ids must
|
|
7
|
+
* be given; anything else is ambiguous and yields `undefined` for the caller to answer with a
|
|
8
|
+
* fallback.
|
|
9
|
+
*/
|
|
10
|
+
function toEntitlementQuery(params) {
|
|
11
|
+
const hasFeature = params.featureId != null && params.featureId !== '';
|
|
12
|
+
const hasCredit = params.currencyId != null && params.currencyId !== '';
|
|
13
|
+
if (hasFeature === hasCredit) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
// After guards, exactly one is true
|
|
17
|
+
if (hasFeature) {
|
|
18
|
+
return { type: cache_core_1.EntitlementType.Feature, id: params.featureId };
|
|
19
|
+
}
|
|
20
|
+
return { type: cache_core_1.EntitlementType.Credit, id: params.currencyId };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXRsZW1lbnRRdWVyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9lbnRpdGxlbWVudFF1ZXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBT0EsZ0RBYUM7QUFwQkQsa0RBQXNFO0FBRXRFOzs7O0dBSUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxNQUFtRDtJQUNwRixNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLElBQUksSUFBSSxNQUFNLENBQUMsU0FBUyxLQUFLLEVBQUUsQ0FBQztJQUN2RSxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsVUFBVSxJQUFJLElBQUksSUFBSSxNQUFNLENBQUMsVUFBVSxLQUFLLEVBQUUsQ0FBQztJQUV4RSxJQUFJLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM3QixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsb0NBQW9DO0lBQ3BDLElBQUksVUFBVSxFQUFFLENBQUM7UUFDZixPQUFPLEVBQUUsSUFBSSxFQUFFLDRCQUFlLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBVSxFQUFFLENBQUM7SUFDbEUsQ0FBQztJQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsNEJBQWUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxVQUFXLEVBQUUsQ0FBQztBQUNsRSxDQUFDIn0=
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stigg/cache-runtime",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Transport-agnostic read policy for Stigg's client-side cache",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"typings": "dist/index.d.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"typings": "dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/stiggio/stigg-sdk.git",
|
|
15
|
+
"directory": "packages/cache-runtime"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "yarn run -T tsc -p tsconfig.build.json",
|
|
20
|
+
"lint": "yarn run -T eslint \"src/**/*.ts\"",
|
|
21
|
+
"test": "yarn run -T jest --forceExit --passWithNoTests"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist/**/*"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"lodash": "^4.18.1",
|
|
28
|
+
"lru-cache": "^10.0.1",
|
|
29
|
+
"nanoid": "^3.3.8"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@stigg/cache-core": "1.27.0",
|
|
33
|
+
"@stigg/cache-redis-store": "1.28.0",
|
|
34
|
+
"@stigg/entitlements-runtime": "2.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|