@lowerdeck/api-key 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+
2
+ $ microbundle
3
+ No name was provided for external module '@lowerdeck/id' in output.globals – guessing 'id'
4
+ Build "@lowerdeck/api-key" to dist:
5
+ 977 B: index.cjs.gz
6
+ 878 B: index.cjs.br
7
+ 921 B: index.module.js.gz
8
+ 825 B: index.module.js.br
9
+ 983 B: index.module.js.gz
10
+ 888 B: index.module.js.br
11
+ 1054 B: index.umd.js.gz
12
+ 946 B: index.umd.js.br
@@ -0,0 +1,35 @@
1
+
2
+ $ vitest run --passWithNoTests
3
+ [?25l
4
+  RUN  v3.2.4 /Users/tobias/code/metorial/metorial-enterprise/oss/src/packages/shared/anonymize-ip
5
+
6
+ [?2026h
7
+  ❯ src/anonymizeIp.test.ts [queued]
8
+
9
+  Test Files 0 passed (1)
10
+  Tests 0 passed (0)
11
+  Start at 10:23:25
12
+  Duration 101ms
13
+ [?2026l ✓ src/anonymizeIp.test.ts (15 tests) 4ms
14
+ ✓ anonymizeIP > anonymizes IPv4 with default options 1ms
15
+ ✓ anonymizeIP > anonymizes IPv4 with keepGroups=1 0ms
16
+ ✓ anonymizeIP > anonymizes IPv4 with keepGroups=3 0ms
17
+ ✓ anonymizeIP > anonymizes IPv4 with custom maskChar 0ms
18
+ ✓ anonymizeIP > throws error for invalid IPv4 keepGroups 1ms
19
+ ✓ anonymizeIP > anonymizes IPv6 with default options 0ms
20
+ ✓ anonymizeIP > anonymizes IPv6 with keepGroups=2 0ms
21
+ ✓ anonymizeIP > anonymizes IPv6 with keepGroups=7 0ms
22
+ ✓ anonymizeIP > anonymizes IPv6 with custom maskChar 0ms
23
+ ✓ anonymizeIP > throws error for invalid IPv6 keepGroups 0ms
24
+ ✓ anonymizeIP > anonymizes IPv6 compressed notation 0ms
25
+ ✓ anonymizeIP > anonymizes IPv6 :: 0ms
26
+ ✓ anonymizeIP > anonymizes IPv6 with embedded IPv4 0ms
27
+ ✓ anonymizeIP > throws error for invalid IP address 0ms
28
+ ✓ anonymizeIP > trims whitespace from IP 0ms
29
+
30
+  Test Files  1 passed (1)
31
+  Tests  15 passed (15)
32
+  Start at  10:23:25
33
+  Duration  230ms (transform 36ms, setup 0ms, collect 35ms, tests 4ms, environment 0ms, prepare 39ms)
34
+
35
+ [?25h
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # `@lowerdeck/api-key`
2
+
3
+ Create and parse structured API keys with embedded configuration. Supports versioning, type prefixes, and automatic validation for secure key management.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @lowerdeck/api-key
9
+ yarn add @lowerdeck/api-key
10
+ bun add @lowerdeck/api-key
11
+ pnpm add @lowerdeck/api-key
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```typescript
17
+ import { createApiKeyGenerator } from '@lowerdeck/api-key';
18
+
19
+ // Define your key types
20
+ const keyTypes = {
21
+ uk: 'user_auth_token',
22
+ ak: 'app_access_token',
23
+ sk: 'secret_key'
24
+ } as const;
25
+
26
+ // Create a key generator
27
+ const ApiKey = createApiKeyGenerator(keyTypes, {
28
+ prefix: 'myapp',
29
+ secretLength: 60
30
+ });
31
+
32
+ // Create a new API key
33
+ const key = ApiKey.create({
34
+ type: 'user_auth_token',
35
+ config: {
36
+ url: 'https://api.example.com'
37
+ }
38
+ });
39
+
40
+ console.log(key.toString()); // myapp_uk_<60-char-secret><encoded-config>v1
41
+
42
+ // Parse an existing key
43
+ const parsed = ApiKey.from('myapp_uk_...');
44
+ if (parsed) {
45
+ console.log(parsed.type); // 'user_auth_token'
46
+ console.log(parsed.config.url); // 'https://api.example.com'
47
+ }
48
+
49
+ // Redact keys for logging
50
+ const redacted = ApiKey.redact(key);
51
+ console.log(redacted); // myapp_uk_abcd...xyz9
52
+ ```
53
+
54
+ ## License
55
+
56
+ This project is licensed under the Apache License 2.0.
57
+
58
+ <div align="center">
59
+ <sub>Built with ❤️ by <a href="https://metorial.com">Metorial</a></sub>
60
+ </div>
@@ -0,0 +1,10 @@
1
+ interface AnonymizationOptions {
2
+ maskChar?: string;
3
+ keepGroups?: {
4
+ ipv4?: number;
5
+ ipv6?: number;
6
+ } | number;
7
+ }
8
+ export declare let anonymizeIP: (ip: string, options?: AnonymizationOptions) => string;
9
+ export {};
10
+ //# sourceMappingURL=anonymizeIp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymizeIp.d.ts","sourceRoot":"","sources":["../src/anonymizeIp.ts"],"names":[],"mappings":"AAQA,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EACP;QACE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACD,MAAM,CAAC;CACZ;AAuHD,eAAO,IAAI,WAAW,GAAI,IAAI,MAAM,EAAE,UAAS,oBAAyB,WAwBvE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=anonymizeIp.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymizeIp.test.d.ts","sourceRoot":"","sources":["../src/anonymizeIp.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export declare let encodeBase62: (buffer: Buffer | string) => string;
2
+ export declare let decodeBase62: (encoded: string) => string;
3
+ //# sourceMappingURL=base62.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base62.d.ts","sourceRoot":"","sources":["../src/base62.ts"],"names":[],"mappings":"AAEA,eAAO,IAAI,YAAY,GAAI,QAAQ,MAAM,GAAG,MAAM,WAgBjD,CAAC;AAEF,eAAO,IAAI,YAAY,GAAI,SAAS,MAAM,WAazC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=base62.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base62.test.d.ts","sourceRoot":"","sources":["../src/base62.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ import { ValidationType } from '@lowerdeck/validation';
2
+ import * as Cookie from 'cookie';
3
+ export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
+ export interface ServiceRequest {
5
+ query: URLSearchParams;
6
+ headers: Headers;
7
+ url: string;
8
+ ip?: string;
9
+ body: any;
10
+ rawBody: any;
11
+ requestId: string;
12
+ getCookies: () => Record<string, string | undefined>;
13
+ getCookie: (name: string) => string | undefined;
14
+ setCookie: (name: string, value: string, opts?: Cookie.SerializeOptions) => void;
15
+ sharedMiddlewareMemo: Map<string, Promise<any>>;
16
+ beforeSend: (handler: () => Promise<any>) => void;
17
+ appendHeaders: (headers: Record<string, string | string[]>) => void;
18
+ }
19
+ export type Simplify<T> = {
20
+ [KeyType in keyof T]: T[KeyType];
21
+ } & {};
22
+ export type ExtendContext<C extends object, E> = E extends object ? Simplify<C & E> : C;
23
+ export declare class Group<Context extends {
24
+ [key: string]: any;
25
+ } = {}> {
26
+ private _middleware;
27
+ constructor(_middleware?: Array<(ctx: Context & ServiceRequest) => Promise<any>>);
28
+ use<T extends {
29
+ [key: string]: any;
30
+ } | undefined | void>(handler: (ctx: Context & ServiceRequest) => Promise<T>, opts?: {
31
+ getSharedMemoKey?: (ctx: Context & ServiceRequest) => string;
32
+ }): Group<Context & T extends infer T_1 ? { [KeyType in keyof T_1]: T_1[KeyType]; } : never>;
33
+ createMiddleware<T extends {
34
+ [key: string]: any;
35
+ }, P = void>(handler: (ctx: Context & ServiceRequest, input: P) => Promise<T>, opts?: {
36
+ getSharedMemoKey?: (ctx: Context & ServiceRequest, input: P) => string;
37
+ }): (input: P) => (ctx: Context & ServiceRequest) => Promise<T>;
38
+ handler(): Handler<unknown, unknown, Context>;
39
+ controller<HandlersAndSubControllers extends {
40
+ [key: string]: Handler<any, any, any> | Controller<any>;
41
+ }>(handlers: HandlersAndSubControllers): Controller<HandlersAndSubControllers>;
42
+ }
43
+ export type Controller<HandlersAndSubControllers extends {
44
+ [key: string]: Handler<any, any, any> | Controller<any>;
45
+ }> = HandlersAndSubControllers;
46
+ export type InferControllerType<T> = T extends Controller<infer U> ? U : never;
47
+ export type InferClient<HandlersAndSubControllers extends {
48
+ [key: string]: Handler<any, any, any> | Controller<any>;
49
+ }> = {
50
+ [K in keyof HandlersAndSubControllers]: HandlersAndSubControllers[K] extends Handler<infer I, infer O, infer C> ? ((input: I, opts?: {
51
+ headers?: Record<string, string>;
52
+ query?: Record<string, string>;
53
+ }) => Promise<O>) & {
54
+ getFull: (input: I, opts?: {
55
+ headers?: Record<string, string>;
56
+ query?: Record<string, string>;
57
+ }) => Promise<{
58
+ data: O;
59
+ status: number;
60
+ headers: Record<string, string>;
61
+ }>;
62
+ } : HandlersAndSubControllers[K] extends Controller<infer U> ? InferClient<U> : never;
63
+ };
64
+ export declare class Handler<Input, Output, Context extends {
65
+ [key: string]: any;
66
+ } = {}> {
67
+ private _middleware;
68
+ private _handler;
69
+ private _validation;
70
+ constructor(_middleware?: Array<(ctx: Context & ServiceRequest) => Promise<any>>);
71
+ do<HandlerOutput>(handler: (ctx: Context & Omit<ServiceRequest, 'body'> & {
72
+ input: Input;
73
+ }) => Promise<HandlerOutput>): Handler<Input, HandlerOutput, Context>;
74
+ use<T extends {
75
+ [key: string]: any;
76
+ } = {}>(handler: (ctx: Context & ServiceRequest) => Promise<T | undefined | void>): Handler<Input, Output, ExtendContext<Context, T>>;
77
+ input<HandlerInput>(validation: ValidationType<HandlerInput>): Handler<HandlerInput, Output, Context>;
78
+ run(req: ServiceRequest, initialContext: any): Promise<{
79
+ response: Output;
80
+ }>;
81
+ }
82
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=controller.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../src/controller.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare let parseForwardedFor: (xForwardedForHeader?: string | null | undefined) => string | undefined;
2
+ //# sourceMappingURL=extractIp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractIp.d.ts","sourceRoot":"","sources":["../src/extractIp.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,iBAAiB,GAAI,sBAAsB,MAAM,GAAG,IAAI,GAAG,SAAS,uBAQ9E,CAAC"}
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ var r=require("@lowerdeck/id"),e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";exports.createApiKeyGenerator=function(t,n){var i=n.prefix,o=n.secretLength||60,c=Object.fromEntries(Object.entries(t).map(function(r){return[r[1],r[0]]}));/*#__PURE__*/return function(){function n(r,e,t,n){this.type=void 0,this._secret=void 0,this.config=void 0,this.version=void 0,this.type=r,this._secret=e,this.config=t,this.version=n}return n.from=function(r){var c=function(r){var n=r.split("_");if(n[0]!=i)return null;var c=t[n[1]];if(!c)return null;var u=n.slice(2).join("_"),f=u.slice(-2);if("v1"!=f)return null;var s=u.slice(0,o);if(s.length!=o)return null;var l=u.slice(o,-2),a=void 0;try{var v=JSON.parse(function(r){for(var t=0n,n=BigInt(62),i=0;i<r.length;i++){var o=e.indexOf(r[i]);if(-1===o)throw new Error("Invalid character");t=t*n+BigInt(o)}var c=t.toString(16);return c.length%2&&(c="0"+c),Buffer.from(c,"hex").toString()}(l));if(!Array.isArray(v)||1!=v.length||"string"!=typeof v[0])return null;a={url:v[0]}}catch(r){return null}return{type:c,secret:s,config:a,version:f}}(r);return c?new n(c.type,c.secret,c.config,c.version):null},n.create=function(e){if(e.secret&&e.secret.length!=o)throw new Error("Secret key must be "+o+" characters long");var t=e.secret?e.secret:r.generatePlainId(o);return new n(e.type,t,e.config,"v1")},n.redact=function(r){var e=r.toString().split("_");if(e[0]!=i)return r.toString();var t=e[0],n=e[1],o=function(r,e){(null==e||e>r.length)&&(e=r.length);for(var t=0,n=Array(e);t<e;t++)n[t]=r[t];return n}(e).slice(2).join("_");return t+"_"+n+"_"+o.slice(0,4)+"..."+o.slice(-4)},n.prototype.toString=function(){var r=function(r){r=Buffer.isBuffer(r)?r:Buffer.from(r);var t=BigInt("0x"+(r.toString("hex")||"0"));if(0n===t)return"0";for(var n="",i=BigInt(62);t>0n;)n=e[Number(t%i)]+n,t/=i;return n}(JSON.stringify([this.config.url]));return i+"_"+c[this.type]+"_"+this._secret+r+"v1"},n}()};
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/base62.ts","../src/keys.ts"],"sourcesContent":["const BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n\nexport let encodeBase62 = (buffer: Buffer | string) => {\n buffer = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);\n\n let bigint = BigInt('0x' + (buffer.toString('hex') || '0'));\n if (bigint === 0n) return '0';\n\n let result = '';\n let base = BigInt(62);\n\n while (bigint > 0n) {\n let remainder = bigint % base;\n result = BASE62_ALPHABET[Number(remainder)] + result;\n bigint = bigint / base;\n }\n\n return result;\n};\n\nexport let decodeBase62 = (encoded: string) => {\n let bigint = 0n;\n let base = BigInt(62);\n\n for (let i = 0; i < encoded.length; i++) {\n let index = BASE62_ALPHABET.indexOf(encoded[i]);\n if (index === -1) throw new Error('Invalid character');\n bigint = bigint * base + BigInt(index);\n }\n\n let hex = bigint.toString(16);\n if (hex.length % 2) hex = '0' + hex;\n return Buffer.from(hex, 'hex').toString();\n};\n","import { generatePlainId } from '@lowerdeck/id';\nimport { decodeBase62, encodeBase62 } from './base62';\n\nexport type ApiKeyVersions = 'v1';\n\n// export type ApiKeyType =\n// | 'user_auth_token'\n// | 'organization_management_token'\n// | 'organization_app_access_token'\n// | 'instance_access_token_secret'\n// | 'instance_access_token_publishable'\n// | 'ephemeral_client_secret'\n// | 'magic_mcp_token_secret';\n\n// let keyTypes = {\n// uk: 'user_auth_token',\n// lk: 'organization_management_token',\n// ak: 'organization_app_access_token',\n// sk: 'instance_access_token_secret',\n// pk: 'instance_access_token_publishable',\n// ek: 'ephemeral_client_secret',\n// mk: 'magic_mcp_token_secret'\n// } as const;\n\ntype ApiKeyConfig = {\n url: string;\n};\n\nexport let createApiKeyGenerator = <\n Types extends Record<string, string>,\n Prefix extends string\n>(\n keyTypes: Types,\n opts: {\n prefix: Prefix;\n secretLength?: number;\n }\n) => {\n const METORIAL_PREFIX = opts.prefix;\n const SECRET_KEY_LENGTH = opts.secretLength || 60;\n\n type ApiKeyType = Types[keyof Types];\n\n let keyTypesReverse = Object.fromEntries(\n Object.entries(keyTypes).map(([key, value]) => [value, key])\n ) as Record<ApiKeyType, keyof typeof keyTypes>;\n\n // type ApiKeyPrefix = `${Prefix}_${keyof typeof keyTypes & string}_`;\n // type ApiKey = `${ApiKeyPrefix}${string}`;\n\n let parseApiKey = (key: string) => {\n let parts = key.split('_');\n if (parts[0] != METORIAL_PREFIX) return null;\n\n let type = keyTypes[parts[1] as keyof typeof keyTypes];\n if (!type) return null;\n\n let rest = parts.slice(2).join('_');\n\n let version = rest.slice(-2);\n if (version != 'v1') return null;\n\n let secret = rest.slice(0, SECRET_KEY_LENGTH);\n if (secret.length != SECRET_KEY_LENGTH) return null;\n\n let configStr = rest.slice(SECRET_KEY_LENGTH, -2);\n let config: ApiKeyConfig | undefined = undefined;\n\n try {\n let configDecoded = JSON.parse(decodeBase62(configStr));\n if (\n !Array.isArray(configDecoded) ||\n configDecoded.length != 1 ||\n typeof configDecoded[0] != 'string'\n ) {\n return null;\n }\n\n config = {\n url: configDecoded[0]\n };\n } catch (e) {\n return null;\n }\n\n return {\n type,\n secret,\n config,\n version: version as ApiKeyVersions\n };\n };\n\n return class UnifiedApiKey {\n private constructor(\n public readonly type: ApiKeyType,\n public readonly _secret: string,\n public readonly config: ApiKeyConfig,\n public readonly version: ApiKeyVersions\n ) {}\n\n static from(key: string) {\n let parsed = parseApiKey(key);\n if (!parsed) return null;\n\n return new UnifiedApiKey(parsed.type, parsed.secret, parsed.config, parsed.version);\n }\n\n static create(d: { type: ApiKeyType; config: ApiKeyConfig; secret?: string }) {\n if (d.secret && d.secret.length != SECRET_KEY_LENGTH) {\n throw new Error(`Secret key must be ${SECRET_KEY_LENGTH} characters long`);\n }\n\n let secret = d.secret ? d.secret : generatePlainId(SECRET_KEY_LENGTH);\n\n return new UnifiedApiKey(d.type, secret, d.config, 'v1');\n }\n\n static redact(key: string | UnifiedApiKey) {\n let parts = key.toString().split('_');\n if (parts[0] != METORIAL_PREFIX) return key.toString();\n\n let [metorial, type, ...rest] = parts;\n let secret = rest.join('_');\n\n return `${metorial}_${type}_${secret.slice(0, 4)}...${secret.slice(-4)}`;\n }\n\n toString() {\n let config = encodeBase62(JSON.stringify([this.config.url]));\n\n return `${METORIAL_PREFIX}_${keyTypesReverse[this.type] as string}_${this._secret}${config}v1`;\n }\n };\n};\n"],"names":["BASE62_ALPHABET","keyTypes","opts","METORIAL_PREFIX","prefix","SECRET_KEY_LENGTH","secretLength","keyTypesReverse","Object","fromEntries","entries","map","_ref","value","UnifiedApiKey","type","_secret","config","version","this","from","key","parsed","parts","split","rest","slice","join","secret","length","configStr","undefined","configDecoded","JSON","parse","encoded","bigint","base","BigInt","i","index","indexOf","Error","hex","toString","Buffer","decodeBase62","Array","isArray","url","e","parseApiKey","create","d","generatePlainId","redact","metorial","_arrayLikeToArray","prototype","buffer","isBuffer","result","Number","encodeBase62","stringify"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './keys';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ let e=e=>!!/^(\d{1,3}\.){3}\d{1,3}$/.test(e)&&e.split(".").every(e=>{let r=parseInt(e,10);return r>=0&&r<=255}),r=e=>{if(e.includes("::")){let r=e.split("::");if(2!==r.length)return!1;if((r[0]?r[0].split(":").length:0)+(r[1]?r[1].split(":").length:0)>7)return!1}return/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/.test(e)||"::"===e},t=(e,r={})=>{let{keepGroups:t=2,maskChar:s="x"}=r,n=e.split(".");if(t<1||t>3)throw new Error("keepGroups for IPv4 must be between 1 and 3");return n.map((e,r)=>r<t?e:s.repeat(e.length)).join(".")},s=(e,r,t)=>{let s=e;if(e.includes("::")){let r=e.split("::"),t=r[0]||"",n=r[1]||"",p=t?t.split(":"):[],l=n?n.split(":"):[],i=Array(8-p.length-l.length).fill("0");s=[...p,...i,...l].join(":")}return s.split(":").map((e,s)=>s<r?e:t.repeat(Math.max(1,e.length))).join(":")},n=(n,p={})=>{if(!n||"string"!=typeof n)throw new Error("IP address must be a non-empty string");let l=n.trim();var i,u;if(e(l))return t(l,{keepGroups:"number"==typeof p.keepGroups?p.keepGroups:null==(i=p.keepGroups)?void 0:i.ipv4,maskChar:p.maskChar}).replace("000","0");if((t=>{if(t.includes(".")){let s=t.split(":");if(e(s[s.length-1])){let e=t.substring(0,t.lastIndexOf(":")+1)+"0";return r(e)}}return r(t)})(l))return((r,n={})=>{let{keepGroups:p=4,maskChar:l="x"}=n;if(p<1||p>7)throw new Error("keepGroups for IPv6 must be between 1 and 7");if(r.includes(".")){let n=r.lastIndexOf(":"),i=r.substring(0,n+1),u=r.substring(n+1);if(e(u)){let e=t(u,{keepGroups:2,maskChar:l}),r=s(i+"0",p,l);return r.substring(0,r.lastIndexOf(":")+1)+e}}return s(r,p,l)})(l,{keepGroups:"number"==typeof p.keepGroups?p.keepGroups:null==(u=p.keepGroups)?void 0:u.ipv6,maskChar:p.maskChar});throw new Error("Invalid IP address format")};export{n as anonymizeIP};
2
+ //# sourceMappingURL=index.modern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.modern.js","sources":["../src/anonymizeIp.ts"],"sourcesContent":["interface AnonymizationOptionsSingle {\n // For IPv4: number of octets to keep (1-3, default: 2)\n // For IPv6: number of groups to keep (1-7, default: 4)\n keepGroups?: number;\n // Character to use for masking (default: 'x')\n maskChar?: string;\n}\n\ninterface AnonymizationOptions {\n maskChar?: string;\n keepGroups?:\n | {\n ipv4?: number;\n ipv6?: number;\n }\n | number;\n}\n\nlet isIPv4 = (ip: string) => {\n let ipv4Regex = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\n if (!ipv4Regex.test(ip)) return false;\n\n return ip.split('.').every(octet => {\n let num = parseInt(octet, 10);\n return num >= 0 && num <= 255;\n });\n};\n\nlet isIPv6 = (ip: string) => {\n // Handle IPv6 with embedded IPv4 (e.g., ::ffff:192.0.2.1)\n if (ip.includes('.')) {\n let parts = ip.split(':');\n let lastPart = parts[parts.length - 1];\n if (isIPv4(lastPart)) {\n // Remove the IPv4 part and validate the IPv6 part\n let ipv6Part = ip.substring(0, ip.lastIndexOf(':') + 1) + '0';\n return isIPv6Simple(ipv6Part);\n }\n }\n\n return isIPv6Simple(ip);\n};\n\nlet isIPv6Simple = (ip: string) => {\n let ipv6Regex = /^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/;\n\n if (ip.includes('::')) {\n let parts = ip.split('::');\n if (parts.length !== 2) return false;\n\n let leftGroups = parts[0] ? parts[0].split(':').length : 0;\n let rightGroups = parts[1] ? parts[1].split(':').length : 0;\n\n // Total groups should not exceed 8\n if (leftGroups + rightGroups > 7) return false;\n }\n\n return ipv6Regex.test(ip) || ip === '::';\n};\n\nlet anonymizeIPv4 = (ip: string, options: AnonymizationOptionsSingle = {}) => {\n let { keepGroups = 2, maskChar = 'x' } = options;\n let octets = ip.split('.');\n\n if (keepGroups < 1 || keepGroups > 3) {\n throw new Error('keepGroups for IPv4 must be between 1 and 3');\n }\n\n let maskedOctets = octets.map((octet, index) => {\n if (index < keepGroups) {\n return octet;\n }\n return maskChar.repeat(octet.length);\n });\n\n return maskedOctets.join('.');\n};\n\nlet anonymizeIPv6 = (ip: string, options: AnonymizationOptionsSingle = {}) => {\n let { keepGroups = 4, maskChar = 'x' } = options;\n\n if (keepGroups < 1 || keepGroups > 7) {\n throw new Error('keepGroups for IPv6 must be between 1 and 7');\n }\n\n // Handle IPv6 with embedded IPv4\n if (ip.includes('.')) {\n let lastColonIndex = ip.lastIndexOf(':');\n let ipv6Part = ip.substring(0, lastColonIndex + 1);\n let ipv4Part = ip.substring(lastColonIndex + 1);\n\n if (isIPv4(ipv4Part)) {\n let anonymizedIPv4 = anonymizeIPv4(ipv4Part, { keepGroups: 2, maskChar });\n let anonymizedIPv6Part = anonymizeIPv6Simple(ipv6Part + '0', keepGroups, maskChar);\n return (\n anonymizedIPv6Part.substring(0, anonymizedIPv6Part.lastIndexOf(':') + 1) +\n anonymizedIPv4\n );\n }\n }\n\n return anonymizeIPv6Simple(ip, keepGroups, maskChar);\n};\n\nlet anonymizeIPv6Simple = (ip: string, keepGroups: number, maskChar: string) => {\n // Expand compressed notation for easier processing\n let expanded = ip;\n\n if (ip.includes('::')) {\n let parts = ip.split('::');\n let leftPart = parts[0] || '';\n let rightPart = parts[1] || '';\n\n let leftGroups = leftPart ? leftPart.split(':') : [];\n let rightGroups = rightPart ? rightPart.split(':') : [];\n\n let missingGroups = 8 - leftGroups.length - rightGroups.length;\n let zeroGroups = Array(missingGroups).fill('0');\n\n let allGroups = [...leftGroups, ...zeroGroups, ...rightGroups];\n expanded = allGroups.join(':');\n }\n\n let groups = expanded.split(':');\n\n let maskedGroups = groups.map((group, index) => {\n if (index < keepGroups) {\n return group;\n }\n return maskChar.repeat(Math.max(1, group.length));\n });\n\n return maskedGroups.join(':');\n};\n\nexport let anonymizeIP = (ip: string, options: AnonymizationOptions = {}) => {\n if (!ip || typeof ip !== 'string') {\n throw new Error('IP address must be a non-empty string');\n }\n\n let trimmedIP = ip.trim();\n\n if (isIPv4(trimmedIP)) {\n return anonymizeIPv4(trimmedIP, {\n keepGroups:\n typeof options.keepGroups === 'number' ? options.keepGroups : options.keepGroups?.ipv4,\n maskChar: options.maskChar\n }).replace('000', '0'); // Ensure no triple zeros in IPv4\n }\n\n if (isIPv6(trimmedIP)) {\n return anonymizeIPv6(trimmedIP, {\n keepGroups:\n typeof options.keepGroups === 'number' ? options.keepGroups : options.keepGroups?.ipv6,\n maskChar: options.maskChar\n });\n }\n\n throw new Error('Invalid IP address format');\n};\n"],"names":["isIPv4","ip","test","split","every","octet","num","parseInt","isIPv6Simple","includes","parts","length","anonymizeIPv4","options","keepGroups","maskChar","octets","Error","map","index","repeat","join","anonymizeIPv6Simple","expanded","leftPart","rightPart","leftGroups","rightGroups","zeroGroups","Array","fill","group","Math","max","anonymizeIP","trimmedIP","trim","_options$keepGroups","_options$keepGroups2","ipv4","replace","ipv6Part","substring","lastIndexOf","isIPv6","anonymizeIPv6","lastColonIndex","ipv4Part","anonymizedIPv4","anonymizedIPv6Part","ipv6"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{generatePlainId as r}from"@lowerdeck/id";var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",e=function(e,n){var i=n.prefix,o=n.secretLength||60,c=Object.fromEntries(Object.entries(e).map(function(r){return[r[1],r[0]]}));/*#__PURE__*/return function(){function n(r,t,e,n){this.type=void 0,this._secret=void 0,this.config=void 0,this.version=void 0,this.type=r,this._secret=t,this.config=e,this.version=n}return n.from=function(r){var c=function(r){var n=r.split("_");if(n[0]!=i)return null;var c=e[n[1]];if(!c)return null;var f=n.slice(2).join("_"),u=f.slice(-2);if("v1"!=u)return null;var s=f.slice(0,o);if(s.length!=o)return null;var l=f.slice(o,-2),a=void 0;try{var v=JSON.parse(function(r){for(var e=0n,n=BigInt(62),i=0;i<r.length;i++){var o=t.indexOf(r[i]);if(-1===o)throw new Error("Invalid character");e=e*n+BigInt(o)}var c=e.toString(16);return c.length%2&&(c="0"+c),Buffer.from(c,"hex").toString()}(l));if(!Array.isArray(v)||1!=v.length||"string"!=typeof v[0])return null;a={url:v[0]}}catch(r){return null}return{type:c,secret:s,config:a,version:u}}(r);return c?new n(c.type,c.secret,c.config,c.version):null},n.create=function(t){if(t.secret&&t.secret.length!=o)throw new Error("Secret key must be "+o+" characters long");var e=t.secret?t.secret:r(o);return new n(t.type,e,t.config,"v1")},n.redact=function(r){var t=r.toString().split("_");if(t[0]!=i)return r.toString();var e=t[0],n=t[1],o=function(r,t){(null==t||t>r.length)&&(t=r.length);for(var e=0,n=Array(t);e<t;e++)n[e]=r[e];return n}(t).slice(2).join("_");return e+"_"+n+"_"+o.slice(0,4)+"..."+o.slice(-4)},n.prototype.toString=function(){var r=function(r){r=Buffer.isBuffer(r)?r:Buffer.from(r);var e=BigInt("0x"+(r.toString("hex")||"0"));if(0n===e)return"0";for(var n="",i=BigInt(62);e>0n;)n=t[Number(e%i)]+n,e/=i;return n}(JSON.stringify([this.config.url]));return i+"_"+c[this.type]+"_"+this._secret+r+"v1"},n}()};export{e as createApiKeyGenerator};
2
+ //# sourceMappingURL=index.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.module.js","sources":["../src/base62.ts","../src/keys.ts"],"sourcesContent":["const BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n\nexport let encodeBase62 = (buffer: Buffer | string) => {\n buffer = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);\n\n let bigint = BigInt('0x' + (buffer.toString('hex') || '0'));\n if (bigint === 0n) return '0';\n\n let result = '';\n let base = BigInt(62);\n\n while (bigint > 0n) {\n let remainder = bigint % base;\n result = BASE62_ALPHABET[Number(remainder)] + result;\n bigint = bigint / base;\n }\n\n return result;\n};\n\nexport let decodeBase62 = (encoded: string) => {\n let bigint = 0n;\n let base = BigInt(62);\n\n for (let i = 0; i < encoded.length; i++) {\n let index = BASE62_ALPHABET.indexOf(encoded[i]);\n if (index === -1) throw new Error('Invalid character');\n bigint = bigint * base + BigInt(index);\n }\n\n let hex = bigint.toString(16);\n if (hex.length % 2) hex = '0' + hex;\n return Buffer.from(hex, 'hex').toString();\n};\n","import { generatePlainId } from '@lowerdeck/id';\nimport { decodeBase62, encodeBase62 } from './base62';\n\nexport type ApiKeyVersions = 'v1';\n\n// export type ApiKeyType =\n// | 'user_auth_token'\n// | 'organization_management_token'\n// | 'organization_app_access_token'\n// | 'instance_access_token_secret'\n// | 'instance_access_token_publishable'\n// | 'ephemeral_client_secret'\n// | 'magic_mcp_token_secret';\n\n// let keyTypes = {\n// uk: 'user_auth_token',\n// lk: 'organization_management_token',\n// ak: 'organization_app_access_token',\n// sk: 'instance_access_token_secret',\n// pk: 'instance_access_token_publishable',\n// ek: 'ephemeral_client_secret',\n// mk: 'magic_mcp_token_secret'\n// } as const;\n\ntype ApiKeyConfig = {\n url: string;\n};\n\nexport let createApiKeyGenerator = <\n Types extends Record<string, string>,\n Prefix extends string\n>(\n keyTypes: Types,\n opts: {\n prefix: Prefix;\n secretLength?: number;\n }\n) => {\n const METORIAL_PREFIX = opts.prefix;\n const SECRET_KEY_LENGTH = opts.secretLength || 60;\n\n type ApiKeyType = Types[keyof Types];\n\n let keyTypesReverse = Object.fromEntries(\n Object.entries(keyTypes).map(([key, value]) => [value, key])\n ) as Record<ApiKeyType, keyof typeof keyTypes>;\n\n // type ApiKeyPrefix = `${Prefix}_${keyof typeof keyTypes & string}_`;\n // type ApiKey = `${ApiKeyPrefix}${string}`;\n\n let parseApiKey = (key: string) => {\n let parts = key.split('_');\n if (parts[0] != METORIAL_PREFIX) return null;\n\n let type = keyTypes[parts[1] as keyof typeof keyTypes];\n if (!type) return null;\n\n let rest = parts.slice(2).join('_');\n\n let version = rest.slice(-2);\n if (version != 'v1') return null;\n\n let secret = rest.slice(0, SECRET_KEY_LENGTH);\n if (secret.length != SECRET_KEY_LENGTH) return null;\n\n let configStr = rest.slice(SECRET_KEY_LENGTH, -2);\n let config: ApiKeyConfig | undefined = undefined;\n\n try {\n let configDecoded = JSON.parse(decodeBase62(configStr));\n if (\n !Array.isArray(configDecoded) ||\n configDecoded.length != 1 ||\n typeof configDecoded[0] != 'string'\n ) {\n return null;\n }\n\n config = {\n url: configDecoded[0]\n };\n } catch (e) {\n return null;\n }\n\n return {\n type,\n secret,\n config,\n version: version as ApiKeyVersions\n };\n };\n\n return class UnifiedApiKey {\n private constructor(\n public readonly type: ApiKeyType,\n public readonly _secret: string,\n public readonly config: ApiKeyConfig,\n public readonly version: ApiKeyVersions\n ) {}\n\n static from(key: string) {\n let parsed = parseApiKey(key);\n if (!parsed) return null;\n\n return new UnifiedApiKey(parsed.type, parsed.secret, parsed.config, parsed.version);\n }\n\n static create(d: { type: ApiKeyType; config: ApiKeyConfig; secret?: string }) {\n if (d.secret && d.secret.length != SECRET_KEY_LENGTH) {\n throw new Error(`Secret key must be ${SECRET_KEY_LENGTH} characters long`);\n }\n\n let secret = d.secret ? d.secret : generatePlainId(SECRET_KEY_LENGTH);\n\n return new UnifiedApiKey(d.type, secret, d.config, 'v1');\n }\n\n static redact(key: string | UnifiedApiKey) {\n let parts = key.toString().split('_');\n if (parts[0] != METORIAL_PREFIX) return key.toString();\n\n let [metorial, type, ...rest] = parts;\n let secret = rest.join('_');\n\n return `${metorial}_${type}_${secret.slice(0, 4)}...${secret.slice(-4)}`;\n }\n\n toString() {\n let config = encodeBase62(JSON.stringify([this.config.url]));\n\n return `${METORIAL_PREFIX}_${keyTypesReverse[this.type] as string}_${this._secret}${config}v1`;\n }\n };\n};\n"],"names":["BASE62_ALPHABET","createApiKeyGenerator","keyTypes","opts","METORIAL_PREFIX","prefix","SECRET_KEY_LENGTH","secretLength","keyTypesReverse","Object","fromEntries","entries","map","_ref","value","UnifiedApiKey","type","_secret","config","version","this","from","key","parsed","parts","split","rest","slice","join","secret","length","configStr","undefined","configDecoded","JSON","parse","encoded","bigint","base","BigInt","i","index","indexOf","Error","hex","toString","Buffer","decodeBase62","Array","isArray","url","e","parseApiKey","create","d","generatePlainId","redact","metorial","_arrayLikeToArray","prototype","buffer","isBuffer","result","Number","encodeBase62","stringify"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ !function(r,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@lowerdeck/id")):"function"==typeof define&&define.amd?define(["exports","@lowerdeck/id"],e):e((r||self).apiKey={},r.id)}(this,function(r,e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";r.createApiKeyGenerator=function(r,n){var i=n.prefix,o=n.secretLength||60,f=Object.fromEntries(Object.entries(r).map(function(r){return[r[1],r[0]]}));/*#__PURE__*/return function(){function n(r,e,t,n){this.type=void 0,this._secret=void 0,this.config=void 0,this.version=void 0,this.type=r,this._secret=e,this.config=t,this.version=n}return n.from=function(e){var f=function(e){var n=e.split("_");if(n[0]!=i)return null;var f=r[n[1]];if(!f)return null;var u=n.slice(2).join("_"),c=u.slice(-2);if("v1"!=c)return null;var s=u.slice(0,o);if(s.length!=o)return null;var l=u.slice(o,-2),a=void 0;try{var v=JSON.parse(function(r){for(var e=0n,n=BigInt(62),i=0;i<r.length;i++){var o=t.indexOf(r[i]);if(-1===o)throw new Error("Invalid character");e=e*n+BigInt(o)}var f=e.toString(16);return f.length%2&&(f="0"+f),Buffer.from(f,"hex").toString()}(l));if(!Array.isArray(v)||1!=v.length||"string"!=typeof v[0])return null;a={url:v[0]}}catch(r){return null}return{type:f,secret:s,config:a,version:c}}(e);return f?new n(f.type,f.secret,f.config,f.version):null},n.create=function(r){if(r.secret&&r.secret.length!=o)throw new Error("Secret key must be "+o+" characters long");var t=r.secret?r.secret:e.generatePlainId(o);return new n(r.type,t,r.config,"v1")},n.redact=function(r){var e=r.toString().split("_");if(e[0]!=i)return r.toString();var t=e[0],n=e[1],o=function(r,e){(null==e||e>r.length)&&(e=r.length);for(var t=0,n=Array(e);t<e;t++)n[t]=r[t];return n}(e).slice(2).join("_");return t+"_"+n+"_"+o.slice(0,4)+"..."+o.slice(-4)},n.prototype.toString=function(){var r=function(r){r=Buffer.isBuffer(r)?r:Buffer.from(r);var e=BigInt("0x"+(r.toString("hex")||"0"));if(0n===e)return"0";for(var n="",i=BigInt(62);e>0n;)n=t[Number(e%i)]+n,e/=i;return n}(JSON.stringify([this.config.url]));return i+"_"+f[this.type]+"_"+this._secret+r+"v1"},n}()}});
2
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/base62.ts","../src/keys.ts"],"sourcesContent":["const BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n\nexport let encodeBase62 = (buffer: Buffer | string) => {\n buffer = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);\n\n let bigint = BigInt('0x' + (buffer.toString('hex') || '0'));\n if (bigint === 0n) return '0';\n\n let result = '';\n let base = BigInt(62);\n\n while (bigint > 0n) {\n let remainder = bigint % base;\n result = BASE62_ALPHABET[Number(remainder)] + result;\n bigint = bigint / base;\n }\n\n return result;\n};\n\nexport let decodeBase62 = (encoded: string) => {\n let bigint = 0n;\n let base = BigInt(62);\n\n for (let i = 0; i < encoded.length; i++) {\n let index = BASE62_ALPHABET.indexOf(encoded[i]);\n if (index === -1) throw new Error('Invalid character');\n bigint = bigint * base + BigInt(index);\n }\n\n let hex = bigint.toString(16);\n if (hex.length % 2) hex = '0' + hex;\n return Buffer.from(hex, 'hex').toString();\n};\n","import { generatePlainId } from '@lowerdeck/id';\nimport { decodeBase62, encodeBase62 } from './base62';\n\nexport type ApiKeyVersions = 'v1';\n\n// export type ApiKeyType =\n// | 'user_auth_token'\n// | 'organization_management_token'\n// | 'organization_app_access_token'\n// | 'instance_access_token_secret'\n// | 'instance_access_token_publishable'\n// | 'ephemeral_client_secret'\n// | 'magic_mcp_token_secret';\n\n// let keyTypes = {\n// uk: 'user_auth_token',\n// lk: 'organization_management_token',\n// ak: 'organization_app_access_token',\n// sk: 'instance_access_token_secret',\n// pk: 'instance_access_token_publishable',\n// ek: 'ephemeral_client_secret',\n// mk: 'magic_mcp_token_secret'\n// } as const;\n\ntype ApiKeyConfig = {\n url: string;\n};\n\nexport let createApiKeyGenerator = <\n Types extends Record<string, string>,\n Prefix extends string\n>(\n keyTypes: Types,\n opts: {\n prefix: Prefix;\n secretLength?: number;\n }\n) => {\n const METORIAL_PREFIX = opts.prefix;\n const SECRET_KEY_LENGTH = opts.secretLength || 60;\n\n type ApiKeyType = Types[keyof Types];\n\n let keyTypesReverse = Object.fromEntries(\n Object.entries(keyTypes).map(([key, value]) => [value, key])\n ) as Record<ApiKeyType, keyof typeof keyTypes>;\n\n // type ApiKeyPrefix = `${Prefix}_${keyof typeof keyTypes & string}_`;\n // type ApiKey = `${ApiKeyPrefix}${string}`;\n\n let parseApiKey = (key: string) => {\n let parts = key.split('_');\n if (parts[0] != METORIAL_PREFIX) return null;\n\n let type = keyTypes[parts[1] as keyof typeof keyTypes];\n if (!type) return null;\n\n let rest = parts.slice(2).join('_');\n\n let version = rest.slice(-2);\n if (version != 'v1') return null;\n\n let secret = rest.slice(0, SECRET_KEY_LENGTH);\n if (secret.length != SECRET_KEY_LENGTH) return null;\n\n let configStr = rest.slice(SECRET_KEY_LENGTH, -2);\n let config: ApiKeyConfig | undefined = undefined;\n\n try {\n let configDecoded = JSON.parse(decodeBase62(configStr));\n if (\n !Array.isArray(configDecoded) ||\n configDecoded.length != 1 ||\n typeof configDecoded[0] != 'string'\n ) {\n return null;\n }\n\n config = {\n url: configDecoded[0]\n };\n } catch (e) {\n return null;\n }\n\n return {\n type,\n secret,\n config,\n version: version as ApiKeyVersions\n };\n };\n\n return class UnifiedApiKey {\n private constructor(\n public readonly type: ApiKeyType,\n public readonly _secret: string,\n public readonly config: ApiKeyConfig,\n public readonly version: ApiKeyVersions\n ) {}\n\n static from(key: string) {\n let parsed = parseApiKey(key);\n if (!parsed) return null;\n\n return new UnifiedApiKey(parsed.type, parsed.secret, parsed.config, parsed.version);\n }\n\n static create(d: { type: ApiKeyType; config: ApiKeyConfig; secret?: string }) {\n if (d.secret && d.secret.length != SECRET_KEY_LENGTH) {\n throw new Error(`Secret key must be ${SECRET_KEY_LENGTH} characters long`);\n }\n\n let secret = d.secret ? d.secret : generatePlainId(SECRET_KEY_LENGTH);\n\n return new UnifiedApiKey(d.type, secret, d.config, 'v1');\n }\n\n static redact(key: string | UnifiedApiKey) {\n let parts = key.toString().split('_');\n if (parts[0] != METORIAL_PREFIX) return key.toString();\n\n let [metorial, type, ...rest] = parts;\n let secret = rest.join('_');\n\n return `${metorial}_${type}_${secret.slice(0, 4)}...${secret.slice(-4)}`;\n }\n\n toString() {\n let config = encodeBase62(JSON.stringify([this.config.url]));\n\n return `${METORIAL_PREFIX}_${keyTypesReverse[this.type] as string}_${this._secret}${config}v1`;\n }\n };\n};\n"],"names":["BASE62_ALPHABET","keyTypes","opts","METORIAL_PREFIX","prefix","SECRET_KEY_LENGTH","secretLength","keyTypesReverse","Object","fromEntries","entries","map","_ref","value","UnifiedApiKey","type","_secret","config","version","this","from","key","parsed","parts","split","rest","slice","join","secret","length","configStr","undefined","configDecoded","JSON","parse","encoded","bigint","base","BigInt","i","index","indexOf","Error","hex","toString","Buffer","decodeBase62","Array","isArray","url","e","parseApiKey","create","d","generatePlainId","redact","metorial","_arrayLikeToArray","prototype","buffer","isBuffer","result","Number","encodeBase62","stringify"],"mappings":"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"}
package/dist/keys.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ export type ApiKeyVersions = 'v1';
2
+ type ApiKeyConfig = {
3
+ url: string;
4
+ };
5
+ export declare let createApiKeyGenerator: <Types extends Record<string, string>, Prefix extends string>(keyTypes: Types, opts: {
6
+ prefix: Prefix;
7
+ secretLength?: number;
8
+ }) => {
9
+ new (type: Types[keyof Types], _secret: string, config: ApiKeyConfig, version: ApiKeyVersions): {
10
+ readonly type: Types[keyof Types];
11
+ readonly _secret: string;
12
+ readonly config: ApiKeyConfig;
13
+ readonly version: ApiKeyVersions;
14
+ toString(): string;
15
+ };
16
+ from(key: string): {
17
+ readonly type: Types[keyof Types];
18
+ readonly _secret: string;
19
+ readonly config: ApiKeyConfig;
20
+ readonly version: ApiKeyVersions;
21
+ toString(): string;
22
+ } | null;
23
+ create(d: {
24
+ type: Types[keyof Types];
25
+ config: ApiKeyConfig;
26
+ secret?: string;
27
+ }): {
28
+ readonly type: Types[keyof Types];
29
+ readonly _secret: string;
30
+ readonly config: ApiKeyConfig;
31
+ readonly version: ApiKeyVersions;
32
+ toString(): string;
33
+ };
34
+ redact(key: string | {
35
+ readonly type: Types[keyof Types];
36
+ readonly _secret: string;
37
+ readonly config: ApiKeyConfig;
38
+ readonly version: ApiKeyVersions;
39
+ toString(): string;
40
+ }): string;
41
+ };
42
+ export {};
43
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC;AAqBlC,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,eAAO,IAAI,qBAAqB,GAC9B,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,MAAM,SAAS,MAAM,EAErB,UAAU,KAAK,EACf,MAAM;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;4CA4D4B,MAAM,UACP,YAAY,WACX,cAAc;;0BAFd,MAAM;yBACP,YAAY;0BACX,cAAc;;;cAGxB,MAAM;;0BALI,MAAM;yBACP,YAAY;0BACX,cAAc;;;cAUxB;QAAE,IAAI,qBAAa;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;0BAZjD,MAAM;yBACP,YAAY;0BACX,cAAc;;;gBAoBtB,MAAM;;0BAtBE,MAAM;yBACP,YAAY;0BACX,cAAc;;KAoBA;CAgB5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=keys.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.test.d.ts","sourceRoot":"","sources":["../src/keys.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { ServiceRequest } from './controller';
2
+ export declare let rpcMux: (opts: {
3
+ path: string;
4
+ cors?: {
5
+ headers?: string[];
6
+ } & ({
7
+ domains: string[];
8
+ } | {
9
+ check: (origin: string) => boolean;
10
+ });
11
+ }, rpcs: {
12
+ handlerNames: string[];
13
+ runMany: (req: ServiceRequest, body: {
14
+ requestId: string;
15
+ calls: {
16
+ id: string;
17
+ name: string;
18
+ payload: any;
19
+ }[];
20
+ }) => Promise<{
21
+ status: number;
22
+ body: {
23
+ calls: any[];
24
+ };
25
+ }>;
26
+ }[]) => {
27
+ path: string;
28
+ fetch: (req: any) => Promise<any>;
29
+ };
30
+ //# sourceMappingURL=rpcMux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcMux.d.ts","sourceRoot":"","sources":["../src/rpcMux.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAe9C,eAAO,IAAI,MAAM,GACf,MAAM;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,GAAG,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;KAAE,CAAC,CAAC;CACtE,EACD,MAAM;IACJ,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,CACP,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,GAAG,CAAC;SACd,EAAE,CAAC;KACL,KACE,OAAO,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE;YACJ,KAAK,EAAE,GAAG,EAAE,CAAC;SACd,CAAC;KACH,CAAC,CAAC;CACJ,EAAE;;iBASkB,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC;CAgPxC,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { Controller, ServiceRequest } from './controller';
2
+ export declare let createServer: (opts: {
3
+ onError?: (opts: {
4
+ request: ServiceRequest;
5
+ error: any;
6
+ reqId: string;
7
+ callId: string;
8
+ callName: string;
9
+ }) => void;
10
+ onRequest?: (opts: {
11
+ reqId: string;
12
+ callId: string;
13
+ callName: string;
14
+ request: ServiceRequest;
15
+ response: {
16
+ status: number;
17
+ body: any;
18
+ };
19
+ }) => void;
20
+ }) => (controller: Controller<any>) => {
21
+ handlerNames: string[];
22
+ runMany: (req: ServiceRequest, body: {
23
+ calls: {
24
+ id: string;
25
+ name: string;
26
+ payload: any;
27
+ }[];
28
+ requestId: string;
29
+ }) => Promise<{
30
+ status: number;
31
+ body: any;
32
+ }>;
33
+ };
34
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAW,cAAc,EAAE,MAAM,cAAc,CAAC;AAInE,eAAO,IAAI,YAAY,GACpB,MAAM;IACL,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,cAAc,CAAC;QACxB,KAAK,EAAE,GAAG,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,GAAG,CAAA;SAAE,CAAC;KACzC,KAAK,IAAI,CAAC;CACZ,MACA,YAAY,UAAU,CAAC,GAAG,CAAC;;mBA4FnB,cAAc,QACb;QACJ,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,GAAG,CAAC;SACd,EAAE,CAAC;QACJ,SAAS,EAAE,MAAM,CAAC;KACnB,KACA,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,GAAG,CAAC;KACX,CAAC;CA4EH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@lowerdeck/api-key",
3
+ "version": "1.0.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "author": "Tobias Herber",
8
+ "license": "Apache 2",
9
+ "type": "module",
10
+ "source": "src/index.ts",
11
+ "exports": {
12
+ "types": "./dist/index.d.ts",
13
+ "require": "./dist/index.cjs",
14
+ "import": "./dist/index.module.js",
15
+ "default": "./dist/index.module.js"
16
+ },
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.module.js",
19
+ "types": "dist/index.d.ts",
20
+ "unpkg": "./dist/index.umd.js",
21
+ "scripts": {
22
+ "test": "vitest run --passWithNoTests",
23
+ "lint": "prettier src/**/*.ts --check",
24
+ "build": "microbundle"
25
+ },
26
+ "devDependencies": {
27
+ "microbundle": "^0.15.1",
28
+ "@lowerdeck/tsconfig": "^1.0.0",
29
+ "typescript": "^5.9.3",
30
+ "vitest": "^3.2.4"
31
+ },
32
+ "dependencies": {
33
+ "@lowerdeck/id": "^1.0.2"
34
+ }
35
+ }
@@ -0,0 +1,38 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { decodeBase62, encodeBase62 } from './base62';
3
+
4
+ describe('base62', () => {
5
+ test('should encode strings', () => {
6
+ expect(encodeBase62('foo')).toBe('SAPP');
7
+ expect(encodeBase62('bar')).toBe('R3HW');
8
+ });
9
+
10
+ test('should decode strings', () => {
11
+ expect(decodeBase62('SAPP')).toBe('foo');
12
+ expect(decodeBase62('R3HW')).toBe('bar');
13
+ });
14
+
15
+ test('should encode and decode strings', () => {
16
+ expect(decodeBase62(encodeBase62('foo'))).toBe('foo');
17
+ expect(decodeBase62(encodeBase62('bar'))).toBe('bar');
18
+ });
19
+
20
+ test('should encode and decode buffers', () => {
21
+ const buffer = Buffer.from('hello');
22
+ expect(decodeBase62(encodeBase62(buffer))).toBe('hello');
23
+ });
24
+
25
+ test('should handle empty strings', () => {
26
+ expect(encodeBase62('\0')).toBe('0');
27
+ expect(decodeBase62('0')).toBe('\0');
28
+ });
29
+
30
+ test('should throw error for invalid characters in decode', () => {
31
+ expect(() => decodeBase62('!@#$')).toThrow('Invalid character');
32
+ });
33
+
34
+ test('should handle large inputs', () => {
35
+ const largeInput = 'a'.repeat(100);
36
+ expect(decodeBase62(encodeBase62(largeInput))).toBe(largeInput);
37
+ });
38
+ });
package/src/base62.ts ADDED
@@ -0,0 +1,34 @@
1
+ const BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
2
+
3
+ export let encodeBase62 = (buffer: Buffer | string) => {
4
+ buffer = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
5
+
6
+ let bigint = BigInt('0x' + (buffer.toString('hex') || '0'));
7
+ if (bigint === 0n) return '0';
8
+
9
+ let result = '';
10
+ let base = BigInt(62);
11
+
12
+ while (bigint > 0n) {
13
+ let remainder = bigint % base;
14
+ result = BASE62_ALPHABET[Number(remainder)] + result;
15
+ bigint = bigint / base;
16
+ }
17
+
18
+ return result;
19
+ };
20
+
21
+ export let decodeBase62 = (encoded: string) => {
22
+ let bigint = 0n;
23
+ let base = BigInt(62);
24
+
25
+ for (let i = 0; i < encoded.length; i++) {
26
+ let index = BASE62_ALPHABET.indexOf(encoded[i]);
27
+ if (index === -1) throw new Error('Invalid character');
28
+ bigint = bigint * base + BigInt(index);
29
+ }
30
+
31
+ let hex = bigint.toString(16);
32
+ if (hex.length % 2) hex = '0' + hex;
33
+ return Buffer.from(hex, 'hex').toString();
34
+ };
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './keys';
package/src/keys.ts ADDED
@@ -0,0 +1,135 @@
1
+ import { generatePlainId } from '@lowerdeck/id';
2
+ import { decodeBase62, encodeBase62 } from './base62';
3
+
4
+ export type ApiKeyVersions = 'v1';
5
+
6
+ // export type ApiKeyType =
7
+ // | 'user_auth_token'
8
+ // | 'organization_management_token'
9
+ // | 'organization_app_access_token'
10
+ // | 'instance_access_token_secret'
11
+ // | 'instance_access_token_publishable'
12
+ // | 'ephemeral_client_secret'
13
+ // | 'magic_mcp_token_secret';
14
+
15
+ // let keyTypes = {
16
+ // uk: 'user_auth_token',
17
+ // lk: 'organization_management_token',
18
+ // ak: 'organization_app_access_token',
19
+ // sk: 'instance_access_token_secret',
20
+ // pk: 'instance_access_token_publishable',
21
+ // ek: 'ephemeral_client_secret',
22
+ // mk: 'magic_mcp_token_secret'
23
+ // } as const;
24
+
25
+ type ApiKeyConfig = {
26
+ url: string;
27
+ };
28
+
29
+ export let createApiKeyGenerator = <
30
+ Types extends Record<string, string>,
31
+ Prefix extends string
32
+ >(
33
+ keyTypes: Types,
34
+ opts: {
35
+ prefix: Prefix;
36
+ secretLength?: number;
37
+ }
38
+ ) => {
39
+ const METORIAL_PREFIX = opts.prefix;
40
+ const SECRET_KEY_LENGTH = opts.secretLength || 60;
41
+
42
+ type ApiKeyType = Types[keyof Types];
43
+
44
+ let keyTypesReverse = Object.fromEntries(
45
+ Object.entries(keyTypes).map(([key, value]) => [value, key])
46
+ ) as Record<ApiKeyType, keyof typeof keyTypes>;
47
+
48
+ // type ApiKeyPrefix = `${Prefix}_${keyof typeof keyTypes & string}_`;
49
+ // type ApiKey = `${ApiKeyPrefix}${string}`;
50
+
51
+ let parseApiKey = (key: string) => {
52
+ let parts = key.split('_');
53
+ if (parts[0] != METORIAL_PREFIX) return null;
54
+
55
+ let type = keyTypes[parts[1] as keyof typeof keyTypes];
56
+ if (!type) return null;
57
+
58
+ let rest = parts.slice(2).join('_');
59
+
60
+ let version = rest.slice(-2);
61
+ if (version != 'v1') return null;
62
+
63
+ let secret = rest.slice(0, SECRET_KEY_LENGTH);
64
+ if (secret.length != SECRET_KEY_LENGTH) return null;
65
+
66
+ let configStr = rest.slice(SECRET_KEY_LENGTH, -2);
67
+ let config: ApiKeyConfig | undefined = undefined;
68
+
69
+ try {
70
+ let configDecoded = JSON.parse(decodeBase62(configStr));
71
+ if (
72
+ !Array.isArray(configDecoded) ||
73
+ configDecoded.length != 1 ||
74
+ typeof configDecoded[0] != 'string'
75
+ ) {
76
+ return null;
77
+ }
78
+
79
+ config = {
80
+ url: configDecoded[0]
81
+ };
82
+ } catch (e) {
83
+ return null;
84
+ }
85
+
86
+ return {
87
+ type,
88
+ secret,
89
+ config,
90
+ version: version as ApiKeyVersions
91
+ };
92
+ };
93
+
94
+ return class UnifiedApiKey {
95
+ private constructor(
96
+ public readonly type: ApiKeyType,
97
+ public readonly _secret: string,
98
+ public readonly config: ApiKeyConfig,
99
+ public readonly version: ApiKeyVersions
100
+ ) {}
101
+
102
+ static from(key: string) {
103
+ let parsed = parseApiKey(key);
104
+ if (!parsed) return null;
105
+
106
+ return new UnifiedApiKey(parsed.type, parsed.secret, parsed.config, parsed.version);
107
+ }
108
+
109
+ static create(d: { type: ApiKeyType; config: ApiKeyConfig; secret?: string }) {
110
+ if (d.secret && d.secret.length != SECRET_KEY_LENGTH) {
111
+ throw new Error(`Secret key must be ${SECRET_KEY_LENGTH} characters long`);
112
+ }
113
+
114
+ let secret = d.secret ? d.secret : generatePlainId(SECRET_KEY_LENGTH);
115
+
116
+ return new UnifiedApiKey(d.type, secret, d.config, 'v1');
117
+ }
118
+
119
+ static redact(key: string | UnifiedApiKey) {
120
+ let parts = key.toString().split('_');
121
+ if (parts[0] != METORIAL_PREFIX) return key.toString();
122
+
123
+ let [metorial, type, ...rest] = parts;
124
+ let secret = rest.join('_');
125
+
126
+ return `${metorial}_${type}_${secret.slice(0, 4)}...${secret.slice(-4)}`;
127
+ }
128
+
129
+ toString() {
130
+ let config = encodeBase62(JSON.stringify([this.config.url]));
131
+
132
+ return `${METORIAL_PREFIX}_${keyTypesReverse[this.type] as string}_${this._secret}${config}v1`;
133
+ }
134
+ };
135
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@lowerdeck/tsconfig/base.json",
4
+ "exclude": [
5
+ "dist"
6
+ ],
7
+ "include": [
8
+ "src"
9
+ ],
10
+ "compilerOptions": {
11
+ "outDir": "dist"
12
+ }
13
+ }
package/tsup.config.js ADDED
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm', 'cjs'],
6
+ splitting: false,
7
+ sourcemap: true,
8
+ clean: true,
9
+ bundle: true,
10
+ dts: true
11
+ });