usage-sdk-test 0.1.0 → 0.1.2

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.
Files changed (105) hide show
  1. package/README.md +2 -1
  2. package/dist/errors.d.ts +20 -0
  3. package/dist/errors.d.ts.map +1 -0
  4. package/dist/errors.js +35 -0
  5. package/dist/errors.js.map +1 -0
  6. package/dist/index.d.ts +8 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +28 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/persistence/MemoryPersistenceProvider.d.ts +4 -0
  11. package/dist/persistence/MemoryPersistenceProvider.js +19 -0
  12. package/dist/persistence/MemoryPersistenceProvider.js.map +1 -0
  13. package/dist/persistence/PersistenceProvider.d.ts +22 -0
  14. package/dist/persistence/PersistenceProvider.js +3 -0
  15. package/dist/persistence/PersistenceProvider.js.map +1 -0
  16. package/dist/plans/MemoryPlanResolver.d.ts +14 -0
  17. package/dist/plans/MemoryPlanResolver.js +20 -0
  18. package/dist/plans/MemoryPlanResolver.js.map +1 -0
  19. package/dist/plans/PlanResolver.d.ts +6 -0
  20. package/dist/plans/PlanResolver.js +3 -0
  21. package/dist/plans/PlanResolver.js.map +1 -0
  22. package/dist/plans/StaticPlanResolver.d.ts +6 -0
  23. package/dist/plans/StaticPlanResolver.js +14 -0
  24. package/dist/plans/StaticPlanResolver.js.map +1 -0
  25. package/dist/pricing/matchRule.d.ts +2 -0
  26. package/dist/pricing/matchRule.d.ts.map +1 -0
  27. package/dist/pricing/matchRule.js +47 -0
  28. package/dist/pricing/matchRule.js.map +1 -0
  29. package/dist/pricing/quote.d.ts +2 -0
  30. package/dist/pricing/quote.d.ts.map +1 -0
  31. package/dist/pricing/quote.js +35 -0
  32. package/dist/pricing/quote.js.map +1 -0
  33. package/dist/providers/memory/MemoryLedgerStore.d.ts +16 -0
  34. package/dist/providers/memory/MemoryLedgerStore.d.ts.map +1 -0
  35. package/dist/providers/memory/MemoryLedgerStore.js +80 -0
  36. package/dist/providers/memory/MemoryLedgerStore.js.map +1 -0
  37. package/dist/providers/memory/MemoryLimitStore.d.ts +24 -0
  38. package/dist/providers/memory/MemoryLimitStore.d.ts.map +1 -0
  39. package/dist/providers/memory/MemoryLimitStore.js +88 -0
  40. package/dist/providers/memory/MemoryLimitStore.js.map +1 -0
  41. package/dist/providers/memory/MemoryPlanStore.d.ts +7 -0
  42. package/dist/providers/memory/MemoryPlanStore.d.ts.map +1 -0
  43. package/dist/providers/memory/MemoryPlanStore.js +15 -0
  44. package/dist/providers/memory/MemoryPlanStore.js.map +1 -0
  45. package/dist/providers/memory/MemoryUsageStore.d.ts +11 -0
  46. package/dist/providers/memory/MemoryUsageStore.d.ts.map +1 -0
  47. package/dist/providers/memory/MemoryUsageStore.js +16 -0
  48. package/dist/providers/memory/MemoryUsageStore.js.map +1 -0
  49. package/dist/sdk/UsageSdk.d.ts +40 -0
  50. package/dist/sdk/UsageSdk.d.ts.map +1 -0
  51. package/dist/sdk/UsageSdk.js +156 -0
  52. package/dist/sdk/UsageSdk.js.map +1 -0
  53. package/dist/sdk/createUsageSdk.d.ts +46 -0
  54. package/dist/sdk/createUsageSdk.d.ts.map +1 -0
  55. package/dist/sdk/createUsageSdk.js +27 -0
  56. package/dist/sdk/createUsageSdk.js.map +1 -0
  57. package/dist/stores/LedgerStore.d.ts +29 -0
  58. package/dist/stores/LedgerStore.d.ts.map +1 -0
  59. package/dist/stores/LedgerStore.js +3 -0
  60. package/dist/stores/LedgerStore.js.map +1 -0
  61. package/dist/stores/LimitStore.d.ts +20 -0
  62. package/dist/stores/LimitStore.d.ts.map +1 -0
  63. package/dist/stores/LimitStore.js +3 -0
  64. package/dist/stores/LimitStore.js.map +1 -0
  65. package/dist/stores/PlanStore.d.ts +4 -0
  66. package/dist/stores/PlanStore.d.ts.map +1 -0
  67. package/dist/stores/PlanStore.js +3 -0
  68. package/dist/stores/PlanStore.js.map +1 -0
  69. package/dist/stores/UsageStore.d.ts +9 -0
  70. package/dist/stores/UsageStore.d.ts.map +1 -0
  71. package/dist/stores/UsageStore.js +3 -0
  72. package/dist/stores/UsageStore.js.map +1 -0
  73. package/dist/types.d.ts +115 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/types.js +3 -0
  76. package/dist/types.js.map +1 -0
  77. package/dist/utils/fingerprint.d.ts +2 -0
  78. package/dist/utils/fingerprint.d.ts.map +1 -0
  79. package/dist/utils/fingerprint.js +20 -0
  80. package/dist/utils/fingerprint.js.map +1 -0
  81. package/dist/utils/guards.d.ts +5 -0
  82. package/dist/utils/guards.d.ts.map +1 -0
  83. package/dist/utils/guards.js +32 -0
  84. package/dist/utils/guards.js.map +1 -0
  85. package/package.json +9 -9
  86. package/examples/basic.ts +0 -35
  87. package/src/errors.ts +0 -19
  88. package/src/index.ts +0 -3
  89. package/src/pricing/matchRule.ts +0 -36
  90. package/src/pricing/quote.ts +0 -38
  91. package/src/providers/memory/MemoryLedgerStore.ts +0 -90
  92. package/src/providers/memory/MemoryLimitStore.ts +0 -102
  93. package/src/providers/memory/MemoryPlanStore.ts +0 -14
  94. package/src/providers/memory/MemoryUsageStore.ts +0 -10
  95. package/src/sdk/UsageSdk.ts +0 -117
  96. package/src/sdk/createUsageSdk.ts +0 -38
  97. package/src/stores/LedgerStore.ts +0 -30
  98. package/src/stores/LimitStore.ts +0 -5
  99. package/src/stores/PlanStore.ts +0 -5
  100. package/src/stores/UsageStore.ts +0 -5
  101. package/src/types.ts +0 -116
  102. package/src/utils/fingerprint.ts +0 -14
  103. package/src/utils/guards.ts +0 -23
  104. package/tsconfig.build.json +0 -14
  105. package/tsconfig.json +0 -13
