@majikah/majik-api 0.1.1 → 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.
- package/dist/majik-api.d.ts +78 -4
- package/dist/majik-api.js +138 -4
- package/dist/types.d.ts +26 -0
- package/dist/utils.js +1 -0
- package/package.json +1 -1
package/dist/majik-api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DomainWhitelist, IPWhitelist, MajikAPICreateOptions, MajikAPIJSON, MajikAPISettings, RateLimit, RateLimitFrequency } from "./types";
|
|
1
|
+
import type { DomainWhitelist, IPWhitelist, MajikAPICreateOptions, MajikAPIJSON, MajikAPISettings, Quota, QuotaFrequency, RateLimit, RateLimitFrequency } from "./types";
|
|
2
2
|
export declare class MajikAPI {
|
|
3
3
|
private readonly _id;
|
|
4
4
|
private readonly _owner_id;
|
|
@@ -26,12 +26,14 @@ export declare class MajikAPI {
|
|
|
26
26
|
* Accepts the raw output of `toJSON()`, a Supabase row, or a Redis cache hit.
|
|
27
27
|
*
|
|
28
28
|
* `raw_api_key` is intentionally NOT restored — it is never in the JSON.
|
|
29
|
+
* `is_valid` is intentionally NOT restored — it is a computed getter.
|
|
29
30
|
*/
|
|
30
31
|
static fromJSON(data: MajikAPIJSON): MajikAPI;
|
|
31
32
|
/**
|
|
32
33
|
* Serialise to a plain JSON-safe object matching MajikAPIJSON.
|
|
33
34
|
* Safe to store in Supabase or cache in Redis.
|
|
34
35
|
* raw_api_key is NEVER included.
|
|
36
|
+
* is_valid is computed at serialisation time from isActive().
|
|
35
37
|
*/
|
|
36
38
|
toJSON(): MajikAPIJSON;
|
|
37
39
|
/**
|
|
@@ -58,14 +60,61 @@ export declare class MajikAPI {
|
|
|
58
60
|
* (500 req/min). Attempting to set a higher rate will throw unless
|
|
59
61
|
* bypassSafeLimit is explicitly passed as true.
|
|
60
62
|
*
|
|
61
|
-
* @param amount
|
|
62
|
-
* @param frequency
|
|
63
|
+
* @param amount - Number of allowed requests per frequency window.
|
|
64
|
+
* @param frequency - The time window unit.
|
|
63
65
|
* @param bypassSafeLimit - When true, skips the MAX_RATE_LIMIT ceiling check.
|
|
64
|
-
*
|
|
66
|
+
* Defaults to false. Use with caution.
|
|
65
67
|
*/
|
|
66
68
|
setRateLimit(amount: number, frequency: RateLimitFrequency, bypassSafeLimit?: boolean): void;
|
|
67
69
|
/** Reset the rate limit back to DEFAULT_RATE_LIMIT. */
|
|
68
70
|
resetRateLimit(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Set a fixed lifetime quota for this key.
|
|
73
|
+
* Once total usage reaches `limit`, isQuotaExceeded() returns true.
|
|
74
|
+
*
|
|
75
|
+
* @param limit - Maximum total number of requests allowed. Must be a
|
|
76
|
+
* positive integer.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* key.setFixedQuota(10_000); // 10 000 requests total, ever
|
|
80
|
+
*/
|
|
81
|
+
setFixedQuota(limit: number): void;
|
|
82
|
+
/**
|
|
83
|
+
* Set a periodic rolling quota for this key.
|
|
84
|
+
* Usage is expected to be tracked externally (e.g. in Redis or Supabase)
|
|
85
|
+
* and passed into isQuotaExceeded() for comparison.
|
|
86
|
+
*
|
|
87
|
+
* @param limit - Maximum number of requests allowed per `frequency` window.
|
|
88
|
+
* @param frequency - The time window unit.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* key.setPeriodicQuota(50_000, "months"); // 50k requests per month
|
|
92
|
+
* key.setPeriodicQuota(1_000, "days"); // 1k requests per day
|
|
93
|
+
*/
|
|
94
|
+
setPeriodicQuota(limit: number, frequency: QuotaFrequency): void;
|
|
95
|
+
/**
|
|
96
|
+
* Remove any quota restriction from this key.
|
|
97
|
+
* After calling this, isQuotaExceeded() will always return false.
|
|
98
|
+
*/
|
|
99
|
+
clearQuota(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Check whether the given usage count has met or exceeded this key's quota.
|
|
102
|
+
*
|
|
103
|
+
* This method does NOT track usage itself — `currentUsage` must be supplied
|
|
104
|
+
* by the caller from whatever store you use (Redis counter, Supabase
|
|
105
|
+
* aggregate, etc.).
|
|
106
|
+
*
|
|
107
|
+
* For a `fixed` quota, pass the key's all-time request count.
|
|
108
|
+
* For a `periodic` quota, pass the request count for the current window.
|
|
109
|
+
*
|
|
110
|
+
* Returns:
|
|
111
|
+
* - `false` if quota is null (unlimited).
|
|
112
|
+
* - `true` if currentUsage >= the configured limit.
|
|
113
|
+
* - `false` if currentUsage < the configured limit.
|
|
114
|
+
*
|
|
115
|
+
* @param currentUsage - The usage count to check against the quota.
|
|
116
|
+
*/
|
|
117
|
+
isQuotaExceeded(currentUsage: number): boolean;
|
|
69
118
|
/**
|
|
70
119
|
* Rotate the API key. Generates a new raw key (or accepts a provided one),
|
|
71
120
|
* hashes it, and replaces _api_key. The stable _id and _owner_id are
|
|
@@ -137,9 +186,33 @@ export declare class MajikAPI {
|
|
|
137
186
|
get timestamp(): string;
|
|
138
187
|
get restricted(): boolean;
|
|
139
188
|
get validUntil(): Date | null;
|
|
189
|
+
/**
|
|
190
|
+
* Whether this key is valid for use right now.
|
|
191
|
+
* True when the key is active (not expired, not restricted).
|
|
192
|
+
*
|
|
193
|
+
* Note: this does NOT factor in quota — quota is a runtime check that
|
|
194
|
+
* requires external usage data. Use isQuotaExceeded(currentUsage) for that.
|
|
195
|
+
*/
|
|
196
|
+
get is_valid(): boolean;
|
|
140
197
|
/** Returns a deep clone — mutations to the returned object have no effect. */
|
|
141
198
|
get settings(): Readonly<MajikAPISettings>;
|
|
142
199
|
get rateLimit(): Readonly<RateLimit>;
|
|
200
|
+
/**
|
|
201
|
+
* The current quota configuration.
|
|
202
|
+
* null means unlimited.
|
|
203
|
+
* Use isQuotaExceeded(currentUsage) to compare against live usage.
|
|
204
|
+
*/
|
|
205
|
+
get quota(): Readonly<Quota>;
|
|
206
|
+
/**
|
|
207
|
+
* The configured quota limit, or null if no quota is set.
|
|
208
|
+
* Convenience shorthand for `key.quota?.limit ?? null`.
|
|
209
|
+
*/
|
|
210
|
+
get quotaLimit(): number | null;
|
|
211
|
+
/**
|
|
212
|
+
* The quota frequency if this is a periodic quota, otherwise null.
|
|
213
|
+
* Useful for determining the reset window without inspecting the full quota object.
|
|
214
|
+
*/
|
|
215
|
+
get quotaFrequency(): QuotaFrequency | null;
|
|
143
216
|
get ipWhitelist(): Readonly<IPWhitelist>;
|
|
144
217
|
get domainWhitelist(): Readonly<DomainWhitelist>;
|
|
145
218
|
get allowedMethods(): string[];
|
|
@@ -159,6 +232,7 @@ export declare class MajikAPI {
|
|
|
159
232
|
*/
|
|
160
233
|
get status(): "active" | "restricted" | "expired" | "revoked";
|
|
161
234
|
private static parseDate;
|
|
235
|
+
private static assertQuotaFrequency;
|
|
162
236
|
private static validateSettings;
|
|
163
237
|
toString(): string;
|
|
164
238
|
}
|
package/dist/majik-api.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { DEFAULT_RATE_LIMIT, MAX_RATE_LIMIT, TO_MINUTES } from "./constants";
|
|
2
2
|
import { assertBoolean, assertPositiveInteger, assertRateLimitFrequency, assertString, assertStringArray, buildDefaultSettings, generateID, isValidISODate, sha256, validateDomain, validateIP, } from "./utils";
|
|
3
3
|
// ─────────────────────────────────────────────
|
|
4
|
+
// Constants
|
|
5
|
+
// ─────────────────────────────────────────────
|
|
6
|
+
const VALID_QUOTA_FREQUENCIES = [
|
|
7
|
+
"hours",
|
|
8
|
+
"days",
|
|
9
|
+
"weeks",
|
|
10
|
+
"months",
|
|
11
|
+
"quarters",
|
|
12
|
+
"years",
|
|
13
|
+
];
|
|
14
|
+
// ─────────────────────────────────────────────
|
|
4
15
|
// MajikAPI Class
|
|
5
16
|
// ─────────────────────────────────────────────
|
|
6
17
|
export class MajikAPI {
|
|
@@ -98,6 +109,7 @@ export class MajikAPI {
|
|
|
98
109
|
* Accepts the raw output of `toJSON()`, a Supabase row, or a Redis cache hit.
|
|
99
110
|
*
|
|
100
111
|
* `raw_api_key` is intentionally NOT restored — it is never in the JSON.
|
|
112
|
+
* `is_valid` is intentionally NOT restored — it is a computed getter.
|
|
101
113
|
*/
|
|
102
114
|
static fromJSON(data) {
|
|
103
115
|
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
@@ -134,6 +146,7 @@ export class MajikAPI {
|
|
|
134
146
|
* Serialise to a plain JSON-safe object matching MajikAPIJSON.
|
|
135
147
|
* Safe to store in Supabase or cache in Redis.
|
|
136
148
|
* raw_api_key is NEVER included.
|
|
149
|
+
* is_valid is computed at serialisation time from isActive().
|
|
137
150
|
*/
|
|
138
151
|
toJSON() {
|
|
139
152
|
return {
|
|
@@ -144,6 +157,7 @@ export class MajikAPI {
|
|
|
144
157
|
timestamp: this._timestamp.toISOString(),
|
|
145
158
|
restricted: this._restricted,
|
|
146
159
|
valid_until: this._valid_until ? this._valid_until.toISOString() : null,
|
|
160
|
+
is_valid: this.is_valid,
|
|
147
161
|
settings: structuredClone(this._settings),
|
|
148
162
|
};
|
|
149
163
|
}
|
|
@@ -213,10 +227,10 @@ export class MajikAPI {
|
|
|
213
227
|
* (500 req/min). Attempting to set a higher rate will throw unless
|
|
214
228
|
* bypassSafeLimit is explicitly passed as true.
|
|
215
229
|
*
|
|
216
|
-
* @param amount
|
|
217
|
-
* @param frequency
|
|
230
|
+
* @param amount - Number of allowed requests per frequency window.
|
|
231
|
+
* @param frequency - The time window unit.
|
|
218
232
|
* @param bypassSafeLimit - When true, skips the MAX_RATE_LIMIT ceiling check.
|
|
219
|
-
*
|
|
233
|
+
* Defaults to false. Use with caution.
|
|
220
234
|
*/
|
|
221
235
|
setRateLimit(amount, frequency, bypassSafeLimit = false) {
|
|
222
236
|
assertPositiveInteger(amount, "amount");
|
|
@@ -240,6 +254,70 @@ export class MajikAPI {
|
|
|
240
254
|
this._settings.rateLimit = { ...DEFAULT_RATE_LIMIT };
|
|
241
255
|
}
|
|
242
256
|
// ─────────────────────────────────────────────
|
|
257
|
+
// Quota Management
|
|
258
|
+
// ─────────────────────────────────────────────
|
|
259
|
+
/**
|
|
260
|
+
* Set a fixed lifetime quota for this key.
|
|
261
|
+
* Once total usage reaches `limit`, isQuotaExceeded() returns true.
|
|
262
|
+
*
|
|
263
|
+
* @param limit - Maximum total number of requests allowed. Must be a
|
|
264
|
+
* positive integer.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* key.setFixedQuota(10_000); // 10 000 requests total, ever
|
|
268
|
+
*/
|
|
269
|
+
setFixedQuota(limit) {
|
|
270
|
+
assertPositiveInteger(limit, "limit");
|
|
271
|
+
this._settings.quota = { type: "fixed", limit };
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Set a periodic rolling quota for this key.
|
|
275
|
+
* Usage is expected to be tracked externally (e.g. in Redis or Supabase)
|
|
276
|
+
* and passed into isQuotaExceeded() for comparison.
|
|
277
|
+
*
|
|
278
|
+
* @param limit - Maximum number of requests allowed per `frequency` window.
|
|
279
|
+
* @param frequency - The time window unit.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* key.setPeriodicQuota(50_000, "months"); // 50k requests per month
|
|
283
|
+
* key.setPeriodicQuota(1_000, "days"); // 1k requests per day
|
|
284
|
+
*/
|
|
285
|
+
setPeriodicQuota(limit, frequency) {
|
|
286
|
+
assertPositiveInteger(limit, "limit");
|
|
287
|
+
MajikAPI.assertQuotaFrequency(frequency, "frequency");
|
|
288
|
+
this._settings.quota = { type: "periodic", limit, frequency };
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Remove any quota restriction from this key.
|
|
292
|
+
* After calling this, isQuotaExceeded() will always return false.
|
|
293
|
+
*/
|
|
294
|
+
clearQuota() {
|
|
295
|
+
this._settings.quota = null;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check whether the given usage count has met or exceeded this key's quota.
|
|
299
|
+
*
|
|
300
|
+
* This method does NOT track usage itself — `currentUsage` must be supplied
|
|
301
|
+
* by the caller from whatever store you use (Redis counter, Supabase
|
|
302
|
+
* aggregate, etc.).
|
|
303
|
+
*
|
|
304
|
+
* For a `fixed` quota, pass the key's all-time request count.
|
|
305
|
+
* For a `periodic` quota, pass the request count for the current window.
|
|
306
|
+
*
|
|
307
|
+
* Returns:
|
|
308
|
+
* - `false` if quota is null (unlimited).
|
|
309
|
+
* - `true` if currentUsage >= the configured limit.
|
|
310
|
+
* - `false` if currentUsage < the configured limit.
|
|
311
|
+
*
|
|
312
|
+
* @param currentUsage - The usage count to check against the quota.
|
|
313
|
+
*/
|
|
314
|
+
isQuotaExceeded(currentUsage) {
|
|
315
|
+
if (this._settings.quota === null)
|
|
316
|
+
return false;
|
|
317
|
+
assertPositiveInteger(currentUsage, "currentUsage");
|
|
318
|
+
return currentUsage >= this._settings.quota.limit;
|
|
319
|
+
}
|
|
320
|
+
// ─────────────────────────────────────────────
|
|
243
321
|
// Key Rotation
|
|
244
322
|
// ─────────────────────────────────────────────
|
|
245
323
|
/**
|
|
@@ -449,6 +527,16 @@ export class MajikAPI {
|
|
|
449
527
|
get validUntil() {
|
|
450
528
|
return this._valid_until ? new Date(this._valid_until) : null;
|
|
451
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* Whether this key is valid for use right now.
|
|
532
|
+
* True when the key is active (not expired, not restricted).
|
|
533
|
+
*
|
|
534
|
+
* Note: this does NOT factor in quota — quota is a runtime check that
|
|
535
|
+
* requires external usage data. Use isQuotaExceeded(currentUsage) for that.
|
|
536
|
+
*/
|
|
537
|
+
get is_valid() {
|
|
538
|
+
return this.isActive();
|
|
539
|
+
}
|
|
452
540
|
/** Returns a deep clone — mutations to the returned object have no effect. */
|
|
453
541
|
get settings() {
|
|
454
542
|
return structuredClone(this._settings);
|
|
@@ -456,6 +544,31 @@ export class MajikAPI {
|
|
|
456
544
|
get rateLimit() {
|
|
457
545
|
return { ...this._settings.rateLimit };
|
|
458
546
|
}
|
|
547
|
+
/**
|
|
548
|
+
* The current quota configuration.
|
|
549
|
+
* null means unlimited.
|
|
550
|
+
* Use isQuotaExceeded(currentUsage) to compare against live usage.
|
|
551
|
+
*/
|
|
552
|
+
get quota() {
|
|
553
|
+
return this._settings.quota ? structuredClone(this._settings.quota) : null;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* The configured quota limit, or null if no quota is set.
|
|
557
|
+
* Convenience shorthand for `key.quota?.limit ?? null`.
|
|
558
|
+
*/
|
|
559
|
+
get quotaLimit() {
|
|
560
|
+
return this._settings.quota?.limit ?? null;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* The quota frequency if this is a periodic quota, otherwise null.
|
|
564
|
+
* Useful for determining the reset window without inspecting the full quota object.
|
|
565
|
+
*/
|
|
566
|
+
get quotaFrequency() {
|
|
567
|
+
if (this._settings.quota?.type === "periodic") {
|
|
568
|
+
return this._settings.quota.frequency;
|
|
569
|
+
}
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
459
572
|
get ipWhitelist() {
|
|
460
573
|
return structuredClone(this._settings.ipWhitelist);
|
|
461
574
|
}
|
|
@@ -510,12 +623,33 @@ export class MajikAPI {
|
|
|
510
623
|
}
|
|
511
624
|
throw new TypeError(`[MajikAPI] "${label}" must be a Date instance or an ISO date string.`);
|
|
512
625
|
}
|
|
626
|
+
static assertQuotaFrequency(value, label) {
|
|
627
|
+
if (!VALID_QUOTA_FREQUENCIES.includes(value)) {
|
|
628
|
+
throw new TypeError(`[MajikAPI] "${label}" must be one of: ${VALID_QUOTA_FREQUENCIES.join(", ")}. Got: "${value}"`);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
513
631
|
static validateSettings(settings) {
|
|
514
632
|
if (typeof settings !== "object" || settings === null) {
|
|
515
633
|
throw new TypeError("[MajikAPI] 'settings' must be an object.");
|
|
516
634
|
}
|
|
517
635
|
assertPositiveInteger(settings.rateLimit?.amount, "settings.rateLimit.amount");
|
|
518
636
|
assertRateLimitFrequency(settings.rateLimit?.frequency, "settings.rateLimit.frequency");
|
|
637
|
+
// Validate quota if present
|
|
638
|
+
if (settings.quota !== null && settings.quota !== undefined) {
|
|
639
|
+
if (typeof settings.quota !== "object") {
|
|
640
|
+
throw new TypeError("[MajikAPI] 'settings.quota' must be an object or null.");
|
|
641
|
+
}
|
|
642
|
+
assertPositiveInteger(settings.quota.limit, "settings.quota.limit");
|
|
643
|
+
if (settings.quota.type === "fixed") {
|
|
644
|
+
// no extra fields to validate
|
|
645
|
+
}
|
|
646
|
+
else if (settings.quota.type === "periodic") {
|
|
647
|
+
MajikAPI.assertQuotaFrequency(settings.quota.frequency, "settings.quota.frequency");
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
throw new TypeError(`[MajikAPI] 'settings.quota.type' must be "fixed" or "periodic". Got: "${settings.quota.type}"`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
519
653
|
assertBoolean(settings.ipWhitelist?.enabled, "settings.ipWhitelist.enabled");
|
|
520
654
|
assertStringArray(settings.ipWhitelist?.addresses, "settings.ipWhitelist.addresses");
|
|
521
655
|
settings.ipWhitelist.addresses.forEach((ip) => validateIP(ip));
|
|
@@ -527,7 +661,7 @@ export class MajikAPI {
|
|
|
527
661
|
// Debug
|
|
528
662
|
// ─────────────────────────────────────────────
|
|
529
663
|
toString() {
|
|
530
|
-
return `[MajikAPI id="${this._id}" owner="${this._owner_id}" name="${this._name}" status="${this.status}"]`;
|
|
664
|
+
return `[MajikAPI id="${this._id}" owner="${this._owner_id}" name="${this._name}" status="${this.status}" is_valid=${this.is_valid}]`;
|
|
531
665
|
}
|
|
532
666
|
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
533
667
|
return this.toString();
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
export type RateLimitFrequency = "seconds" | "minutes" | "hours";
|
|
2
|
+
export type QuotaFrequency = "hours" | "days" | "weeks" | "months" | "quarters" | "years";
|
|
2
3
|
export interface RateLimit {
|
|
3
4
|
amount: number;
|
|
4
5
|
frequency: RateLimitFrequency;
|
|
5
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Quota controls how many total requests (or requests within a rolling window)
|
|
9
|
+
* are permitted for this key.
|
|
10
|
+
*
|
|
11
|
+
* - `fixed` — A lifetime cap. Once `limit` total requests have been made,
|
|
12
|
+
* the key is considered at quota. No time window applies.
|
|
13
|
+
*
|
|
14
|
+
* - `periodic` — A rolling/periodic cap. Resets every `frequency` window
|
|
15
|
+
* (e.g. 1 000 requests per day, 50 000 per month).
|
|
16
|
+
*
|
|
17
|
+
* - `null` — No quota. Unlimited usage (subject only to rate limiting).
|
|
18
|
+
*/
|
|
19
|
+
export type Quota = {
|
|
20
|
+
type: "fixed";
|
|
21
|
+
limit: number;
|
|
22
|
+
} | {
|
|
23
|
+
type: "periodic";
|
|
24
|
+
limit: number;
|
|
25
|
+
frequency: QuotaFrequency;
|
|
26
|
+
} | null;
|
|
6
27
|
export interface IPWhitelist {
|
|
7
28
|
enabled: boolean;
|
|
8
29
|
addresses: string[];
|
|
@@ -13,6 +34,7 @@ export interface DomainWhitelist {
|
|
|
13
34
|
}
|
|
14
35
|
export interface MajikAPISettings {
|
|
15
36
|
rateLimit: RateLimit;
|
|
37
|
+
quota: Quota;
|
|
16
38
|
ipWhitelist: IPWhitelist;
|
|
17
39
|
domainWhitelist: DomainWhitelist;
|
|
18
40
|
allowedMethods?: string[];
|
|
@@ -27,6 +49,9 @@ export interface MajikAPISettings {
|
|
|
27
49
|
* api_key — SHA-256 hash of the raw plaintext key. Has a UNIQUE INDEX in
|
|
28
50
|
* Postgres (not the PK). Used as the Redis cache key prefix.
|
|
29
51
|
* The raw key is never stored anywhere.
|
|
52
|
+
* is_valid — Computed convenience flag. True when the key is active (not
|
|
53
|
+
* expired, not restricted). Does NOT account for quota — use
|
|
54
|
+
* isQuotaExceeded() for runtime quota checks.
|
|
30
55
|
*/
|
|
31
56
|
export interface MajikAPIJSON {
|
|
32
57
|
id: string;
|
|
@@ -36,6 +61,7 @@ export interface MajikAPIJSON {
|
|
|
36
61
|
timestamp: string;
|
|
37
62
|
restricted: boolean;
|
|
38
63
|
valid_until: string | null;
|
|
64
|
+
is_valid: boolean;
|
|
39
65
|
settings: MajikAPISettings;
|
|
40
66
|
}
|
|
41
67
|
export interface MajikAPICreateOptions {
|
package/dist/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-api",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "A high-security API key management library for TypeScript. Handles generation, SHA-256 hashing, and lifecycle management including rate limiting, IP/domain whitelisting, and secure key rotation.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.2",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|