Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/client/GuildPassClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AccessService } from '../access/access.service';
// GuildPass SDK: Import external module dependencies.
import { DEFAULT_CONFIG } from '../config/defaultConfig';
// GuildPass SDK: Pull in package or module bindings.
import { GuildPassClientConfig } from '../config/sdkConfig';
import { GuildPassClientConfig, validateConfig } from '../config/sdkConfig';
// GuildPass SDK: Import external module dependencies.
import { ContractClient } from '../contracts/contractClient';
// GuildPass SDK: Pull in package or module bindings.
Expand Down Expand Up @@ -41,6 +41,7 @@ export class GuildPassClient {

// GuildPass SDK: Class member structure property or constructor.
constructor(config: GuildPassClientConfig) {
validateConfig(config);
// GuildPass SDK: Execution block boundary initialization.
this.config = {
...DEFAULT_CONFIG,
Expand Down
20 changes: 20 additions & 0 deletions src/config/sdkConfig.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { GuildPassError } from '../errors/GuildPassError';
import { GuildPassErrorCode } from '../errors/errorCodes';

// GuildPass SDK: Exported component definition.
export type GuildPassClientConfig = {
apiUrl: string;
Expand All @@ -8,3 +11,20 @@ export type GuildPassClientConfig = {
timeoutMs?: number;
// GuildPass SDK: End of logic containment structure block.
};

export function validateConfig(config: GuildPassClientConfig): void {
if (!config.apiUrl) {
throw new GuildPassError('apiUrl is required', GuildPassErrorCode.INVALID_CONFIG);
}
try {
const url = new URL(config.apiUrl);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error();
}
} catch {
throw new GuildPassError(`Invalid apiUrl: "${config.apiUrl}"`, GuildPassErrorCode.INVALID_CONFIG);
}
if (config.timeoutMs !== undefined && (typeof config.timeoutMs !== 'number' || config.timeoutMs <= 0)) {
throw new GuildPassError('timeoutMs must be a positive number', GuildPassErrorCode.INVALID_CONFIG);
}
}
31 changes: 31 additions & 0 deletions tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { describe, it, expect } from 'vitest';
// GuildPass SDK: Import external module dependencies.
import { GuildPassClient } from '../src/client/GuildPassClient';
import { GuildPassError } from '../src/errors/GuildPassError';
import { GuildPassErrorCode } from '../src/errors/errorCodes';

// GuildPass SDK: Test suite container block.
describe('GuildPassClient', () => {
Expand Down Expand Up @@ -47,3 +49,32 @@ describe('GuildPassClient', () => {
});
// GuildPass SDK: End of logic containment structure block.
});

describe('GuildPassClient config validation', () => {
it('should throw when apiUrl is missing', () => {
expect(() => new GuildPassClient({ apiUrl: '' }))
.toThrow(GuildPassError);
expect(() => new GuildPassClient({ apiUrl: '' }))
.toThrow(expect.objectContaining({ code: GuildPassErrorCode.INVALID_CONFIG }));
});

it('should throw when apiUrl is an invalid URL', () => {
expect(() => new GuildPassClient({ apiUrl: 'not-a-url' }))
.toThrow(expect.objectContaining({ code: GuildPassErrorCode.INVALID_CONFIG }));
});

it('should throw when timeoutMs is zero', () => {
expect(() => new GuildPassClient({ apiUrl: 'https://api.guildpass.xyz', timeoutMs: 0 }))
.toThrow(expect.objectContaining({ code: GuildPassErrorCode.INVALID_CONFIG }));
});

it('should throw when timeoutMs is negative', () => {
expect(() => new GuildPassClient({ apiUrl: 'https://api.guildpass.xyz', timeoutMs: -1 }))
.toThrow(expect.objectContaining({ code: GuildPassErrorCode.INVALID_CONFIG }));
});

it('should not throw for valid config', () => {
expect(() => new GuildPassClient({ apiUrl: 'https://api.guildpass.xyz', timeoutMs: 5000 }))
.not.toThrow();
});
});
Loading