UNPKG

@erebus-sh/sdk

Version:
1 lines 10.6 kB
{"version":3,"file":"session-CN_NCE4R.cjs","names":[],"sources":["../src/service/baseClient.ts","../src/service/session.ts"],"sourcesContent":["import ky from \"ky\";\n\nconst CLIENT_NAME = \"erebus-service-client\";\n\ninterface BaseClientOptions {\n base_url?: string;\n}\n\nexport const baseClient = ({ base_url }: BaseClientOptions) =>\n ky.create({\n prefixUrl: base_url ?? \"https://api.erebus.sh/v1/\",\n headers: {\n \"content-type\": \"application/json\",\n },\n hooks: {\n beforeRequest: [\n (request) => {\n request.headers.set(\"x-client\", CLIENT_NAME);\n },\n ],\n },\n });\n","import type { Access } from \"@repo/schemas/grant\";\nimport { baseClient } from \"./baseClient\";\nimport { ErebusError } from \"../internal/error\";\nimport type { GrantRequest } from \"@repo/schemas/request/grantChannelRequest\";\nimport { HTTPError } from \"ky\";\n\nexport class ErebusSession {\n constructor(\n private readonly grantRequest: GrantRequest,\n private readonly client: ReturnType<typeof baseClient>,\n ) {\n if (!this.grantRequest.secret_key) {\n throw new ErebusError(\n [\n \"Secret key is required to create a session. Use the ErebusService class method.\",\n \"example:\",\n \"const service = new ErebusService({ secret_api_key: 'test' });\",\n \"const session = await service.prepareSession({ userId: 'test' });\",\n ].join(\"\\n\"),\n );\n }\n if (!this.grantRequest.userId) {\n throw new ErebusError(\n [\n \"User ID is required to create a session. Use the ErebusService class method.\",\n \"example:\",\n \"const service = new ErebusService({ secret_api_key: 'test' });\",\n \"const session = await service.prepareSession({ userId: 'test' });\",\n ].join(\"\\n\"),\n );\n }\n // Set default expiration to 2 hours from now\n this.grantRequest.expiresAt = Math.floor(Date.now() / 1000) + 2 * 60 * 60; // 2 hours from now\n }\n\n public join(channel: string) {\n if (!channel) {\n throw new ErebusError(\"Channel is required to join.\");\n }\n\n if (!/^[A-Za-z0-9_]+$/.test(channel)) {\n throw new ErebusError(\n `Channel name ${channel} must not contain spaces or special characters. Only letters, numbers, and underscores are allowed.`,\n );\n }\n\n if (channel.length > 64) {\n throw new ErebusError(\"Channel name must be less than 64 characters.\");\n }\n\n // if already joined, throw an error\n if (this.grantRequest.channel) {\n throw new ErebusError(\n \"Channel already joined. Please call join(channel) only once.\",\n );\n }\n\n this.grantRequest.channel = channel;\n }\n\n public allow(topic: string, scope: Access) {\n if (!this.grantRequest.channel) {\n throw new ErebusError(\n [\n \"You must set a channel before allowing access to any topics.\",\n \"Please call join(channel) first.\",\n \"example:\",\n \"session.join('channel_name');\",\n ].join(\"\\n\"),\n );\n }\n\n if (!topic) {\n throw new ErebusError(\"Topic is required to allow access.\");\n }\n\n if (topic !== \"*\" && !/^[A-Za-z0-9_]+$/.test(topic)) {\n throw new ErebusError(\n \"Topic name must not contain spaces or special characters. Only letters, numbers, and underscores are allowed. Use '*' to allow all topics.\",\n );\n }\n\n if (topic.length > 64) {\n throw new ErebusError(\"Topic name must be less than 64 characters.\");\n }\n\n if (this.grantRequest.topics.length > 64) {\n throw new ErebusError(\n \"Connecting to more than 64 topics at once is inefficient. Please reduce the number of topics in this grant.\",\n );\n }\n\n if (!scope) {\n throw new ErebusError(\"Scope is required to allow access.\");\n }\n\n this.grantRequest.topics.push({\n topic,\n scope,\n });\n }\n\n public setExpiration(expiration: number) {\n const now = Math.floor(Date.now() / 1000); // current time in seconds\n const min = now + 10 * 60; // 10 minutes from now\n const max = now + 2 * 60 * 60; // 2 hours from now\n\n if (typeof expiration !== \"number\" || !Number.isFinite(expiration)) {\n throw new ErebusError(\n \"Expiration must be a valid number (unix timestamp in seconds).\",\n );\n }\n if (expiration < min) {\n throw new ErebusError(\"Expiration must be at least 10 minutes from now.\");\n }\n if (expiration > max) {\n throw new ErebusError(\"Expiration cannot be more than 2 hours from now.\");\n }\n this.grantRequest.expiresAt = expiration;\n }\n\n /**\n * Last function to be called to get the signed JWT token.\n *\n * @returns\n */\n public async authorize(): Promise<string> {\n if (!this.grantRequest.channel) {\n throw new ErebusError(\n \"You must set a channel before allowing access to any topics. Please call join(channel) first.\",\n );\n }\n\n if (this.grantRequest.topics.length === 0) {\n throw new ErebusError(\n [\n \"At least one topic is required. Please use the allow method to grant access to topics.\",\n \"example:\",\n \"session.allow('topic-1', Access.Read);\",\n ].join(\"\\n\"),\n );\n }\n\n if (this.grantRequest.topics.length > 64) {\n throw new ErebusError(\n [\n \"Connecting to more than 64 topics at once is inefficient. Please reduce the number of topics in this grant.\",\n ].join(\"\\n\"),\n );\n }\n\n const request = this.grantRequest;\n try {\n const response = await this.client.post(\"api/v1/grant-channel\", {\n json: request,\n });\n\n if (!response.ok) {\n throw new ErebusError(\n [\n \"The server returned an error.\",\n \"Please check your API key and ensure you have provided a valid topics array (at least one and less than 64 topics). Please try again.\",\n \"If the problem persists, please contact support: sdk@erebus.sh\",\n ].join(\"\\n\"),\n );\n }\n console.log(\n \"[ErebusSession.authorize] Response received for user:\",\n this.grantRequest.userId,\n );\n const data = (await response.json()) as { grant_jwt: string };\n if (!data) {\n throw new ErebusError(\n [\n \"The server returned an empty response or invalid data.\",\n \"Please check your API key and try again.\",\n \"If the problem persists, please contact support: sdk@erebus.sh\",\n ].join(\"\\n\"),\n );\n }\n return data.grant_jwt;\n } catch (error: unknown) {\n if (error instanceof HTTPError) {\n console.error(error);\n if (error.response.status === 401) {\n throw new ErebusError(\n \"Invalid API key or token. Please check your API key and try again.\",\n JSON.stringify(await error.response.json()),\n );\n } else if (error.response.status === 400) {\n throw new ErebusError(\n \"Invalid topics array. Please check your topics array and try again.\",\n JSON.stringify(await error.response.json()),\n );\n } else if (error.response.status === 500) {\n throw new ErebusError(\n \"Internal server error. Please try again later.\",\n JSON.stringify(await error.response.json()),\n );\n }\n throw new ErebusError(\n `Failed to get token: ${error.response.statusText}`,\n JSON.stringify(await error.response.json()),\n );\n }\n throw error;\n }\n }\n\n /**\n * Debug object for the session.\n */\n get __debugObject(): {\n grant: GrantRequest;\n client: ReturnType<typeof baseClient>;\n } {\n return {\n grant: this.grantRequest,\n client: this.client,\n };\n }\n}\n"],"mappings":"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"}