Skip to content

Commit 54a922a

Browse files
Merge branch 'develop'
2 parents 79103b2 + fa6a692 commit 54a922a

36 files changed

+8516
-1
lines changed
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: false
5+
---
6+
# SDK Domain Structure Guide
7+
8+
This guide defines the standard structure and patterns for SDK domains (user, template, webhook, workflow, etc.).
9+
10+
## File Structure
11+
12+
Each domain should have the following files:
13+
- `src/{domain}/client.ts` - Main client class
14+
- `src/{domain}/types.ts` - Type definitions
15+
- `examples/{domain}-usage.ts` - Example script
16+
17+
## Client Class Structure
18+
19+
The client class should:
20+
1. Extend `BaseClient`
21+
2. Have clear method documentation with JSDoc comments
22+
3. Follow consistent parameter naming (camelCase)
23+
4. Use proper type annotations
24+
5. Handle API responses consistently
25+
26+
### Method Patterns
27+
28+
#### Pattern 1: Direct Request Type
29+
Use this pattern when the request is straightforward and maps directly to the API payload:
30+
31+
```typescript
32+
/**
33+
* Method description.
34+
* @param requestData - Request data matching the RequestType interface fields
35+
* @returns A ResponseType object representing the operation result
36+
*/
37+
async methodName(requestData: RequestType): Promise<ResponseType> {
38+
const response = await this.makeRequest<RequestType, ResponseType>(
39+
'HTTP_METHOD',
40+
'/api/v1/public/endpoint',
41+
requestData
42+
);
43+
return response.data as ResponseType;
44+
}
45+
```
46+
47+
#### Pattern 2: Individual Parameters
48+
Use this pattern when:
49+
- The method needs complex validation logic
50+
- Parameters are optional or have interdependencies
51+
- The API payload needs to be constructed from multiple parameters
52+
53+
```typescript
54+
/**
55+
* Method description.
56+
* @param param1 - Description of first parameter
57+
* @param param2 - Description of second parameter
58+
* @param optionalParam - Description of optional parameter
59+
* @returns A ResponseType object representing the operation result
60+
*/
61+
async methodName(
62+
param1: Param1Type,
63+
param2: Param2Type,
64+
optionalParam?: OptionalType
65+
): Promise<ResponseType> {
66+
// Validate parameters
67+
if (!param1 || !param2) {
68+
throw new SirenValidationError('Required parameters missing');
69+
}
70+
71+
// Construct payload
72+
const payload: RequestType = {
73+
field1: param1,
74+
field2: param2,
75+
...(optionalParam && { optionalField: optionalParam })
76+
};
77+
78+
const response = await this.makeRequest<RequestType, ResponseType>(
79+
'HTTP_METHOD',
80+
'/api/v1/public/endpoint',
81+
payload
82+
);
83+
return response.data as ResponseType;
84+
}
85+
```
86+
87+
## Types Structure
88+
89+
Types should:
90+
1. Use clear, descriptive interfaces
91+
2. Follow consistent naming (PascalCase for types, camelCase for properties)
92+
3. Include proper JSDoc comments
93+
4. Only define types that are actually used in the client methods
94+
5. Use the `APIResponse` wrapper at the client level, not in type definitions
95+
96+
Example structure:
97+
```typescript
98+
/**
99+
* Base interface for domain data.
100+
*/
101+
export interface DomainBase {
102+
/** Unique identifier */
103+
id?: string;
104+
/** Name of the domain object */
105+
name?: string;
106+
// ... other base fields
107+
}
108+
109+
/**
110+
* Request interface for domain operations.
111+
*/
112+
export interface DomainRequest extends DomainBase {}
113+
114+
/**
115+
* Response data for domain operations.
116+
*/
117+
export interface Domain extends DomainBase {
118+
/** Creation timestamp */
119+
createdAt?: string;
120+
/** Last update timestamp */
121+
updatedAt?: string;
122+
// ... other response fields
123+
}
124+
```
125+
126+
Note: Do not define API response types (e.g., `DomainAPIResponse`) in the types file. The `APIResponse` wrapper is handled at the client level through `makeRequest<RequestType, ResponseType>`.
127+
128+
## Example Script Structure
129+
130+
Example scripts should:
131+
1. Use consistent environment setup
132+
2. Show all main operations
133+
3. Use exact same values as Python SDK examples
134+
4. Have proper error handling
135+
5. Use minimal but complete examples
136+
137+
Example structure:
138+
```typescript
139+
import 'dotenv/config';
140+
import { SirenClient } from '../src';
141+
import { SirenAPIError, SirenError } from '../src/common/errors';
142+
143+
const apiToken = process.env.SIREN_API_KEY;
144+
if (!apiToken) {
145+
console.error('Error: SIREN_API_KEY environment variable is not set');
146+
process.exit(1);
147+
}
148+
149+
const client = new SirenClient({ apiToken, env: 'dev' });
150+
151+
async function domainExamples() {
152+
try {
153+
// Operation 1
154+
const result1 = await client.domain.operation1({
155+
// Use exact same values as Python SDK
156+
});
157+
console.log('Operation 1 result:', result1);
158+
159+
// Operation 2
160+
const result2 = await client.domain.operation2({
161+
// Use exact same values as Python SDK
162+
});
163+
console.log('Operation 2 result:', result2);
164+
} catch (error) {
165+
if (error instanceof SirenAPIError) {
166+
console.error(`API Error: ${error.errorCode} - ${error.message}`);
167+
} else if (error instanceof SirenError) {
168+
console.error(`SDK Error: ${error.message}`);
169+
} else {
170+
console.error('Unexpected error:', error);
171+
}
172+
}
173+
}
174+
175+
domainExamples();
176+
```
177+
178+
## Error Handling
179+
180+
All domains should:
181+
1. Use `SirenAPIError` for API-level errors
182+
2. Use `SirenError` for SDK-level errors
183+
3. Include proper error messages and codes
184+
4. Handle errors consistently across all methods
185+
186+
## API Response Handling
187+
188+
All domains should:
189+
1. Use the `APIResponse` wrapper consistently
190+
2. Handle null checks properly
191+
3. Use type assertions only when necessary
192+
4. Return clean data objects without the wrapper
193+
194+
## Testing
195+
196+
Each domain should have:
197+
1. Unit tests for all methods
198+
2. Tests for success and error cases
199+
3. Tests matching Python SDK's test cases
200+
4. Proper mocking of API responses
201+
202+
## Documentation
203+
204+
Each domain should have:
205+
1. Clear method documentation
206+
2. Type documentation
207+
3. Example usage in comments
208+
4. Consistent formatting
209+
210+
## References
211+
212+
For reference implementations, see:
213+
- [User Client](mdc:siren-ts-sdk/src/user/client.ts)
214+
- [User Types](mdc:siren-ts-sdk/src/user/types.ts)
215+
- [User Example](mdc:siren-ts-sdk/examples/user-usage.ts)
216+
- [Messaging Client](mdc:siren-ts-sdk/src/messaging/client.ts)

.github/workflows/publish.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Publish to npm
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
tags:
7+
- "v*.*.*"
8+
9+
jobs:
10+
publish:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-node@v4
17+
with:
18+
node-version: "18"
19+
registry-url: "https://registry.npmjs.org/"
20+
always-auth: true
21+
22+
- name: Install deps & build
23+
run: |
24+
npm ci
25+
npm run build
26+
27+
- name: Publish to npm
28+
run: npm publish
29+
env:
30+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Node modules
2+
node_modules/
3+
4+
# Build output
5+
dist/
6+
build/
7+
8+
# TypeScript cache
9+
*.tsbuildinfo
10+
11+
# Logs
12+
npm-debug.log*
13+
yarn-debug.log*
14+
yarn-error.log*
15+
16+
# Env files
17+
.env
18+
.env.*
19+
20+
# Test coverage
21+
coverage/
22+
23+
# IDE files
24+
.vscode/
25+
.idea/
26+
.DS_Store
27+
28+
# Jest cache
29+
.jest/
30+
31+
# Misc
32+
*.log

0 commit comments

Comments
 (0)