Skip to content

Commit 2f9655b

Browse files
docs
1 parent e006c36 commit 2f9655b

2 files changed

Lines changed: 159 additions & 194 deletions

File tree

CLAUDE.md

Lines changed: 73 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -4,233 +4,124 @@ Claude Code instructions for the **Types** package.
44

55
## Package Identity
66

7-
**@shipstatic/types** is the single source of truth for all shared TypeScript types, constants, and utilities across the Shipstatic platform.
7+
**@shipstatic/types** is the single source of truth for all shared TypeScript types, constants, and utilities across the Shipstatic platform. If a type is used by more than one package, it belongs here.
88

9-
**Maturity:** Release candidate. Interfaces are stabilizing; changes should be deliberate and well-considered.
10-
11-
```
12-
Types package ← imported by ← API, SDK, CLI, Drop, Web apps
13-
```
14-
15-
**Rule:** If a type is used by more than one package, it belongs here.
9+
**Maturity:** Release candidate — changes should be deliberate.
1610

1711
## Architecture
1812

19-
Single file: `src/index.ts` organized into sections:
20-
21-
```typescript
22-
// =============================================================================
23-
// I. CORE ENTITIES
24-
// =============================================================================
25-
// Deployment, Domain, Token, Account
26-
27-
// =============================================================================
28-
// ERROR SYSTEM
29-
// =============================================================================
30-
// ShipError class, ErrorType enum
31-
32-
// =============================================================================
33-
// CONFIG TYPES
34-
// =============================================================================
35-
// ConfigResponse, PlatformConfig, ResolvedConfig
36-
37-
// ... etc
38-
```
39-
40-
### Section Order
41-
42-
| Section | Contents |
43-
|---------|----------|
44-
| Core Entities | Deployment, Domain, Token, Account + list responses |
45-
| Error System | ErrorType enum, ShipError class, ErrorResponse |
46-
| Config Types | ConfigResponse, PlatformConfig |
47-
| Common Response Patterns | PingResponse |
48-
| Validation Utilities | validateApiKey, validateDeployToken, validateApiUrl |
49-
| SPA Check Types | SPACheckRequest, SPACheckResponse |
50-
| Static File | StaticFile interface |
51-
| Platform Config | DEFAULT_API, ResolvedConfig |
52-
| Progress Tracking | ProgressCallback, DeploymentProgress |
53-
| Platform Constants | API_KEY_PREFIX, DEPLOY_TOKEN_PREFIX, AuthMethod |
54-
| Resource Contracts | DeploymentResource, DomainResource, etc. |
55-
| Billing Types | BillingStatus, CheckoutSession, BillingResource |
56-
| Activity Types | ActivityEvent, Activity, ActivityListResponse |
57-
| File Upload Types | FileValidationStatus, ValidatableFile, ValidationIssue |
58-
| Domain Utilities | isPlatformDomain, isCustomDomain, extractSubdomain, generateDomainUrl |
59-
| Label Utilities | serializeLabels, deserializeLabels |
13+
Single file: `src/index.ts`, organized into named sections in this order:
14+
15+
| Section | Purpose |
16+
|---------|---------|
17+
| Core Entities | Deployment, Domain, Token, Account — status consts, interfaces, list responses |
18+
| Error System | `ErrorType` enum, `ShipError` class, `isShipError` guard |
19+
| Config Types | `ConfigResponse` (plan-based limits from /config endpoint) |
20+
| Extension Blocklist | `BLOCKED_EXTENSIONS`, `isBlockedExtension()` |
21+
| Common Responses | `PingResponse` |
22+
| Platform Constants | Auth prefixes/lengths, `AuthMethod`, `DEPLOYMENT_CONFIG_FILENAME` |
23+
| Validation Utilities | `validateApiKey`, `validateDeployToken`, `validateApiUrl`, `isDeployment` |
24+
| SPA Check Types | `SPACheckRequest`, `SPACheckResponse` |
25+
| Static File | `StaticFile` (cross-environment file representation) |
26+
| Platform Configuration | `PlatformConfig`, `ResolvedConfig` |
27+
| Progress Tracking | `ProgressInfo` |
28+
| URL Constant | `DEFAULT_API` |
29+
| Resource Contracts | `DeployInput`, `DeploymentUploadOptions`, `*Resource` interfaces |
30+
| Billing Types | `BillingStatus`, `CheckoutSession`, `BillingResource`, `KeysResource` |
31+
| Activity Types | `ActivityEvent`, `UserVisibleActivityEvent`, `Activity`, `ActivityMeta` |
32+
| File Upload Types | `FileValidationStatus`, `ValidationIssue`, `ValidatableFile`, `FileValidationResult`, `UploadedFile` |
33+
| Domain Utilities | `isPlatformDomain`, `isCustomDomain`, `extractSubdomain`, `generate*Url` |
34+
| Label Utilities | `LABEL_CONSTRAINTS`, `LABEL_PATTERN`, `serializeLabels`, `deserializeLabels` |
6035

