@thirdweb-dev/service-utils 0.5.0-nightly-6cf298a29-20240308012322 → 0.5.1

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 (142) hide show
  1. package/dist/cjs/cf-worker/index.js +152 -0
  2. package/dist/cjs/cf-worker/index.js.map +1 -0
  3. package/dist/cjs/cf-worker/usage.js +55 -0
  4. package/dist/cjs/cf-worker/usage.js.map +1 -0
  5. package/dist/cjs/core/api.js +42 -0
  6. package/dist/cjs/core/api.js.map +1 -0
  7. package/dist/cjs/core/authorize/client.js +104 -0
  8. package/dist/cjs/core/authorize/client.js.map +1 -0
  9. package/dist/cjs/core/authorize/index.js +110 -0
  10. package/dist/cjs/core/authorize/index.js.map +1 -0
  11. package/dist/cjs/core/authorize/service.js +60 -0
  12. package/dist/cjs/core/authorize/service.js.map +1 -0
  13. package/dist/cjs/core/authorize/types.js +3 -0
  14. package/dist/cjs/core/authorize/types.js.map +1 -0
  15. package/dist/cjs/core/rateLimit/index.js +60 -0
  16. package/dist/cjs/core/rateLimit/index.js.map +1 -0
  17. package/dist/cjs/core/rateLimit/types.js +3 -0
  18. package/dist/cjs/core/rateLimit/types.js.map +1 -0
  19. package/dist/cjs/core/services.js +85 -0
  20. package/dist/cjs/core/services.js.map +1 -0
  21. package/dist/cjs/core/types.js +3 -0
  22. package/dist/cjs/core/types.js.map +1 -0
  23. package/dist/cjs/core/usage.js +85 -0
  24. package/dist/cjs/core/usage.js.map +1 -0
  25. package/dist/cjs/index.js +13 -0
  26. package/dist/cjs/index.js.map +1 -0
  27. package/dist/cjs/mocks.js +61 -0
  28. package/dist/cjs/mocks.js.map +1 -0
  29. package/dist/cjs/node/index.js +156 -0
  30. package/dist/cjs/node/index.js.map +1 -0
  31. package/dist/cjs/package.json +1 -0
  32. package/dist/esm/cf-worker/index.js +145 -0
  33. package/dist/esm/cf-worker/index.js.map +1 -0
  34. package/dist/esm/cf-worker/usage.js +53 -0
  35. package/dist/esm/cf-worker/usage.js.map +1 -0
  36. package/dist/esm/core/api.js +38 -0
  37. package/dist/esm/core/api.js.map +1 -0
  38. package/dist/esm/core/authorize/client.js +99 -0
  39. package/dist/esm/core/authorize/client.js.map +1 -0
  40. package/dist/esm/core/authorize/index.js +107 -0
  41. package/dist/esm/core/authorize/index.js.map +1 -0
  42. package/dist/esm/core/authorize/service.js +57 -0
  43. package/dist/esm/core/authorize/service.js.map +1 -0
  44. package/dist/esm/core/authorize/types.js +2 -0
  45. package/dist/esm/core/authorize/types.js.map +1 -0
  46. package/dist/esm/core/rateLimit/index.js +57 -0
  47. package/dist/esm/core/rateLimit/index.js.map +1 -0
  48. package/dist/esm/core/rateLimit/types.js +2 -0
  49. package/dist/esm/core/rateLimit/types.js.map +1 -0
  50. package/dist/esm/core/services.js +81 -0
  51. package/dist/esm/core/services.js.map +1 -0
  52. package/dist/esm/core/types.js +2 -0
  53. package/dist/esm/core/types.js.map +1 -0
  54. package/dist/esm/core/usage.js +82 -0
  55. package/dist/esm/core/usage.js.map +1 -0
  56. package/dist/esm/index.js +5 -0
  57. package/dist/esm/index.js.map +1 -0
  58. package/dist/esm/mocks.js +58 -0
  59. package/dist/esm/mocks.js.map +1 -0
  60. package/dist/esm/node/index.js +149 -0
  61. package/dist/esm/node/index.js.map +1 -0
  62. package/dist/esm/package.json +1 -0
  63. package/dist/{declarations/src → types}/cf-worker/index.d.ts +8 -10
  64. package/dist/types/cf-worker/index.d.ts.map +1 -0
  65. package/dist/types/cf-worker/usage.d.ts +24 -0
  66. package/dist/types/cf-worker/usage.d.ts.map +1 -0
  67. package/dist/types/core/api.d.ts +121 -0
  68. package/dist/types/core/api.d.ts.map +1 -0
  69. package/dist/types/core/authorize/client.d.ts +17 -0
  70. package/dist/types/core/authorize/client.d.ts.map +1 -0
  71. package/dist/{declarations/src → types}/core/authorize/index.d.ts +6 -5
  72. package/dist/types/core/authorize/index.d.ts.map +1 -0
  73. package/dist/types/core/authorize/service.d.ts +4 -0
  74. package/dist/types/core/authorize/service.d.ts.map +1 -0
  75. package/dist/types/core/authorize/types.d.ts +10 -0
  76. package/dist/types/core/authorize/types.d.ts.map +1 -0
  77. package/dist/{declarations/src → types}/core/rateLimit/index.d.ts +4 -4
  78. package/dist/types/core/rateLimit/index.d.ts.map +1 -0
  79. package/dist/types/core/rateLimit/types.d.ts.map +1 -0
  80. package/dist/{declarations/src → types}/core/services.d.ts +55 -23
  81. package/dist/types/core/services.d.ts.map +1 -0
  82. package/dist/types/core/types.d.ts.map +1 -0
  83. package/dist/{declarations/src/cf-worker → types/core}/usage.d.ts +84 -30
  84. package/dist/types/core/usage.d.ts.map +1 -0
  85. package/dist/types/index.d.ts +5 -0
  86. package/dist/types/index.d.ts.map +1 -0
  87. package/dist/types/mocks.d.ts +7 -0
  88. package/dist/types/mocks.d.ts.map +1 -0
  89. package/dist/types/node/index.d.ts +23 -0
  90. package/dist/types/node/index.d.ts.map +1 -0
  91. package/package.json +42 -45
  92. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts +0 -2
  93. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts.map +0 -1
  94. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.dev.js +0 -272
  95. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.js +0 -7
  96. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.prod.js +0 -272
  97. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js +0 -258
  98. package/cf-worker/package.json +0 -4
  99. package/dist/declarations/src/cf-worker/index.d.ts.map +0 -1
  100. package/dist/declarations/src/cf-worker/usage.d.ts.map +0 -1
  101. package/dist/declarations/src/core/api.d.ts +0 -84
  102. package/dist/declarations/src/core/api.d.ts.map +0 -1
  103. package/dist/declarations/src/core/authorize/client.d.ts +0 -9
  104. package/dist/declarations/src/core/authorize/client.d.ts.map +0 -1
  105. package/dist/declarations/src/core/authorize/index.d.ts.map +0 -1
  106. package/dist/declarations/src/core/authorize/service.d.ts +0 -7
  107. package/dist/declarations/src/core/authorize/service.d.ts.map +0 -1
  108. package/dist/declarations/src/core/authorize/types.d.ts +0 -12
  109. package/dist/declarations/src/core/authorize/types.d.ts.map +0 -1
  110. package/dist/declarations/src/core/rateLimit/index.d.ts.map +0 -1
  111. package/dist/declarations/src/core/rateLimit/types.d.ts.map +0 -1
  112. package/dist/declarations/src/core/services.d.ts.map +0 -1
  113. package/dist/declarations/src/core/types.d.ts.map +0 -1
  114. package/dist/declarations/src/core/usageLimit/index.d.ts +0 -5
  115. package/dist/declarations/src/core/usageLimit/index.d.ts.map +0 -1
  116. package/dist/declarations/src/core/usageLimit/types.d.ts +0 -9
  117. package/dist/declarations/src/core/usageLimit/types.d.ts.map +0 -1
  118. package/dist/declarations/src/index.d.ts +0 -2
  119. package/dist/declarations/src/index.d.ts.map +0 -1
  120. package/dist/declarations/src/node/index.d.ts +0 -43
  121. package/dist/declarations/src/node/index.d.ts.map +0 -1
  122. package/dist/index-3b9a0743.esm.js +0 -572
  123. package/dist/index-62b88cac.cjs.dev.js +0 -576
  124. package/dist/index-aa324361.cjs.prod.js +0 -576
  125. package/dist/services-2aecbda8.esm.js +0 -65
  126. package/dist/services-508322f3.cjs.dev.js +0 -70
  127. package/dist/services-5c4d6977.cjs.prod.js +0 -70
  128. package/dist/thirdweb-dev-service-utils.cjs.d.ts +0 -2
  129. package/dist/thirdweb-dev-service-utils.cjs.d.ts.map +0 -1
  130. package/dist/thirdweb-dev-service-utils.cjs.dev.js +0 -12
  131. package/dist/thirdweb-dev-service-utils.cjs.js +0 -7
  132. package/dist/thirdweb-dev-service-utils.cjs.prod.js +0 -12
  133. package/dist/thirdweb-dev-service-utils.esm.js +0 -1
  134. package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts +0 -2
  135. package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts.map +0 -1
  136. package/node/dist/thirdweb-dev-service-utils-node.cjs.dev.js +0 -193
  137. package/node/dist/thirdweb-dev-service-utils-node.cjs.js +0 -7
  138. package/node/dist/thirdweb-dev-service-utils-node.cjs.prod.js +0 -193
  139. package/node/dist/thirdweb-dev-service-utils-node.esm.js +0 -180
  140. package/node/package.json +0 -4
  141. /package/dist/{declarations/src → types}/core/rateLimit/types.d.ts +0 -0
  142. /package/dist/{declarations/src → types}/core/types.d.ts +0 -0
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorizeWorker = authorizeWorker;
4
+ exports.extractAuthorizationData = extractAuthorizationData;
5
+ exports.hashSecretKey = hashSecretKey;
6
+ exports.logHttpRequest = logHttpRequest;
7
+ const tslib_1 = require("tslib");
8
+ const index_js_1 = require("../core/authorize/index.js");
9
+ tslib_1.__exportStar(require("./usage.js"), exports);
10
+ tslib_1.__exportStar(require("../core/services.js"), exports);
11
+ tslib_1.__exportStar(require("../core/rateLimit/index.js"), exports);
12
+ const DEFAULT_CACHE_TTL_SECONDS = 60;
13
+ async function authorizeWorker(authInput, serviceConfig) {
14
+ let authData;
15
+ try {
16
+ authData = await extractAuthorizationData(authInput);
17
+ }
18
+ catch (e) {
19
+ if (e instanceof Error && e.message === "KEY_CONFLICT") {
20
+ return {
21
+ authorized: false,
22
+ status: 400,
23
+ errorMessage: "Please pass either a client id or a secret key.",
24
+ errorCode: "KEY_CONFLICT",
25
+ };
26
+ }
27
+ return {
28
+ authorized: false,
29
+ status: 500,
30
+ errorMessage: "Internal Server Error",
31
+ errorCode: "INTERNAL_SERVER_ERROR",
32
+ };
33
+ }
34
+ return await (0, index_js_1.authorize)(authData, serviceConfig, {
35
+ get: async (clientId) => serviceConfig.kvStore.get(clientId),
36
+ put: (clientId, data) => serviceConfig.ctx.waitUntil(serviceConfig.kvStore.put(clientId, JSON.stringify({
37
+ updatedAt: Date.now(),
38
+ data,
39
+ }), {
40
+ expirationTtl: serviceConfig.cacheTtlSeconds &&
41
+ serviceConfig.cacheTtlSeconds >= DEFAULT_CACHE_TTL_SECONDS
42
+ ? serviceConfig.cacheTtlSeconds
43
+ : DEFAULT_CACHE_TTL_SECONDS,
44
+ })),
45
+ cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS,
46
+ });
47
+ }
48
+ async function extractAuthorizationData(authInput) {
49
+ const requestUrl = new URL(authInput.req.url);
50
+ const headers = authInput.req.headers;
51
+ const secretKey = headers.get("x-secret-key");
52
+ // prefer clientId that is explicitly passed in
53
+ let clientId = authInput.clientId ?? null;
54
+ if (!clientId) {
55
+ // next preference is clientId from header
56
+ clientId = headers.get("x-client-id");
57
+ }
58
+ // next preference is search param
59
+ if (!clientId) {
60
+ clientId = requestUrl.searchParams.get("clientId");
61
+ }
62
+ // bundle id from header is first preference
63
+ let bundleId = headers.get("x-bundle-id");
64
+ // next preference is search param
65
+ if (!bundleId) {
66
+ bundleId = requestUrl.searchParams.get("bundleId");
67
+ }
68
+ let ecosystemId = headers.get("x-ecosystem-id");
69
+ if (!ecosystemId) {
70
+ ecosystemId = requestUrl.searchParams.get("ecosystemId");
71
+ }
72
+ let ecosystemPartnerId = headers.get("x-ecosystem-partner-id");
73
+ if (!ecosystemPartnerId) {
74
+ ecosystemPartnerId = requestUrl.searchParams.get("ecosystemPartnerId");
75
+ }
76
+ let origin = headers.get("origin");
77
+ // if origin header is not available we'll fall back to referrer;
78
+ if (!origin) {
79
+ origin = headers.get("referer");
80
+ }
81
+ // if we have an origin at this point, normalize it
82
+ if (origin) {
83
+ try {
84
+ origin = new URL(origin).host;
85
+ }
86
+ catch (e) {
87
+ console.warn("failed to parse origin", origin, e);
88
+ }
89
+ }
90
+ // handle if we a secret key is passed in the headers
91
+ let secretKeyHash = null;
92
+ if (secretKey) {
93
+ // hash the secret key
94
+ secretKeyHash = await hashSecretKey(secretKey);
95
+ }
96
+ let jwt = null;
97
+ if (headers.has("authorization")) {
98
+ const authHeader = headers.get("authorization");
99
+ if (authHeader) {
100
+ const [type, token] = authHeader.split(" ");
101
+ if (type?.toLowerCase() === "bearer" && !!token) {
102
+ jwt = token;
103
+ }
104
+ }
105
+ }
106
+ return {
107
+ jwt,
108
+ hashedJWT: jwt ? await hashSecretKey(jwt) : null,
109
+ secretKey,
110
+ clientId,
111
+ ecosystemId,
112
+ ecosystemPartnerId,
113
+ origin,
114
+ bundleId,
115
+ secretKeyHash,
116
+ targetAddress: authInput.targetAddress,
117
+ };
118
+ }
119
+ async function hashSecretKey(secretKey) {
120
+ return bufferToHex(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(secretKey)));
121
+ }
122
+ function bufferToHex(buffer) {
123
+ return [...new Uint8Array(buffer)]
124
+ .map((x) => x.toString(16).padStart(2, "0"))
125
+ .join("");
126
+ }
127
+ async function logHttpRequest({ clientId, req, res, isAuthed, statusMessage, latencyMs, }) {
128
+ try {
129
+ const authorizationData = await extractAuthorizationData({ req, clientId });
130
+ const headers = req.headers;
131
+ console.log(JSON.stringify({
132
+ method: req.method,
133
+ pathname: req.url,
134
+ hasSecretKey: !!authorizationData.secretKey,
135
+ hasClientId: !!authorizationData.clientId,
136
+ hasJwt: !!authorizationData.jwt,
137
+ clientId: authorizationData.clientId,
138
+ isAuthed,
139
+ status: res.status,
140
+ sdkName: headers.get("x-sdk-name") ?? undefined,
141
+ sdkVersion: headers.get("x-sdk-version") ?? undefined,
142
+ platform: headers.get("x-sdk-platform") ?? undefined,
143
+ os: headers.get("x-sdk-os") ?? undefined,
144
+ latencyMs,
145
+ }));
146
+ if (statusMessage) {
147
+ console.log(`statusMessage=${statusMessage}`);
148
+ }
149
+ }
150
+ catch { }
151
+ }
152
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cf-worker/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publishUsageEvents = publishUsageEvents;
4
+ const aws4fetch_1 = require("aws4fetch");
5
+ const usage_js_1 = require("../core/usage.js");
6
+ // Initialize a singleton for AWS usage.
7
+ let _aws;
8
+ function getAws(options) {
9
+ if (!_aws) {
10
+ _aws = new aws4fetch_1.AwsClient(options);
11
+ }
12
+ return _aws;
13
+ }
14
+ /**
15
+ * Publish usage events. Provide the relevant fields for your application.
16
+ *
17
+ * Usage in Cloudflare Workers:
18
+ * ctx.waitUntil(
19
+ * publishUsageEvents(
20
+ * [event1, event2],
21
+ * { queueUrl, accessKeyId, secretAccessKey },
22
+ * )
23
+ * )
24
+ *
25
+ * @param usageEvents
26
+ * @param config
27
+ */
28
+ async function publishUsageEvents(usageEvents, config) {
29
+ const { queueUrl, accessKeyId, secretAccessKey, region = "us-west-2", } = config;
30
+ const entries = usageEvents.map((event) => {
31
+ // Enforce schema of usage event.
32
+ const parsed = usage_js_1.usageEventSchema.parse(event);
33
+ return {
34
+ Id: crypto.randomUUID(),
35
+ MessageBody: JSON.stringify(parsed),
36
+ };
37
+ });
38
+ const aws = getAws({
39
+ accessKeyId,
40
+ secretAccessKey,
41
+ region,
42
+ });
43
+ await aws.fetch(`https://sqs.${region}.amazonaws.com`, {
44
+ headers: {
45
+ "X-Amz-Target": "AmazonSQS.SendMessageBatch",
46
+ "X-Amz-Date": new Date().toISOString(),
47
+ "Content-Type": "application/x-amz-json-1.0",
48
+ },
49
+ body: JSON.stringify({
50
+ QueueUrl: queueUrl,
51
+ Entries: entries,
52
+ }),
53
+ });
54
+ }
55
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/cf-worker/usage.ts"],"names":[],"mappings":";;AAsES,gDAAkB;AAtE3B,yCAAsC;AACtC,+CAAqE;AAGrE,wCAAwC;AACxC,IAAI,IAA2B,CAAC;AAChC,SAAS,MAAM,CAAC,OAAmD;IACjE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,GAAG,IAAI,qBAAS,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,KAAK,UAAU,kBAAkB,CAC/B,WAAyB,EACzB,MAKC;IAED,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,eAAe,EACf,MAAM,GAAG,WAAW,GACrB,GAAG,MAAM,CAAC;IAEX,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,iCAAiC;QACjC,MAAM,MAAM,GAAG,2BAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;YACvB,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SACpC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,MAAM,CAAC;QACjB,WAAW;QACX,eAAe;QACf,MAAM;KACP,CAAC,CAAC;IACH,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,MAAM,gBAAgB,EAAE;QACrD,OAAO,EAAE;YACP,cAAc,EAAE,4BAA4B;YAC5C,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACtC,cAAc,EAAE,4BAA4B;SAC7C;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,OAAO;SACjB,CAAC;KACH,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchTeamAndProject = fetchTeamAndProject;
4
+ exports.updateRateLimitedAt = updateRateLimitedAt;
5
+ async function fetchTeamAndProject(authData, config) {
6
+ const { apiUrl, serviceApiKey } = config;
7
+ const clientId = authData.clientId;
8
+ const url = `${apiUrl}/v2/keys/use${clientId ? `?clientId=${clientId}` : ""}`;
9
+ const response = await fetch(url, {
10
+ method: "GET",
11
+ headers: {
12
+ ...(authData.secretKey ? { "x-secret-key": authData.secretKey } : {}),
13
+ ...(authData.jwt ? { Authorization: `Bearer ${authData.jwt}` } : {}),
14
+ "x-service-api-key": serviceApiKey,
15
+ "content-type": "application/json",
16
+ },
17
+ });
18
+ let text = "";
19
+ try {
20
+ text = await response.text();
21
+ return JSON.parse(text);
22
+ }
23
+ catch {
24
+ throw new Error(`Error fetching key metadata from API: ${response.status} - ${text}`);
25
+ }
26
+ }
27
+ async function updateRateLimitedAt(projectId, config) {
28
+ const { apiUrl, serviceScope: scope, serviceApiKey } = config;
29
+ const url = `${apiUrl}/usage/rateLimit`;
30
+ await fetch(url, {
31
+ method: "PUT",
32
+ headers: {
33
+ "x-service-api-key": serviceApiKey,
34
+ "content-type": "application/json",
35
+ },
36
+ body: JSON.stringify({
37
+ apiKeyId: projectId, // projectId is the apiKeyId
38
+ scope,
39
+ }),
40
+ });
41
+ }
42
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/core/api.ts"],"names":[],"mappings":";;AAyIA,kDA2BC;AAED,kDAmBC;AAhDM,KAAK,UAAU,mBAAmB,CACvC,QAA4B,EAC5B,MAAyB;IAEzB,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAEzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,MAAM,eAAe,QAAQ,CAAC,CAAC,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,mBAAmB,EAAE,aAAa;YAClC,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IAEH,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,yCAAyC,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CACrE,CAAC;IACJ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,MAAyB;IAEzB,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAE9D,MAAM,GAAG,GAAG,GAAG,MAAM,kBAAkB,CAAC;IAExC,MAAM,KAAK,CAAC,GAAG,EAAE;QACf,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,mBAAmB,EAAE,aAAa;YAClC,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,QAAQ,EAAE,SAAS,EAAE,4BAA4B;YACjD,KAAK;SACN,CAAC;KACH,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorizeClient = authorizeClient;
4
+ exports.authorizeDomain = authorizeDomain;
5
+ exports.authorizeBundleId = authorizeBundleId;
6
+ function authorizeClient(authOptions, teamAndProjectResponse) {
7
+ const { origin, bundleId } = authOptions;
8
+ const { team, project, authMethod } = teamAndProjectResponse;
9
+ const authResult = {
10
+ authorized: true,
11
+ team,
12
+ project,
13
+ authMethod,
14
+ };
15
+ // if there's no project, we'll return the authResult (JWT or teamId auth)
16
+ if (!project) {
17
+ return authResult;
18
+ }
19
+ if (authMethod === "secretKey") {
20
+ // if the auth was done using secretKey, we do not want to enforce domains or bundleIds
21
+ return authResult;
22
+ }
23
+ // check for public restrictions
24
+ if (project.domains.includes("*")) {
25
+ return authResult;
26
+ }
27
+ // validate domains
28
+ if (origin) {
29
+ if (authorizeDomain({
30
+ domains: project.domains,
31
+ origin,
32
+ })) {
33
+ return authResult;
34
+ }
35
+ return {
36
+ authorized: false,
37
+ errorMessage: `Invalid request: Unauthorized domain: ${origin}. You can view the restrictions on this API key at https://thirdweb.com/create-api-key`,
38
+ errorCode: "ORIGIN_UNAUTHORIZED",
39
+ status: 401,
40
+ };
41
+ }
42
+ // validate bundleId
43
+ if (bundleId) {
44
+ if (authorizeBundleId({
45
+ bundleIds: project.bundleIds,
46
+ bundleId,
47
+ })) {
48
+ return authResult;
49
+ }
50
+ return {
51
+ authorized: false,
52
+ errorMessage: `Invalid request: Unauthorized Bundle ID: ${bundleId}. You can view the restrictions on this API key at https://thirdweb.com/create-api-key`,
53
+ errorCode: "BUNDLE_UNAUTHORIZED",
54
+ status: 401,
55
+ };
56
+ }
57
+ return {
58
+ authorized: false,
59
+ errorMessage: "The keys are invalid. Please check the secret-key/clientId and try again.",
60
+ errorCode: "UNAUTHORIZED",
61
+ status: 401,
62
+ };
63
+ }
64
+ // Exposed for use in validating ecosystem partners settings
65
+ function authorizeDomain({ domains, origin, }) {
66
+ // find matching domain, or if all domains allowed
67
+ // embedded-wallet.thirdweb(-dev).com is automatically allowed
68
+ // because the rpc is passed from user's domain to embedded-wallet.thirdweb.com iframe for use.
69
+ // Note this doesn't allow embedded-wallets from being used if it's disabled. The service check that runs after enforces that.
70
+ return !![
71
+ ...domains,
72
+ "embedded-wallet.thirdweb.com",
73
+ "embedded-wallet.thirdweb-dev.com",
74
+ ].find((d) => {
75
+ // if any domain is allowed, we'll return true
76
+ if (d === "*") {
77
+ return true;
78
+ }
79
+ // special rule for `localhost`
80
+ // if the domain is localhost, we'll allow any origin that starts with localhost
81
+ if (d === "localhost" && origin.startsWith("localhost")) {
82
+ return true;
83
+ }
84
+ // If the allowedDomain has a wildcard,
85
+ // we'll check that the ending of our domain matches the wildcard
86
+ if (d.startsWith("*.")) {
87
+ // get rid of the * and check if it ends with the `.<domain>.<tld>`
88
+ const domainRoot = d.slice(1);
89
+ return origin.endsWith(domainRoot);
90
+ }
91
+ // If there's no wildcard, we'll check for an exact match
92
+ return d === origin;
93
+ });
94
+ }
95
+ function authorizeBundleId({ bundleIds, bundleId, }) {
96
+ // find matching bundle id, or if all bundles allowed
97
+ return !!bundleIds.find((b) => {
98
+ if (b === "*") {
99
+ return true;
100
+ }
101
+ return b === bundleId;
102
+ });
103
+ }
104
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/core/authorize/client.ts"],"names":[],"mappings":";;AASA,0CA0EC;AAGD,0CAmCC;AAED,8CAYC;AA9HD,SAAgB,eAAe,CAC7B,WAAuC,EACvC,sBAA8C;IAE9C,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC;IACzC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,sBAAsB,CAAC;IAE7D,MAAM,UAAU,GAAwB;QACtC,UAAU,EAAE,IAAI;QAChB,IAAI;QACJ,OAAO;QACP,UAAU;KACX,CAAC;IAEF,0EAA0E;IAC1E,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;QAC/B,uFAAuF;QACvF,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,gCAAgC;IAChC,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,mBAAmB;IACnB,IAAI,MAAM,EAAE,CAAC;QACX,IACE,eAAe,CAAC;YACd,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM;SACP,CAAC,EACF,CAAC;YACD,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,yCAAyC,MAAM,wFAAwF;YACrJ,SAAS,EAAE,qBAAqB;YAChC,MAAM,EAAE,GAAG;SACZ,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,IAAI,QAAQ,EAAE,CAAC;QACb,IACE,iBAAiB,CAAC;YAChB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ;SACT,CAAC,EACF,CAAC;YACD,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,4CAA4C,QAAQ,wFAAwF;YAC1J,SAAS,EAAE,qBAAqB;YAChC,MAAM,EAAE,GAAG;SACZ,CAAC;IACJ,CAAC;IAED,OAAO;QACL,UAAU,EAAE,KAAK;QACjB,YAAY,EACV,2EAA2E;QAC7E,SAAS,EAAE,cAAc;QACzB,MAAM,EAAE,GAAG;KACZ,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,SAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,MAAM,GACgC;IACtC,kDAAkD;IAClD,8DAA8D;IAC9D,+FAA+F;IAC/F,8HAA8H;IAC9H,OAAO,CAAC,CAAC;QACP,GAAG,OAAO;QACV,8BAA8B;QAC9B,kCAAkC;KACnC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;QACX,8CAA8C;QAC9C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,+BAA+B;QAC/B,gFAAgF;QAChF,IAAI,CAAC,KAAK,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,uCAAuC;QACvC,iEAAiE;QACjE,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,mEAAmE;YACnE,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,OAAO,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC;QAED,yDAAyD;QACzD,OAAO,CAAC,KAAK,MAAM,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAQ,GACkC;IAC1C,qDAAqD;IACrD,OAAO,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;QAC5B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,CAAC,KAAK,QAAQ,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorize = authorize;
4
+ const api_js_1 = require("../api.js");
5
+ const client_js_1 = require("./client.js");
6
+ const service_js_1 = require("./service.js");
7
+ async function authorize(authData, serviceConfig, cacheOptions) {
8
+ let teamAndProjectResponse = null;
9
+ const cacheKey = `key_v2_${authData.clientId ?? authData.secretKeyHash ?? authData.hashedJWT}`;
10
+ // TODO if we have cache options we want to check the cache first
11
+ if (cacheOptions) {
12
+ try {
13
+ const cachedKey = await cacheOptions.get(cacheKey);
14
+ if (cachedKey) {
15
+ const parsed = JSON.parse(cachedKey);
16
+ if ("updatedAt" in parsed) {
17
+ // we want to compare the updatedAt time to the current time
18
+ // if the difference is greater than the cacheTtl we want to ignore the cached data
19
+ const now = Date.now();
20
+ const diff = now - parsed.updatedAt;
21
+ const cacheTtlMs = cacheOptions.cacheTtlSeconds * 1000;
22
+ // only if the diff is less than the cacheTtl do we want to use the cached key
23
+ if (diff < cacheTtlMs) {
24
+ teamAndProjectResponse = parsed.teamAndProjectResponse;
25
+ }
26
+ }
27
+ else {
28
+ teamAndProjectResponse = parsed;
29
+ }
30
+ }
31
+ }
32
+ catch {
33
+ // ignore errors, proceed as if not in cache
34
+ }
35
+ }
36
+ // if we don't have a cached key, fetch from the API
37
+ if (!teamAndProjectResponse) {
38
+ try {
39
+ const { data, error } = await (0, api_js_1.fetchTeamAndProject)(authData, serviceConfig);
40
+ if (error) {
41
+ return {
42
+ authorized: false,
43
+ errorCode: error.code,
44
+ errorMessage: error.message,
45
+ status: error.statusCode,
46
+ };
47
+ }
48
+ if (!data) {
49
+ return {
50
+ authorized: false,
51
+ errorCode: "NO_KEY",
52
+ errorMessage: "No error but also no key returned.",
53
+ status: 500,
54
+ };
55
+ }
56
+ // if we have a key for sure then assign it
57
+ teamAndProjectResponse = data;
58
+ // cache the retrieved key if we have cache options
59
+ if (cacheOptions) {
60
+ // we await this always because it can be a promise or not
61
+ await cacheOptions.put(cacheKey, data);
62
+ }
63
+ }
64
+ catch (err) {
65
+ console.warn("failed to fetch key metadata from api", err);
66
+ return {
67
+ authorized: false,
68
+ status: 500,
69
+ errorMessage: "Failed to fetch key metadata. Please check your secret-key/clientId.",
70
+ errorCode: "FAILED_TO_FETCH_KEY",
71
+ };
72
+ }
73
+ }
74
+ if (!teamAndProjectResponse) {
75
+ return {
76
+ authorized: false,
77
+ status: 401,
78
+ errorMessage: "Key is invalid. Please check your secret-key/clientId.",
79
+ errorCode: "INVALID_KEY",
80
+ };
81
+ }
82
+ // now we can validate the key itself
83
+ const clientAuth = (0, client_js_1.authorizeClient)(authData, teamAndProjectResponse);
84
+ if (!clientAuth.authorized) {
85
+ return {
86
+ errorCode: clientAuth.errorCode,
87
+ authorized: false,
88
+ status: 401,
89
+ errorMessage: clientAuth.errorMessage,
90
+ };
91
+ }
92
+ // if we've made it this far we need to check service specific authorization
93
+ const serviceAuth = (0, service_js_1.authorizeService)(teamAndProjectResponse, serviceConfig);
94
+ if (!serviceAuth.authorized) {
95
+ return {
96
+ errorCode: serviceAuth.errorCode,
97
+ authorized: false,
98
+ status: 403,
99
+ errorMessage: serviceAuth.errorMessage,
100
+ };
101
+ }
102
+ // if we reach this point we are authorized!
103
+ return {
104
+ authorized: true,
105
+ team: teamAndProjectResponse.team,
106
+ project: teamAndProjectResponse.project,
107
+ authMethod: clientAuth.authMethod,
108
+ };
109
+ }
110
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/authorize/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorizeService = authorizeService;
4
+ function authorizeService(teamAndProjectResponse, serviceConfig) {
5
+ const { team, project, authMethod } = teamAndProjectResponse;
6
+ if (serviceConfig.serviceScope === null) {
7
+ // if explicitly set to null, we do not want to check for service level authorization
8
+ return {
9
+ authorized: true,
10
+ team,
11
+ authMethod,
12
+ };
13
+ }
14
+ if (!team.enabledScopes.includes(serviceConfig.serviceScope)) {
15
+ return {
16
+ authorized: false,
17
+ errorMessage: `Invalid request: Unauthorized service: ${serviceConfig.serviceScope}. You can view the restrictions for this team in your dashboard: https://thirdweb.com`,
18
+ errorCode: "SERVICE_UNAUTHORIZED",
19
+ status: 403,
20
+ };
21
+ }
22
+ if (!project) {
23
+ // acting on behalf of the team (ie. coming from dashboard), authorize
24
+ return {
25
+ authorized: true,
26
+ team,
27
+ authMethod,
28
+ };
29
+ }
30
+ // validate services
31
+ const services = project.services;
32
+ const service = services.find((srv) => srv.name === serviceConfig.serviceScope);
33
+ if (!service) {
34
+ return {
35
+ authorized: false,
36
+ errorMessage: `Invalid request: Unauthorized service: ${serviceConfig.serviceScope}. You can view the restrictions on this project in your dashboard: https://thirdweb.com`,
37
+ errorCode: "SERVICE_UNAUTHORIZED",
38
+ status: 403,
39
+ };
40
+ }
41
+ // validate service actions
42
+ if (serviceConfig.serviceAction) {
43
+ const isActionAllowed = service.actions.includes(serviceConfig.serviceAction);
44
+ if (!isActionAllowed) {
45
+ return {
46
+ authorized: false,
47
+ errorMessage: `Invalid request: Unauthorized action: ${serviceConfig.serviceScope} ${serviceConfig.serviceAction}. You can view the restrictions on this API key in your dashboard: https://thirdweb.com/create-api-key`,
48
+ errorCode: "SERVICE_ACTION_UNAUTHORIZED",
49
+ status: 403,
50
+ };
51
+ }
52
+ }
53
+ return {
54
+ authorized: true,
55
+ team,
56
+ project,
57
+ authMethod,
58
+ };
59
+ }
60
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../src/core/authorize/service.ts"],"names":[],"mappings":";;AAGA,4CAoEC;AApED,SAAgB,gBAAgB,CAC9B,sBAA8C,EAC9C,aAAgC;IAEhC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,sBAAsB,CAAC;IAE7D,IAAI,aAAa,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QACxC,qFAAqF;QACrF,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,IAAI;YACJ,UAAU;SACX,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7D,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,0CAA0C,aAAa,CAAC,YAAY,uFAAuF;YACzK,SAAS,EAAE,sBAAsB;YACjC,MAAM,EAAE,GAAG;SACZ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,sEAAsE;QACtE,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,IAAI;YACJ,UAAU;SACX,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAC3B,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,aAAa,CAAC,YAAY,CACjD,CAAC;IACF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,0CAA0C,aAAa,CAAC,YAAY,yFAAyF;YAC3K,SAAS,EAAE,sBAAsB;YACjC,MAAM,EAAE,GAAG;SACZ,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,aAAa,CAAC,aAAa,EAAE,CAAC;QAChC,MAAM,eAAe,GAAI,OAAO,CAAC,OAAoB,CAAC,QAAQ,CAC5D,aAAa,CAAC,aAAa,CAC5B,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO;gBACL,UAAU,EAAE,KAAK;gBACjB,YAAY,EAAE,yCAAyC,aAAa,CAAC,YAAY,IAAI,aAAa,CAAC,aAAa,yGAAyG;gBACzN,SAAS,EAAE,6BAA6B;gBACxC,MAAM,EAAE,GAAG;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU,EAAE,IAAI;QAChB,IAAI;QACJ,OAAO;QACP,UAAU;KACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/authorize/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rateLimit = rateLimit;
4
+ const api_js_1 = require("../api.js");
5
+ const RATE_LIMIT_WINDOW_SECONDS = 10;
6
+ async function rateLimit(args) {
7
+ const { project, limitPerSecond, serviceConfig, redis, sampleRate = 1.0, } = args;
8
+ const shouldSampleRequest = Math.random() < sampleRate;
9
+ if (!shouldSampleRequest) {
10
+ return {
11
+ rateLimited: false,
12
+ requestCount: 0,
13
+ rateLimit: 0,
14
+ };
15
+ }
16
+ if (limitPerSecond === 0) {
17
+ // No rate limit is provided. Assume the request is not rate limited.
18
+ return {
19
+ rateLimited: false,
20
+ requestCount: 0,
21
+ rateLimit: 0,
22
+ };
23
+ }
24
+ const serviceScope = serviceConfig.serviceScope;
25
+ // Gets the 10-second window for the current timestamp.
26
+ const timestampWindow = Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) *
27
+ RATE_LIMIT_WINDOW_SECONDS;
28
+ const key = `rate-limit:${serviceScope}:${project?.id}:${timestampWindow}`;
29
+ // Increment and get the current request count in this window.
30
+ const requestCount = await redis.incr(key);
31
+ if (requestCount === 1) {
32
+ // For the first increment, set an expiration to clean up this key.
33
+ await redis.expire(key, RATE_LIMIT_WINDOW_SECONDS);
34
+ }
35
+ // Get the limit for this window accounting for the sample rate.
36
+ const limitPerWindow = limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
37
+ if (requestCount > limitPerWindow) {
38
+ // Report rate limit hits.
39
+ if (project?.id) {
40
+ await (0, api_js_1.updateRateLimitedAt)(project.id, serviceConfig);
41
+ }
42
+ // Reject requests when they've exceeded 2x the rate limit.
43
+ if (requestCount > 2 * limitPerWindow) {
44
+ return {
45
+ rateLimited: true,
46
+ requestCount,
47
+ rateLimit: limitPerWindow,
48
+ status: 429,
49
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
50
+ errorCode: "RATE_LIMIT_EXCEEDED",
51
+ };
52
+ }
53
+ }
54
+ return {
55
+ rateLimited: false,
56
+ requestCount,
57
+ rateLimit: limitPerWindow,
58
+ };
59
+ }
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":";;AAeA,8BAiFC;AAhGD,sCAImB;AAGnB,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAQ9B,KAAK,UAAU,SAAS,CAAC,IAW/B;IACC,MAAM,EACJ,OAAO,EACP,cAAc,EACd,aAAa,EACb,KAAK,EACL,UAAU,GAAG,GAAG,GACjB,GAAG,IAAI,CAAC;IAET,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC;IACvD,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,qEAAqE;QACrE,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IAEhD,uDAAuD;IACvD,MAAM,eAAe,GACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,yBAAyB,CAAC,CAAC;QAC3D,yBAAyB,CAAC;IAC5B,MAAM,GAAG,GAAG,cAAc,YAAY,IAAI,OAAO,EAAE,EAAE,IAAI,eAAe,EAAE,CAAC;IAE3E,8DAA8D;IAC9D,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,mEAAmE;QACnE,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;IACrD,CAAC;IAED,gEAAgE;IAChE,MAAM,cAAc,GAClB,cAAc,GAAG,UAAU,GAAG,yBAAyB,CAAC;IAE1D,IAAI,YAAY,GAAG,cAAc,EAAE,CAAC;QAClC,0BAA0B;QAC1B,IAAI,OAAO,EAAE,EAAE,EAAE,CAAC;YAChB,MAAM,IAAA,4BAAmB,EAAC,OAAO,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACvD,CAAC;QAED,2DAA2D;QAC3D,IAAI,YAAY,GAAG,CAAC,GAAG,cAAc,EAAE,CAAC;YACtC,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,YAAY;gBACZ,SAAS,EAAE,cAAc;gBACzB,MAAM,EAAE,GAAG;gBACX,YAAY,EAAE,wBAAwB,YAAY,kBAAkB,cAAc,sFAAsF;gBACxK,SAAS,EAAE,qBAAqB;aACjC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,YAAY;QACZ,SAAS,EAAE,cAAc;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/rateLimit/types.ts"],"names":[],"mappings":""}