package/README.md CHANGED
@@ -5,9 +5,10 @@
5
5
  ## Quick Start
6
6
 
7
7
  ```ts
8
- import { createUsageSdk } from "@chronnote/usage";
8
+ import { createUsageSdk, MemoryPersistenceProvider } from "usage-sdk-test";
9
9
 
10
10
  const sdk = createUsageSdk({
11
+ persistence: new MemoryPersistenceProvider(),
11
12
  plans: [
12
13
  {
13
14
  planId: "default",
@@ -0,0 +1,20 @@
1
+ import type { EnforceErrorCode } from "./types";
2
+ import type { CheckResult, GrantResult } from "./types";
3
+ export declare class UsageError extends Error {
4
+ readonly code: EnforceErrorCode;
5
+ readonly retryAfterMs?: number;
6
+ constructor(code: EnforceErrorCode, message?: string, retryAfterMs?: number);
7
+ }
8
+ export declare const toEnforceResultError: (err: unknown) => {
9
+ ok: false;
10
+ code: EnforceErrorCode;
11
+ message: string;
12
+ retryAfterMs: number | undefined;
13
+ } | {
14
+ ok: false;
15
+ code: "INVALID_ARGUMENT";
16
+ message: string;
17
+ retryAfterMs?: undefined;
18
+ };
19
+ export declare const toCheckResultError: (err: unknown) => CheckResult;
20
+ export declare const toGrantResultError: (err: unknown) => GrantResult;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEnB,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;CAK5E;AAED,eAAO,MAAM,oBAAoB,GAAI,KAAK,OAAO;;;;;;;;;;CAKhD,CAAC"}
package/dist/errors.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toGrantResultError = exports.toCheckResultError = exports.toEnforceResultError = exports.UsageError = void 0;
4
+ class UsageError extends Error {
5
+ code;
6
+ retryAfterMs;
7
+ constructor(code, message, retryAfterMs) {
8
+ super(message ?? code);
9
+ this.code = code;
10
+ this.retryAfterMs = retryAfterMs;
11
+ }
12
+ }
13
+ exports.UsageError = UsageError;
14
+ const toEnforceResultError = (err) => {
15
+ if (err instanceof UsageError) {
16
+ return { ok: false, code: err.code, message: err.message, retryAfterMs: err.retryAfterMs };
17
+ }
18
+ return { ok: false, code: "INVALID_ARGUMENT", message: err instanceof Error ? err.message : String(err) };
19
+ };
20
+ exports.toEnforceResultError = toEnforceResultError;
21
+ const toCheckResultError = (err) => {
22
+ if (err instanceof UsageError) {
23
+ return { ok: false, code: err.code, message: err.message, retryAfterMs: err.retryAfterMs };
24
+ }
25
+ return { ok: false, code: "INVALID_ARGUMENT", message: err instanceof Error ? err.message : String(err) };
26
+ };
27
+ exports.toCheckResultError = toCheckResultError;
28
+ const toGrantResultError = (err) => {
29
+ if (err instanceof UsageError) {
30
+ return { ok: false, code: err.code, message: err.message };
31
+ }
32
+ return { ok: false, code: "INVALID_ARGUMENT", message: err instanceof Error ? err.message : String(err) };
33
+ };
34
+ exports.toGrantResultError = toGrantResultError;
35
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAGA,MAAa,UAAW,SAAQ,KAAK;IAC1B,IAAI,CAAmB;IACvB,YAAY,CAAU;IAE/B,YAAY,IAAsB,EAAE,OAAgB,EAAE,YAAqB;QACzE,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF;AATD,gCASC;AAEM,MAAM,oBAAoB,GAAG,CAAC,GAAY,EAAE,EAAE;IACnD,IAAI,GAAG,YAAY,UAAU,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC;IACtG,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,IAAI,EAAE,kBAA2B,EAAE,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9H,CAAC,CAAC;AALW,QAAA,oBAAoB,wBAK/B;AAEK,MAAM,kBAAkB,GAAG,CAAC,GAAY,EAAe,EAAE;IAC9D,IAAI,GAAG,YAAY,UAAU,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC;IAC7F,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5G,CAAC,CAAC;AALW,QAAA,kBAAkB,sBAK7B;AAEK,MAAM,kBAAkB,GAAG,CAAC,GAAY,EAAe,EAAE;IAC9D,IAAI,GAAG,YAAY,UAAU,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5G,CAAC,CAAC;AALW,QAAA,kBAAkB,sBAK7B"}
@@ -0,0 +1,8 @@
1
+ export * from "./types";
2
+ export * from "./errors";
3
+ export { createUsageSdk } from "./sdk/createUsageSdk";
4
+ export type { PersistenceProvider, PersistenceInit, PersistenceStores } from "./persistence/PersistenceProvider";
5
+ export { MemoryPersistenceProvider } from "./persistence/MemoryPersistenceProvider";
6
+ export type { PlanResolver, PlanResolverInput } from "./plans/PlanResolver";
7
+ export { StaticPlanResolver } from "./plans/StaticPlanResolver";
8
+ export { MemoryPlanResolver } from "./plans/MemoryPlanResolver";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.MemoryPlanResolver = exports.StaticPlanResolver = exports.MemoryPersistenceProvider = exports.createUsageSdk = void 0;
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./errors"), exports);
20
+ var createUsageSdk_1 = require("./sdk/createUsageSdk");
21
+ Object.defineProperty(exports, "createUsageSdk", { enumerable: true, get: function () { return createUsageSdk_1.createUsageSdk; } });
22
+ var MemoryPersistenceProvider_1 = require("./persistence/MemoryPersistenceProvider");
23
+ Object.defineProperty(exports, "MemoryPersistenceProvider", { enumerable: true, get: function () { return MemoryPersistenceProvider_1.MemoryPersistenceProvider; } });
24
+ var StaticPlanResolver_1 = require("./plans/StaticPlanResolver");
25
+ Object.defineProperty(exports, "StaticPlanResolver", { enumerable: true, get: function () { return StaticPlanResolver_1.StaticPlanResolver; } });
26
+ var MemoryPlanResolver_1 = require("./plans/MemoryPlanResolver");
27
+ Object.defineProperty(exports, "MemoryPlanResolver", { enumerable: true, get: function () { return MemoryPlanResolver_1.MemoryPlanResolver; } });
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,2CAAyB;AACzB,uDAAsD;AAA7C,gHAAA,cAAc,OAAA;AAEvB,qFAAoF;AAA3E,sIAAA,yBAAyB,OAAA;AAElC,iEAAgE;AAAvD,wHAAA,kBAAkB,OAAA;AAC3B,iEAAgE;AAAvD,wHAAA,kBAAkB,OAAA"}
@@ -0,0 +1,4 @@
1
+ import type { PersistenceInit, PersistenceProvider, PersistenceStores } from "./PersistenceProvider";
2
+ export declare class MemoryPersistenceProvider implements PersistenceProvider {
3
+ create(init: PersistenceInit): PersistenceStores;
4
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryPersistenceProvider = void 0;
4
+ const MemoryPlanStore_1 = require("../providers/memory/MemoryPlanStore");
5
+ const MemoryLedgerStore_1 = require("../providers/memory/MemoryLedgerStore");
6
+ const MemoryLimitStore_1 = require("../providers/memory/MemoryLimitStore");
7
+ const MemoryUsageStore_1 = require("../providers/memory/MemoryUsageStore");
8
+ class MemoryPersistenceProvider {
9
+ create(init) {
10
+ return {
11
+ planStore: new MemoryPlanStore_1.MemoryPlanStore(init.plans),
12
+ ledgerStore: new MemoryLedgerStore_1.MemoryLedgerStore(init.initialBalances),
13
+ limitStore: new MemoryLimitStore_1.MemoryLimitStore(),
14
+ usageStore: new MemoryUsageStore_1.MemoryUsageStore(),
15
+ };
16
+ }
17
+ }
18
+ exports.MemoryPersistenceProvider = MemoryPersistenceProvider;
19
+ //# sourceMappingURL=MemoryPersistenceProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryPersistenceProvider.js","sourceRoot":"","sources":["../../src/persistence/MemoryPersistenceProvider.ts"],"names":[],"mappings":";;;AACA,yEAAsE;AACtE,6EAA0E;AAC1E,2EAAwE;AACxE,2EAAwE;AAExE,MAAa,yBAAyB;IACpC,MAAM,CAAC,IAAqB;QAC1B,OAAO;YACL,SAAS,EAAE,IAAI,iCAAe,CAAC,IAAI,CAAC,KAAK,CAAC;YAC1C,WAAW,EAAE,IAAI,qCAAiB,CAAC,IAAI,CAAC,eAAe,CAAC;YACxD,UAAU,EAAE,IAAI,mCAAgB,EAAE;YAClC,UAAU,EAAE,IAAI,mCAAgB,EAAE;SACnC,CAAC;IACJ,CAAC;CACF;AATD,8DASC"}
@@ -0,0 +1,22 @@
1
+ import type { PricePlan } from "../types";
2
+ import type { PlanStore } from "../stores/PlanStore";
3
+ import type { LedgerStore } from "../stores/LedgerStore";
4
+ import type { LimitStore } from "../stores/LimitStore";
5
+ import type { UsageStore } from "../stores/UsageStore";
6
+ import type { Money } from "../types";
7
+ export type PersistenceInit = {
8
+ plans: PricePlan[];
9
+ initialBalances?: Array<{
10
+ accountId: string;
11
+ money: Money;
12
+ }>;
13
+ };
14
+ export type PersistenceStores = {
15
+ planStore: PlanStore;
16
+ ledgerStore: LedgerStore;
17
+ limitStore: LimitStore;
18
+ usageStore: UsageStore;
19
+ };
20
+ export interface PersistenceProvider {
21
+ create(init: PersistenceInit): PersistenceStores;
22
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=PersistenceProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersistenceProvider.js","sourceRoot":"","sources":["../../src/persistence/PersistenceProvider.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { PlanResolver, PlanResolverInput } from "./PlanResolver";
2
+ export declare class MemoryPlanResolver implements PlanResolver {
3
+ private readonly map;
4
+ private readonly defaultPlanId;
5
+ constructor(input: {
6
+ defaultPlanId: string;
7
+ initial?: Array<{
8
+ accountId: string;
9
+ planId: string;
10
+ }>;
11
+ });
12
+ resolvePlanId(input: PlanResolverInput): Promise<string>;
13
+ setPlanId(accountId: string, planId: string): void;
14
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryPlanResolver = void 0;
4
+ class MemoryPlanResolver {
5
+ map = new Map();
6
+ defaultPlanId;
7
+ constructor(input) {
8
+ this.defaultPlanId = input.defaultPlanId;
9
+ for (const it of input.initial ?? [])
10
+ this.map.set(it.accountId, it.planId);
11
+ }
12
+ async resolvePlanId(input) {
13
+ return this.map.get(input.accountId) ?? this.defaultPlanId;
14
+ }
15
+ setPlanId(accountId, planId) {
16
+ this.map.set(accountId, planId);
17
+ }
18
+ }
19
+ exports.MemoryPlanResolver = MemoryPlanResolver;
20
+ //# sourceMappingURL=MemoryPlanResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryPlanResolver.js","sourceRoot":"","sources":["../../src/plans/MemoryPlanResolver.ts"],"names":[],"mappings":";;;AAEA,MAAa,kBAAkB;IACZ,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChC,aAAa,CAAS;IAEvC,YAAY,KAAwF;QAClG,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QACzC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAwB;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC;IAC7D,CAAC;IAED,SAAS,CAAC,SAAiB,EAAE,MAAc;QACzC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;CACF;AAhBD,gDAgBC"}
@@ -0,0 +1,6 @@
1
+ export type PlanResolverInput = {
2
+ accountId: string;
3
+ };
4
+ export interface PlanResolver {
5
+ resolvePlanId(input: PlanResolverInput): Promise<string>;
6
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=PlanResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanResolver.js","sourceRoot":"","sources":["../../src/plans/PlanResolver.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { PlanResolver, PlanResolverInput } from "./PlanResolver";
2
+ export declare class StaticPlanResolver implements PlanResolver {
3
+ private readonly planId;
4
+ constructor(planId: string);
5
+ resolvePlanId(_input: PlanResolverInput): Promise<string>;
6
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StaticPlanResolver = void 0;
4
+ class StaticPlanResolver {
5
+ planId;
6
+ constructor(planId) {
7
+ this.planId = planId;
8
+ }
9
+ async resolvePlanId(_input) {
10
+ return this.planId;
11
+ }
12
+ }
13
+ exports.StaticPlanResolver = StaticPlanResolver;
14
+ //# sourceMappingURL=StaticPlanResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StaticPlanResolver.js","sourceRoot":"","sources":["../../src/plans/StaticPlanResolver.ts"],"names":[],"mappings":";;;AAEA,MAAa,kBAAkB;IACA;IAA7B,YAA6B,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAE/C,KAAK,CAAC,aAAa,CAAC,MAAyB;QAC3C,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAND,gDAMC"}
@@ -0,0 +1,2 @@
1
+ import type { PriceRule, UsageEvent } from "../types";
2
+ export declare const pickBestRule: (rules: PriceRule[], event: UsageEvent) => PriceRule | null;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchRule.d.ts","sourceRoot":"","sources":["../../src/pricing/matchRule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAoBzD,eAAO,MAAM,YAAY,GAAI,OAAO,SAAS,EAAE,EAAE,OAAO,UAAU,KAAG,SAAS,GAAG,IAehF,CAAC"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pickBestRule = void 0;
4
+ const matchWhen = (when, dimensions) => {
5
+ if (!when)
6
+ return { ok: true, score: 0 };
7
+ const dims = dimensions ?? {};
8
+ let score = 0;
9
+ for (const [key, expected] of Object.entries(when)) {
10
+ const actual = dims[key];
11
+ if (expected === "*")
12
+ continue;
13
+ if (Array.isArray(expected)) {
14
+ if (!actual || !expected.includes(actual))
15
+ return { ok: false, score: 0 };
16
+ score += 1;
17
+ continue;
18
+ }
19
+ if (actual !== expected)
20
+ return { ok: false, score: 0 };
21
+ score += 1;
22
+ }
23
+ return { ok: true, score };
24
+ };
25
+ const pickBestRule = (rules, event) => {
26
+ const candidates = [];
27
+ for (const rule of rules) {
28
+ if (rule.meter !== event.meter)
29
+ continue;
30
+ const matched = matchWhen(rule.when, event.dimensions);
31
+ if (!matched.ok)
32
+ continue;
33
+ candidates.push({ rule, score: matched.score, priority: rule.priority ?? 0 });
34
+ }
35
+ if (candidates.length === 0)
36
+ return null;
37
+ candidates.sort((a, b) => {
38
+ if (b.score !== a.score)
39
+ return b.score - a.score;
40
+ if (b.priority !== a.priority)
41
+ return b.priority - a.priority;
42
+ return 0;
43
+ });
44
+ return candidates[0]?.rule ?? null;
45
+ };
46
+ exports.pickBestRule = pickBestRule;
47
+ //# sourceMappingURL=matchRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchRule.js","sourceRoot":"","sources":["../../src/pricing/matchRule.ts"],"names":[],"mappings":";;;AAEA,MAAM,SAAS,GAAG,CAAC,IAAmC,EAAE,UAAgD,EAAE,EAAE;IAC1G,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,QAAQ,KAAK,GAAG;YAAE,SAAS;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAC1E,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACxD,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEK,MAAM,YAAY,GAAG,CAAC,KAAkB,EAAE,KAAiB,EAAoB,EAAE;IACtF,MAAM,UAAU,GAAgE,EAAE,CAAC;IACnF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;YAAE,SAAS;QACzC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,SAAS;QAC1B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvB,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK;YAAE,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;QAClD,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;YAAE,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;QAC9D,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IACH,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;AACrC,CAAC,CAAC;AAfW,QAAA,YAAY,gBAevB"}
@@ -0,0 +1,2 @@
1
+ import type { PricePlan, Quote, QuoteInput } from "../types";
2
+ export declare const quoteWithPlan: (input: QuoteInput, plan: PricePlan) => Quote;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../src/pricing/quote.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAS,SAAS,EAAE,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAC;AAIlF,eAAO,MAAM,aAAa,GAAI,OAAO,UAAU,EAAE,MAAM,SAAS,KAAG,KAgClE,CAAC"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.quoteWithPlan = void 0;
4
+ const errors_1 = require("../errors");
5
+ const guards_1 = require("../utils/guards");
6
+ const matchRule_1 = require("./matchRule");
7
+ const quoteWithPlan = (input, plan) => {
8
+ if (!plan.rules.length)
9
+ throw new errors_1.UsageError("NO_PRICE_RULE", `plan ${plan.planId} has no rules`);
10
+ const items = [];
11
+ let currency = null;
12
+ let totalMinor = 0;
13
+ for (let i = 0; i < input.events.length; i++) {
14
+ const event = input.events[i];
15
+ (0, guards_1.assertUsageEvent)(event, `events[${i}]`);
16
+ const rule = (0, matchRule_1.pickBestRule)(plan.rules, event);
17
+ if (!rule) {
18
+ throw new errors_1.UsageError("NO_PRICE_RULE", `no price rule for meter=${event.meter}`);
19
+ }
20
+ if (!currency)
21
+ currency = rule.currency;
22
+ if (currency !== rule.currency) {
23
+ throw new errors_1.UsageError("CURRENCY_MISMATCH", `mixed currencies in a single quote are not supported (got ${currency} and ${rule.currency})`);
24
+ }
25
+ (0, guards_1.assertNonNegativeInteger)(rule.unitPriceMinor, "rule.unitPriceMinor");
26
+ const costMinor = rule.unitPriceMinor * event.quantity;
27
+ (0, guards_1.assertNonNegativeInteger)(costMinor, "computed costMinor");
28
+ totalMinor += costMinor;
29
+ items.push({ event, costMinor, ruleId: rule.ruleId });
30
+ }
31
+ const total = { currency: currency ?? "CNY", amountMinor: totalMinor };
32
+ return { total, items };
33
+ };
34
+ exports.quoteWithPlan = quoteWithPlan;
35
+ //# sourceMappingURL=quote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/pricing/quote.ts"],"names":[],"mappings":";;;AAAA,sCAAuC;AAEvC,4CAA6E;AAC7E,2CAA2C;AAEpC,MAAM,aAAa,GAAG,CAAC,KAAiB,EAAE,IAAe,EAAS,EAAE;IACzE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,MAAM,IAAI,mBAAU,CAAC,eAAe,EAAE,QAAQ,IAAI,CAAC,MAAM,eAAe,CAAC,CAAC;IAElG,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,IAAI,QAAQ,GAA6B,IAAI,CAAC;IAC9C,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC;QAC/B,IAAA,yBAAgB,EAAC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;QAExC,MAAM,IAAI,GAAG,IAAA,wBAAY,EAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,mBAAU,CAAC,eAAe,EAAE,2BAA2B,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAClF,CAAC;QAED,IAAI,CAAC,QAAQ;YAAE,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACxC,IAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,mBAAU,CAAC,mBAAmB,EAAE,6DAA6D,QAAQ,QAAQ,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC3I,CAAC;QAED,IAAA,iCAAwB,EAAC,IAAI,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;QAErE,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC;QACvD,IAAA,iCAAwB,EAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;QAC1D,UAAU,IAAI,SAAS,CAAC;QAExB,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,KAAK,GAAU,EAAE,QAAQ,EAAE,QAAQ,IAAI,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC9E,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC,CAAC;AAhCW,QAAA,aAAa,iBAgCxB"}
@@ -0,0 +1,16 @@
1
+ import type { LedgerApplyResult, LedgerCreditInput, LedgerDebitInput, LedgerStore } from "../../stores/LedgerStore";
2
+ import type { Money } from "../../types";
3
+ export declare class MemoryLedgerStore implements LedgerStore {
4
+ private readonly balances;
5
+ private readonly idempotency;
6
+ constructor(initialBalances?: Array<{
7
+ accountId: string;
8
+ money: Money;
9
+ }>);
10
+ getBalance(input: {
11
+ accountId: string;
12
+ currency: Money["currency"];
13
+ }): Promise<Money>;
14
+ debit(input: LedgerDebitInput): Promise<LedgerApplyResult>;
15
+ credit(input: LedgerCreditInput): Promise<LedgerApplyResult>;
16
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryLedgerStore.d.ts","sourceRoot":"","sources":["../../../src/providers/memory/MemoryLedgerStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACvH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAgB5C,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwC;gBAExD,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IAQlE,UAAU,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IAMrF,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA4B1D,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAyBnE"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryLedgerStore = void 0;
4
+ const errors_1 = require("../../errors");
5
+ const guards_1 = require("../../utils/guards");
6
+ const makeBalanceKey = (accountId, currency) => `${accountId}::${currency}`;
7
+ const randomId = () => {
8
+ const c = globalThis.crypto;
9
+ if (c?.randomUUID)
10
+ return c.randomUUID();
11
+ return `tx_${Date.now()}_${Math.random().toString(16).slice(2)}`;
12
+ };
13
+ class MemoryLedgerStore {
14
+ balances = new Map();
15
+ idempotency = new Map();
16
+ constructor(initialBalances) {
17
+ for (const b of initialBalances ?? []) {
18
+ (0, guards_1.assertMoney)(b.money, "initialBalances[].money");
19
+ const key = makeBalanceKey(b.accountId, b.money.currency);
20
+ this.balances.set(key, b.money.amountMinor);
21
+ }
22
+ }
23
+ async getBalance(input) {
24
+ const key = makeBalanceKey(input.accountId, input.currency);
25
+ const amountMinor = this.balances.get(key) ?? 0;
26
+ return { currency: input.currency, amountMinor };
27
+ }
28
+ async debit(input) {
29
+ (0, guards_1.assertMoney)(input.money, "money");
30
+ if (!input.idempotencyKey)
31
+ throw new errors_1.UsageError("INVALID_ARGUMENT", "idempotencyKey is required");
32
+ if (!input.fingerprint)
33
+ throw new errors_1.UsageError("INVALID_ARGUMENT", "fingerprint is required");
34
+ (0, guards_1.assertNonNegativeInteger)(input.nowMs, "nowMs");
35
+ const existing = this.idempotency.get(input.idempotencyKey);
36
+ if (existing) {
37
+ if (existing.fingerprint !== input.fingerprint)
38
+ throw new errors_1.UsageError("IDEMPOTENCY_CONFLICT", "idempotencyKey already used with different input");
39
+ return existing.result;
40
+ }
41
+ const key = makeBalanceKey(input.accountId, input.money.currency);
42
+ const current = this.balances.get(key) ?? 0;
43
+ if (current < input.money.amountMinor)
44
+ throw new errors_1.UsageError("INSUFFICIENT_BALANCE", "insufficient balance");
45
+ const next = current - input.money.amountMinor;
46
+ this.balances.set(key, next);
47
+ const result = {
48
+ txId: randomId(),
49
+ balanceAfter: { currency: input.money.currency, amountMinor: next },
50
+ };
51
+ this.idempotency.set(input.idempotencyKey, { fingerprint: input.fingerprint, result });
52
+ return result;
53
+ }
54
+ async credit(input) {
55
+ (0, guards_1.assertMoney)(input.money, "money");
56
+ if (!input.idempotencyKey)
57
+ throw new errors_1.UsageError("INVALID_ARGUMENT", "idempotencyKey is required");
58
+ if (!input.fingerprint)
59
+ throw new errors_1.UsageError("INVALID_ARGUMENT", "fingerprint is required");
60
+ (0, guards_1.assertNonNegativeInteger)(input.nowMs, "nowMs");
61
+ const existing = this.idempotency.get(input.idempotencyKey);
62
+ if (existing) {
63
+ if (existing.fingerprint !== input.fingerprint)
64
+ throw new errors_1.UsageError("IDEMPOTENCY_CONFLICT", "idempotencyKey already used with different input");
65
+ return existing.result;
66
+ }
67
+ const key = makeBalanceKey(input.accountId, input.money.currency);
68
+ const current = this.balances.get(key) ?? 0;
69
+ const next = current + input.money.amountMinor;
70
+ this.balances.set(key, next);
71
+ const result = {
72
+ txId: randomId(),
73
+ balanceAfter: { currency: input.money.currency, amountMinor: next },
74
+ };
75
+ this.idempotency.set(input.idempotencyKey, { fingerprint: input.fingerprint, result });
76
+ return result;
77
+ }
78
+ }
79
+ exports.MemoryLedgerStore = MemoryLedgerStore;
80
+ //# sourceMappingURL=MemoryLedgerStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryLedgerStore.js","sourceRoot":"","sources":["../../../src/providers/memory/MemoryLedgerStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { LimitStore } from "../../stores/LimitStore";
2
+ export declare class MemoryLimitStore implements LimitStore {
3
+ private readonly counters;
4
+ private getCounter;
5
+ private setCounter;
6
+ consumeRpm(input: {
7
+ accountId: string;
8
+ rpm: number;
9
+ requestCount: number;
10
+ nowMs: number;
11
+ }): Promise<void>;
12
+ consumeDailyMinor(input: {
13
+ accountId: string;
14
+ amountMinor: number;
15
+ limitMinor: number;
16
+ nowMs: number;
17
+ }): Promise<void>;
18
+ consumeMonthlyMinor(input: {
19
+ accountId: string;
20
+ amountMinor: number;
21
+ limitMinor: number;
22
+ nowMs: number;
23
+ }): Promise<void>;
24
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryLimitStore.d.ts","sourceRoot":"","sources":["../../../src/providers/memory/MemoryLimitStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAoC7D,qBAAa,gBAAiB,YAAW,UAAU;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IAEvD,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,UAAU;IAIZ,UAAU,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBzG,iBAAiB,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAetH,mBAAmB,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAc/H"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryLimitStore = void 0;
4
+ const errors_1 = require("../../errors");
5
+ const guards_1 = require("../../utils/guards");
6
+ const pad2 = (n) => String(n).padStart(2, "0");
7
+ const getMinuteKey = (nowMs) => {
8
+ const d = new Date(nowMs);
9
+ return `${d.getUTCFullYear()}${pad2(d.getUTCMonth() + 1)}${pad2(d.getUTCDate())}${pad2(d.getUTCHours())}${pad2(d.getUTCMinutes())}`;
10
+ };
11
+ const getDayKey = (nowMs) => {
12
+ const d = new Date(nowMs);
13
+ return `${d.getUTCFullYear()}${pad2(d.getUTCMonth() + 1)}${pad2(d.getUTCDate())}`;
14
+ };
15
+ const getMonthKey = (nowMs) => {
16
+ const d = new Date(nowMs);
17
+ return `${d.getUTCFullYear()}${pad2(d.getUTCMonth() + 1)}`;
18
+ };
19
+ const endOfUtcMinute = (nowMs) => Math.floor(nowMs / 60000) * 60000 + 60000;
20
+ const endOfUtcDay = (nowMs) => {
21
+ const d = new Date(nowMs);
22
+ const next = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() + 1, 0, 0, 0, 0);
23
+ return next;
24
+ };
25
+ const endOfUtcMonth = (nowMs) => {
26
+ const d = new Date(nowMs);
27
+ const next = Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1, 0, 0, 0, 0);
28
+ return next;
29
+ };
30
+ class MemoryLimitStore {
31
+ counters = new Map();
32
+ getCounter(key, nowMs) {
33
+ const c = this.counters.get(key);
34
+ if (!c)
35
+ return null;
36
+ if (c.expiresAtMs <= nowMs) {
37
+ this.counters.delete(key);
38
+ return null;
39
+ }
40
+ return c;
41
+ }
42
+ setCounter(key, value, expiresAtMs) {
43
+ this.counters.set(key, { value, expiresAtMs });
44
+ }
45
+ async consumeRpm(input) {
46
+ (0, guards_1.assertNonNegativeInteger)(input.nowMs, "nowMs");
47
+ (0, guards_1.assertNonNegativeInteger)(input.requestCount, "requestCount");
48
+ if (input.rpm <= 0)
49
+ throw new errors_1.UsageError("RPM_LIMIT_EXCEEDED", "rpm limit exceeded", 60_000);
50
+ const window = getMinuteKey(input.nowMs);
51
+ const key = `rpm::${input.accountId}::${window}`;
52
+ const current = this.getCounter(key, input.nowMs)?.value ?? 0;
53
+ const next = current + input.requestCount;
54
+ if (next > input.rpm) {
55
+ const retryAfterMs = Math.max(0, endOfUtcMinute(input.nowMs) - input.nowMs);
56
+ throw new errors_1.UsageError("RPM_LIMIT_EXCEEDED", "rpm limit exceeded", retryAfterMs);
57
+ }
58
+ this.setCounter(key, next, endOfUtcMinute(input.nowMs));
59
+ }
60
+ async consumeDailyMinor(input) {
61
+ (0, guards_1.assertNonNegativeInteger)(input.nowMs, "nowMs");
62
+ (0, guards_1.assertNonNegativeInteger)(input.amountMinor, "amountMinor");
63
+ if (input.limitMinor <= 0)
64
+ throw new errors_1.UsageError("DAILY_LIMIT_EXCEEDED", "daily limit exceeded");
65
+ const window = getDayKey(input.nowMs);
66
+ const key = `dailyMinor::${input.accountId}::${window}`;
67
+ const current = this.getCounter(key, input.nowMs)?.value ?? 0;
68
+ const next = current + input.amountMinor;
69
+ if (next > input.limitMinor)
70
+ throw new errors_1.UsageError("DAILY_LIMIT_EXCEEDED", "daily limit exceeded");
71
+ this.setCounter(key, next, endOfUtcDay(input.nowMs));
72
+ }
73
+ async consumeMonthlyMinor(input) {
74
+ (0, guards_1.assertNonNegativeInteger)(input.nowMs, "nowMs");
75
+ (0, guards_1.assertNonNegativeInteger)(input.amountMinor, "amountMinor");
76
+ if (input.limitMinor <= 0)
77
+ throw new errors_1.UsageError("MONTHLY_LIMIT_EXCEEDED", "monthly limit exceeded");
78
+ const window = getMonthKey(input.nowMs);
79
+ const key = `monthlyMinor::${input.accountId}::${window}`;
80
+ const current = this.getCounter(key, input.nowMs)?.value ?? 0;
81
+ const next = current + input.amountMinor;
82
+ if (next > input.limitMinor)
83
+ throw new errors_1.UsageError("MONTHLY_LIMIT_EXCEEDED", "monthly limit exceeded");
84
+ this.setCounter(key, next, endOfUtcMonth(input.nowMs));
85
+ }
86
+ }
87
+ exports.MemoryLimitStore = MemoryLimitStore;
88
+ //# sourceMappingURL=MemoryLimitStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryLimitStore.js","sourceRoot":"","sources":["../../../src/providers/memory/MemoryLimitStore.ts"],"names":[],"mappings":"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"}