6136
## Quick Reference
6237

6338
```bash
64-
pnpm build # Build package (TypeScript compilation validates types)
65-
pnpm test --run # Run validation constant tests
39+
pnpm build # TypeScript compilation validates all types
40+
pnpm test --run # Runtime tests: validation constants, blocked extensions, label patterns
6641
```
6742

68-
**Runtime behavior tests:** `tests/validation-constants.test.ts` verifies validation constants and utilities (blocked extensions, file statuses, label patterns). TypeScript types are validated at compile time.
69-
7043
## Key Patterns
7144

7245
### ShipError
7346

74-
Unified error class used by API, SDK, and CLI:
75-
7647
```typescript
7748
// Factory methods
78-
ShipError.validation(message, details)
79-
ShipError.notFound(resource, id)
80-
ShipError.authentication(message)
81-
ShipError.business(message, status)
82-
ShipError.network(message, cause)
83-
ShipError.api(message, status)
84-
85-
// Type checking
86-
error.isClientError()
87-
error.isNetworkError()
88-
error.isAuthError()
89-
90-
// Wire format conversion
91-
error.toResponse()
92-
ShipError.fromResponse(response)
49+
ShipError.validation(message, details?)
50+
ShipError.notFound(resource, id?)
51+
ShipError.authentication(message?, details?)
52+
ShipError.rateLimit(message?)
53+
ShipError.business(message, status?) // status defaults to 400
54+
ShipError.network(message, cause?)
55+
ShipError.cancelled(message)
56+
ShipError.file(message, filePath?)
57+
ShipError.config(message, details?)
58+
ShipError.api(message, status?) // status defaults to 500
59+
ShipError.database / ShipError.storage // aliases for api()
60+
61+
// Type checks
62+
error.isClientError() // Business | Config | File | Validation
63+
error.isNetworkError() / isAuthError() / isValidationError() / isFileError() / isConfigError()
64+
error.isType(errorType)
65+
66+
// Wire format
67+
error.toResponse() / ShipError.fromResponse(response)
68+
69+
// Structural guard (handles module duplication in bundles)
70+
isShipError(error)
9371
```
9472
9573
### Resource Contracts
9674
97-
Interfaces that SDK implementations must follow. These define the **minimal contract** - SDKs may accept additional options for implementation-specific concerns (timeout, signals, etc.):
75+
Interfaces define the **minimal contract** — SDK implementations may add runtime options (timeout, signal, callbacks). Always match the full interface:
9876
99-
```typescript
100-
interface DeploymentResource {
101-
upload: (input: DeployInput, options?: DeploymentUploadOptions) => Promise<Deployment>;
102-
list: () => Promise<DeploymentListResponse>;
103-
get: (id: string) => Promise<Deployment>;
104-
set: (id: string, options: { labels: string[] }) => Promise<Deployment>;
105-
remove: (id: string) => Promise<void>;
106-
}
107-
108-
interface DomainResource {
109-
set: (name: string, options?: { deployment?: string; labels?: string[] }) => Promise<Domain>;
110-
list: () => Promise<DomainListResponse>;
111-
get: (name: string) => Promise<Domain>;
112-
remove: (name: string) => Promise<void>;
113-
verify: (name: string) => Promise<{ message: string }>;
114-
// ... dns, records, share
115-
}
116-
117-
interface TokenResource {
118-
create: (options?: { ttl?: number; labels?: string[] }) => Promise<TokenCreateResponse>;
119-
list: () => Promise<TokenListResponse>;
120-
remove: (token: string) => Promise<void>;
121-
}
77+
```
78+
DeploymentResource : upload, list, get, set, remove
79+
DomainResource : set, list, get, remove, verify, validate, dns, records, share
80+
TokenResource : create, list, remove
81+
BillingResource : checkout, status
82+
KeysResource : create
83+
AccountResource : get
12284
```
12385
124-
**Design principle:** Contracts define API-level options (labels, subdomain). SDK implementations extend with runtime options (timeout, signal, callbacks).
125-
126-
### Status Constants
127-
128-
Use const objects with `as const` for type-safe status values:
86+
### Status Constants Pattern
12987
13088
```typescript
131-
export const DeploymentStatus = {
132-
PENDING: 'pending',
133-
SUCCESS: 'success',
134-
FAILED: 'failed',
135-
DELETING: 'deleting'
136-
} as const;
137-
138-
export type DeploymentStatusType = typeof DeploymentStatus[keyof typeof DeploymentStatus];
89+
export const FooStatus = { PENDING: 'pending', ACTIVE: 'active' } as const;
90+
export type FooStatusType = typeof FooStatus[keyof typeof FooStatus];
13991
```
14092
141-
### Readonly vs Mutable Fields
93+
Used by: `DeploymentStatus`, `DomainStatus`, `AccountPlan`, `FileValidationStatus`, `AuthMethod`.
14294
143-
Interfaces use `readonly` for immutable fields:
95+
### Readonly vs Mutable
14496
145-
```typescript
146-
interface Deployment {
147-
readonly deployment: string; // Never changes
148-
readonly created: number; // Never changes
149-
status: DeploymentStatusType; // Can be updated
150-
expires: number | null; // Can be updated
151-
}
152-
```
97+
Use `readonly` for stable fields (`id`, `created`, `url`). Leave mutable fields that the API can update (`status`, `expires`, `labels`, `deployment`).
15398
15499
## Consumers
155100
156101
| Package | Uses |
157102
|---------|------|
158103
| `@shipstatic/ship` | All types, ShipError, validation utilities |
159-
| `@shipstatic/drop` | FileValidationStatus, ValidatableFile |
104+
| `@shipstatic/drop` | `FileValidationStatus`, `ValidatableFile` |
160105
| `cloudflare/api` | All entity types, ShipError, constants |
161106
| `cloudflare/consumer` | ShipError, entity types |
162107
| `web/my` | Entity types, response types |
163108
164109
## Adding New Types
165110
166-
1. **Find the right section** in `src/index.ts`
167-
2. **Add type with JSDoc** - All public types need documentation
168-
3. **Use patterns** - Match existing patterns (readonly, status constants, etc.)
169-
4. **Export explicitly** - All types are exported from the single file
170-
5. **Build** - `pnpm build` validates TypeScript
171-
172-
### When Adding Entity Types
173-
174-
```typescript
175-
// 1. Status constants (if applicable)
176-
export const NewEntityStatus = {
177-
PENDING: 'pending',
178-
ACTIVE: 'active'
179-
} as const;
180-
181-
export type NewEntityStatusType = typeof NewEntityStatus[keyof typeof NewEntityStatus];
182-
183-
// 2. Core entity interface
184-
export interface NewEntity {
185-
readonly id: string;
186-
readonly created: number;
187-
status: NewEntityStatusType;
188-
}
189-
190-
// 3. List response
191-
export interface NewEntityListResponse {
192-
entities: NewEntity[];
193-
cursor?: string;
194-
total?: number;
195-
}
196-
197-
// 4. Resource contract (if SDK-accessible)
198-
export interface NewEntityResource {
199-
create: (...) => Promise<NewEntity>;
200-
list: () => Promise<NewEntityListResponse>;
201-
// ...
202-
}
203-
```
204-
205-
### When Adding Error Types
111+
1. Find the right section in `src/index.ts` (keep section order above)
112+
2. Add JSDoc to every exported symbol
113+
3. Follow existing entity pattern: status const → entity interface → list response → resource contract
114+
4. Run `pnpm build` to validate
206115
207-
Add to ErrorType enum and create factory method on ShipError:
208-
209-
```typescript
210-
// In ErrorType enum
211-
NewError = "new_error",
212-
213-
// In ShipError class
214-
static newError(message: string): ShipError {
215-
return new ShipError(ErrorType.NewError, message, 400);
216-
}
217-
```
116+
**New error types:** Add to `ErrorType` enum + a static factory on `ShipError`.
218117
219118
## Design Principles
220119
221-
1. **Single source of truth** - No type duplication anywhere
222-
2. **Wire format compatibility** - Types match API JSON exactly
223-
3. **Readonly by default** - Mutable only when necessary
224-
4. **Exhaustive enums** - Use const objects for compile-time safety
225-
5. **JSDoc everything** - Types are self-documenting
226-
227-
## Related Documentation
228-
229-
| Document | Content |
230-
|----------|---------|
231-
| `../ship/CLAUDE.md` | SDK that implements resource contracts |
232-
| `../drop/CLAUDE.md` | Uses file validation types |
233-
| `../../cloudflare/api/CLAUDE.md` | API that produces these types |
120+
1. **Single source of truth** — no type duplication anywhere
121+
2. **Wire format compatibility** — types match API JSON exactly
122+
3. **Readonly by default** — mutable only when necessary
123+
4. **Const objects over enums** — `as const` for compile-time safety
124+
5. **JSDoc everything** — types are self-documenting
234125
235126
---
236127

0 commit comments

Comments
 (0)