@schafevormfenster/rest-commons 0.1.1
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.
- package/CONTRIBUTING.md +1190 -0
- package/README.md +275 -0
- package/bin/setup.js +10 -0
- package/dist/api-schemas/error.schema.d.ts +20 -0
- package/dist/api-schemas/error.schema.d.ts.map +1 -0
- package/dist/api-schemas/error.schema.js +17 -0
- package/dist/api-schemas/health.schema.d.ts +497 -0
- package/dist/api-schemas/health.schema.d.ts.map +1 -0
- package/dist/api-schemas/health.schema.js +33 -0
- package/dist/api-schemas/okay.schema.d.ts +13 -0
- package/dist/api-schemas/okay.schema.d.ts.map +1 -0
- package/dist/api-schemas/okay.schema.js +5 -0
- package/dist/api-schemas/paginated-results.schema.d.ts +59 -0
- package/dist/api-schemas/paginated-results.schema.d.ts.map +1 -0
- package/dist/api-schemas/paginated-results.schema.js +10 -0
- package/dist/api-schemas/partial-results.schema.d.ts +30 -0
- package/dist/api-schemas/partial-results.schema.d.ts.map +1 -0
- package/dist/api-schemas/partial-results.schema.js +10 -0
- package/dist/api-schemas/result.schema.d.ts +17 -0
- package/dist/api-schemas/result.schema.d.ts.map +1 -0
- package/dist/api-schemas/result.schema.js +5 -0
- package/dist/api-schemas/results.schema.d.ts +21 -0
- package/dist/api-schemas/results.schema.d.ts.map +1 -0
- package/dist/api-schemas/results.schema.js +5 -0
- package/dist/helpers/correlation/get-correlation-id.d.ts +7 -0
- package/dist/helpers/correlation/get-correlation-id.d.ts.map +1 -0
- package/dist/helpers/correlation/get-correlation-id.js +16 -0
- package/dist/helpers/correlation/get-header.d.ts +7 -0
- package/dist/helpers/correlation/get-header.d.ts.map +1 -0
- package/dist/helpers/correlation/get-header.js +11 -0
- package/dist/helpers/detect-mime-type.d.ts +11 -0
- package/dist/helpers/detect-mime-type.d.ts.map +1 -0
- package/dist/helpers/detect-mime-type.js +40 -0
- package/dist/helpers/detect-suspicious-patterns.d.ts +8 -0
- package/dist/helpers/detect-suspicious-patterns.d.ts.map +1 -0
- package/dist/helpers/detect-suspicious-patterns.js +55 -0
- package/dist/helpers/eventify-constants.types.d.ts +32 -0
- package/dist/helpers/eventify-constants.types.d.ts.map +1 -0
- package/dist/helpers/eventify-constants.types.js +40 -0
- package/dist/helpers/hash-binary.d.ts +21 -0
- package/dist/helpers/hash-binary.d.ts.map +1 -0
- package/dist/helpers/hash-binary.js +28 -0
- package/dist/helpers/mime-types/detect-image-mime-type.d.ts +5 -0
- package/dist/helpers/mime-types/detect-image-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-image-mime-type.js +41 -0
- package/dist/helpers/mime-types/detect-ole-mime-type.d.ts +6 -0
- package/dist/helpers/mime-types/detect-ole-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-ole-mime-type.js +34 -0
- package/dist/helpers/mime-types/detect-pdf-mime-type.d.ts +5 -0
- package/dist/helpers/mime-types/detect-pdf-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-pdf-mime-type.js +13 -0
- package/dist/helpers/mime-types/detect-zip-mime-type.d.ts +6 -0
- package/dist/helpers/mime-types/detect-zip-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-zip-mime-type.js +23 -0
- package/dist/helpers/parameter-validation.d.ts +6 -0
- package/dist/helpers/parameter-validation.d.ts.map +1 -0
- package/dist/helpers/parameter-validation.js +19 -0
- package/dist/helpers/parameter-validation.types.d.ts +16 -0
- package/dist/helpers/parameter-validation.types.d.ts.map +1 -0
- package/dist/helpers/parameter-validation.types.js +38 -0
- package/dist/helpers/response-headers/build-api-unauthorized-headers.d.ts +6 -0
- package/dist/helpers/response-headers/build-api-unauthorized-headers.d.ts.map +1 -0
- package/dist/helpers/response-headers/build-api-unauthorized-headers.js +23 -0
- package/dist/helpers/response-headers/environment.types.d.ts +2 -0
- package/dist/helpers/response-headers/environment.types.d.ts.map +1 -0
- package/dist/helpers/response-headers/environment.types.js +1 -0
- package/dist/helpers/response-headers/resolve-environment.d.ts +8 -0
- package/dist/helpers/response-headers/resolve-environment.d.ts.map +1 -0
- package/dist/helpers/response-headers/resolve-environment.js +18 -0
- package/dist/helpers/slugify.d.ts +15 -0
- package/dist/helpers/slugify.d.ts.map +1 -0
- package/dist/helpers/slugify.js +32 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/normalization/normalize-list.d.ts +11 -0
- package/dist/normalization/normalize-list.d.ts.map +1 -0
- package/dist/normalization/normalize-list.js +19 -0
- package/dist/normalization/normalize-location.d.ts +16 -0
- package/dist/normalization/normalize-location.d.ts.map +1 -0
- package/dist/normalization/normalize-location.js +26 -0
- package/dist/primitives/coordinate-precision.d.ts +10 -0
- package/dist/primitives/coordinate-precision.d.ts.map +1 -0
- package/dist/primitives/coordinate-precision.js +27 -0
- package/dist/primitives/geo-point.schema.d.ts +8 -0
- package/dist/primitives/geo-point.schema.d.ts.map +1 -0
- package/dist/primitives/geo-point.schema.js +10 -0
- package/dist/primitives/geoname-id.schema.d.ts +8 -0
- package/dist/primitives/geoname-id.schema.d.ts.map +1 -0
- package/dist/primitives/geoname-id.schema.js +9 -0
- package/dist/primitives/international-zip.schema.d.ts +76 -0
- package/dist/primitives/international-zip.schema.d.ts.map +1 -0
- package/dist/primitives/international-zip.schema.js +81 -0
- package/dist/primitives/latitude.schema.d.ts +9 -0
- package/dist/primitives/latitude.schema.d.ts.map +1 -0
- package/dist/primitives/latitude.schema.js +13 -0
- package/dist/primitives/location.schema.d.ts +8 -0
- package/dist/primitives/location.schema.d.ts.map +1 -0
- package/dist/primitives/location.schema.js +15 -0
- package/dist/primitives/longitude.schema.d.ts +9 -0
- package/dist/primitives/longitude.schema.d.ts.map +1 -0
- package/dist/primitives/longitude.schema.js +13 -0
- package/dist/primitives/numeric-id.schema.d.ts +8 -0
- package/dist/primitives/numeric-id.schema.d.ts.map +1 -0
- package/dist/primitives/numeric-id.schema.js +10 -0
- package/dist/primitives/slug.schema.d.ts +17 -0
- package/dist/primitives/slug.schema.d.ts.map +1 -0
- package/dist/primitives/slug.schema.js +30 -0
- package/dist/primitives/uuid.schema.d.ts +8 -0
- package/dist/primitives/uuid.schema.d.ts.map +1 -0
- package/dist/primitives/uuid.schema.js +9 -0
- package/dist/primitives/wikidata-id.schema.d.ts +9 -0
- package/dist/primitives/wikidata-id.schema.d.ts.map +1 -0
- package/dist/primitives/wikidata-id.schema.js +10 -0
- package/dist/time/boundary-enforcement.d.ts +11 -0
- package/dist/time/boundary-enforcement.d.ts.map +1 -0
- package/dist/time/boundary-enforcement.js +43 -0
- package/dist/time/bounded-time.schema.d.ts +31 -0
- package/dist/time/bounded-time.schema.d.ts.map +1 -0
- package/dist/time/bounded-time.schema.js +77 -0
- package/dist/time/flexible-time-parser.d.ts +12 -0
- package/dist/time/flexible-time-parser.d.ts.map +1 -0
- package/dist/time/flexible-time-parser.js +94 -0
- package/dist/time/flexible-time.schema.d.ts +31 -0
- package/dist/time/flexible-time.schema.d.ts.map +1 -0
- package/dist/time/flexible-time.schema.js +31 -0
- package/dist/time/get-week-end.d.ts +10 -0
- package/dist/time/get-week-end.d.ts.map +1 -0
- package/dist/time/get-week-end.js +25 -0
- package/dist/time/get-week-start.d.ts +10 -0
- package/dist/time/get-week-start.d.ts.map +1 -0
- package/dist/time/get-week-start.js +25 -0
- package/dist/time/is-relative-time.d.ts +8 -0
- package/dist/time/is-relative-time.d.ts.map +1 -0
- package/dist/time/is-relative-time.js +9 -0
- package/dist/time/iso8601.schema.d.ts +14 -0
- package/dist/time/iso8601.schema.d.ts.map +1 -0
- package/dist/time/iso8601.schema.js +17 -0
- package/dist/time/iso8601.types.d.ts +6 -0
- package/dist/time/iso8601.types.d.ts.map +1 -0
- package/dist/time/iso8601.types.js +11 -0
- package/dist/time/parse-relative-time.d.ts +9 -0
- package/dist/time/parse-relative-time.d.ts.map +1 -0
- package/dist/time/parse-relative-time.js +36 -0
- package/dist/time/relative-time.schema.d.ts +23 -0
- package/dist/time/relative-time.schema.d.ts.map +1 -0
- package/dist/time/relative-time.schema.js +25 -0
- package/dist/time/since-parameter.schema.d.ts +8 -0
- package/dist/time/since-parameter.schema.d.ts.map +1 -0
- package/dist/time/since-parameter.schema.js +56 -0
- package/dist/time/time-helpers.d.ts +19 -0
- package/dist/time/time-helpers.d.ts.map +1 -0
- package/dist/time/time-helpers.js +56 -0
- package/dist/time/time-schemas.d.ts +20 -0
- package/dist/time/time-schemas.d.ts.map +1 -0
- package/dist/time/time-schemas.js +25 -0
- package/dist/time/timezone.types.d.ts +17 -0
- package/dist/time/timezone.types.d.ts.map +1 -0
- package/dist/time/timezone.types.js +15 -0
- package/dist/validation/zod-error-handler.d.ts +3 -0
- package/dist/validation/zod-error-handler.d.ts.map +1 -0
- package/dist/validation/zod-error-handler.js +189 -0
- package/dist/validation/zod-utils.d.ts +9 -0
- package/dist/validation/zod-utils.d.ts.map +1 -0
- package/dist/validation/zod-utils.js +23 -0
- package/eslint.config.mjs +16 -0
- package/package.json +44 -0
- package/src/api-schemas/error.schema.test.ts +27 -0
- package/src/api-schemas/error.schema.ts +23 -0
- package/src/api-schemas/health.schema.test.ts +104 -0
- package/src/api-schemas/health.schema.ts +63 -0
- package/src/api-schemas/okay.schema.test.ts +15 -0
- package/src/api-schemas/okay.schema.ts +8 -0
- package/src/api-schemas/paginated-results.schema.ts +17 -0
- package/src/api-schemas/partial-results.schema.ts +13 -0
- package/src/api-schemas/result.schema.test.ts +19 -0
- package/src/api-schemas/result.schema.ts +9 -0
- package/src/api-schemas/results.schema.test.ts +15 -0
- package/src/api-schemas/results.schema.ts +9 -0
- package/src/helpers/correlation/get-correlation-id.test.ts +126 -0
- package/src/helpers/correlation/get-correlation-id.ts +22 -0
- package/src/helpers/correlation/get-header.test.ts +179 -0
- package/src/helpers/correlation/get-header.ts +21 -0
- package/src/helpers/detect-mime-type.test.ts +100 -0
- package/src/helpers/detect-mime-type.ts +46 -0
- package/src/helpers/detect-suspicious-patterns.test.ts +45 -0
- package/src/helpers/detect-suspicious-patterns.ts +57 -0
- package/src/helpers/eventify-constants.test.ts +52 -0
- package/src/helpers/eventify-constants.types.test.ts +52 -0
- package/src/helpers/eventify-constants.types.ts +51 -0
- package/src/helpers/hash-binary.test.ts +60 -0
- package/src/helpers/hash-binary.ts +30 -0
- package/src/helpers/mime-types/detect-image-mime-type.test.ts +73 -0
- package/src/helpers/mime-types/detect-image-mime-type.ts +50 -0
- package/src/helpers/mime-types/detect-ole-mime-type.test.ts +86 -0
- package/src/helpers/mime-types/detect-ole-mime-type.ts +44 -0
- package/src/helpers/mime-types/detect-pdf-mime-type.test.ts +39 -0
- package/src/helpers/mime-types/detect-pdf-mime-type.ts +15 -0
- package/src/helpers/mime-types/detect-zip-mime-type.test.ts +88 -0
- package/src/helpers/mime-types/detect-zip-mime-type.ts +28 -0
- package/src/helpers/parameter-validation.test.ts +35 -0
- package/src/helpers/parameter-validation.ts +32 -0
- package/src/helpers/process-eventify-request.ts +146 -0
- package/src/helpers/response-headers/build-api-unauthorized-headers.ts +30 -0
- package/src/helpers/response-headers/environment.types.ts +1 -0
- package/src/helpers/response-headers/resolve-environment.ts +17 -0
- package/src/helpers/slugify.test.ts +77 -0
- package/src/helpers/slugify.ts +34 -0
- package/src/index.ts +46 -0
- package/src/normalization/normalize-list.test.ts +43 -0
- package/src/normalization/normalize-list.ts +21 -0
- package/src/normalization/normalize-location.test.ts +91 -0
- package/src/normalization/normalize-location.ts +29 -0
- package/src/primitives/coordinate-precision.test.ts +46 -0
- package/src/primitives/coordinate-precision.ts +30 -0
- package/src/primitives/geo-point.schema.test.ts +70 -0
- package/src/primitives/geo-point.schema.ts +14 -0
- package/src/primitives/geoname-id.schema.test.ts +60 -0
- package/src/primitives/geoname-id.schema.ts +12 -0
- package/src/primitives/international-zip.schema.test.ts +212 -0
- package/src/primitives/international-zip.schema.ts +103 -0
- package/src/primitives/latitude.schema.test.ts +77 -0
- package/src/primitives/latitude.schema.ts +20 -0
- package/src/primitives/location.schema.test.ts +21 -0
- package/src/primitives/location.schema.ts +22 -0
- package/src/primitives/longitude.schema.test.ts +77 -0
- package/src/primitives/longitude.schema.ts +20 -0
- package/src/primitives/numeric-id.schema.test.ts +32 -0
- package/src/primitives/numeric-id.schema.ts +13 -0
- package/src/primitives/slug.schema.test.ts +101 -0
- package/src/primitives/slug.schema.ts +41 -0
- package/src/primitives/uuid.schema.test.ts +45 -0
- package/src/primitives/uuid.schema.ts +12 -0
- package/src/primitives/wikidata-id.schema.test.ts +51 -0
- package/src/primitives/wikidata-id.schema.ts +16 -0
- package/src/time/README.md +220 -0
- package/src/time/boundary-enforcement.test.ts +130 -0
- package/src/time/boundary-enforcement.ts +59 -0
- package/src/time/bounded-time.schema.test.ts +294 -0
- package/src/time/bounded-time.schema.ts +111 -0
- package/src/time/flexible-time-parser.test.ts +586 -0
- package/src/time/flexible-time-parser.ts +122 -0
- package/src/time/flexible-time.schema.test.ts +243 -0
- package/src/time/flexible-time.schema.ts +43 -0
- package/src/time/is-relative-time.test.ts +23 -0
- package/src/time/is-relative-time.ts +9 -0
- package/src/time/iso8601.schema.ts +29 -0
- package/src/time/iso8601.types.test.ts +112 -0
- package/src/time/iso8601.types.ts +21 -0
- package/src/time/parse-relative-time.test.ts +49 -0
- package/src/time/parse-relative-time.ts +50 -0
- package/src/time/relative-time.schema.test.ts +23 -0
- package/src/time/relative-time.schema.ts +38 -0
- package/src/time/since-parameter.schema.test.ts +59 -0
- package/src/time/since-parameter.schema.ts +69 -0
- package/src/time/time-helpers.test.ts +263 -0
- package/src/time/time-helpers.ts +78 -0
- package/src/time/time-schemas.test.ts +181 -0
- package/src/time/time-schemas.ts +42 -0
- package/src/time/time.schema.test.ts +237 -0
- package/src/time/timezone-independence.test.ts +188 -0
- package/src/time/timezone.types.test.ts +55 -0
- package/src/time/timezone.types.ts +22 -0
- package/tsconfig.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# @schafevormfenster/rest-commons
|
|
2
|
+
|
|
3
|
+
> Centralized authority for REST API standards and schemas
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@schafevormfenster/rest-commons)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## What is this package?
|
|
9
|
+
|
|
10
|
+
**@schafevormfenster/rest-commons** is the central repository for REST API standards, schemas, and utilities used across all @schafevormfenster services. It provides a standardized foundation for building consistent, type-safe REST APIs with built-in validation, security, and best practices.
|
|
11
|
+
|
|
12
|
+
Think of it as the **"XSD for REST APIs"** - a single source of truth for API contracts, data structures, and validation rules.
|
|
13
|
+
|
|
14
|
+
## Why does this package exist?
|
|
15
|
+
|
|
16
|
+
### The Problem
|
|
17
|
+
|
|
18
|
+
Without centralized standards, REST APIs often suffer from:
|
|
19
|
+
|
|
20
|
+
- **Inconsistent response formats** across different endpoints
|
|
21
|
+
- **Duplicated validation logic** in multiple services
|
|
22
|
+
- **Type mismatches** between client and server
|
|
23
|
+
- **Security vulnerabilities** from inadequate input validation
|
|
24
|
+
- **Poor API documentation** due to lack of standard structures
|
|
25
|
+
- **Maintenance burden** when response formats need to change
|
|
26
|
+
|
|
27
|
+
### The Solution
|
|
28
|
+
|
|
29
|
+
This package provides:
|
|
30
|
+
|
|
31
|
+
1. **Standardized Response Schemas**: Consistent wrappers for all API responses (success, error, collections, health checks)
|
|
32
|
+
2. **Reusable Primitive Schemas**: Common data types (UUID, slug, location, timestamps) that work across all services
|
|
33
|
+
3. **Type-Safe Validation**: Runtime validation with Zod that automatically generates TypeScript types
|
|
34
|
+
4. **Security Utilities**: Input sanitization, suspicious pattern detection, and validation helpers
|
|
35
|
+
5. **Time Handling**: Robust ISO 8601 support, relative time parsing, and timezone handling
|
|
36
|
+
6. **Response Utilities**: Correlation IDs, standardized headers, and environment detection
|
|
37
|
+
|
|
38
|
+
## What problems does it solve?
|
|
39
|
+
|
|
40
|
+
### 1. Response Consistency
|
|
41
|
+
|
|
42
|
+
**Before**: Every service defines its own response format
|
|
43
|
+
```typescript
|
|
44
|
+
// Service A
|
|
45
|
+
{ data: {...}, success: true }
|
|
46
|
+
|
|
47
|
+
// Service B
|
|
48
|
+
{ result: {...}, status: "ok" }
|
|
49
|
+
|
|
50
|
+
// Service C
|
|
51
|
+
{ body: {...}, code: 200 }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**After**: All services use standard response schemas
|
|
55
|
+
```typescript
|
|
56
|
+
// All services
|
|
57
|
+
{
|
|
58
|
+
status: 200,
|
|
59
|
+
timestamp: "2024-01-15T10:30:00.000Z",
|
|
60
|
+
data: {...}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Type Safety
|
|
65
|
+
|
|
66
|
+
**Before**: Manual type definitions that can drift from runtime validation
|
|
67
|
+
```typescript
|
|
68
|
+
// Types might not match actual validation
|
|
69
|
+
type User = { id: string; name: string };
|
|
70
|
+
// Validation is separate and can diverge
|
|
71
|
+
const validateUser = (data: any) => { ... };
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**After**: Single source of truth with Zod
|
|
75
|
+
```typescript
|
|
76
|
+
// Schema and type are always in sync
|
|
77
|
+
export const UserSchema = z.object({
|
|
78
|
+
id: z.string().uuid(),
|
|
79
|
+
name: z.string().min(1),
|
|
80
|
+
});
|
|
81
|
+
export type User = z.infer<typeof UserSchema>;
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Code Reusability
|
|
85
|
+
|
|
86
|
+
**Before**: Every service implements its own validation
|
|
87
|
+
```typescript
|
|
88
|
+
// Service A
|
|
89
|
+
function validateUUID(id: string) { ... }
|
|
90
|
+
|
|
91
|
+
// Service B (duplicate implementation)
|
|
92
|
+
function validateUUID(id: string) { ... }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**After**: Import and reuse from commons
|
|
96
|
+
```typescript
|
|
97
|
+
import { UuidSchema } from "@schafevormfenster/rest-commons";
|
|
98
|
+
|
|
99
|
+
const validated = UuidSchema.parse(id);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 4. Security & Validation
|
|
103
|
+
|
|
104
|
+
**Before**: Inconsistent or missing security checks
|
|
105
|
+
```typescript
|
|
106
|
+
// Some services check for suspicious patterns, others don't
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**After**: Built-in security utilities
|
|
110
|
+
```typescript
|
|
111
|
+
import { detectSuspiciousPatterns } from "@schafevormfenster/rest-commons";
|
|
112
|
+
|
|
113
|
+
if (detectSuspiciousPatterns(userInput)) {
|
|
114
|
+
throw new ValidationError("Invalid input detected");
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 5. API Documentation
|
|
119
|
+
|
|
120
|
+
**Before**: Manual documentation that quickly becomes outdated
|
|
121
|
+
```markdown
|
|
122
|
+
## Response Format
|
|
123
|
+
Returns a JSON object with...
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**After**: Self-documenting schemas
|
|
127
|
+
```typescript
|
|
128
|
+
// Schema serves as executable documentation
|
|
129
|
+
export const MyResponseSchema = ResultSchema.extend({
|
|
130
|
+
data: MyDataSchema,
|
|
131
|
+
});
|
|
132
|
+
// Automatically generates OpenAPI spec, TypeScript types, and validation
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## When should you use this package?
|
|
136
|
+
|
|
137
|
+
Use **@schafevormfenster/rest-commons** when you:
|
|
138
|
+
|
|
139
|
+
- ✅ Build REST APIs in the @schafevormfenster ecosystem
|
|
140
|
+
- ✅ Need standardized response formats
|
|
141
|
+
- ✅ Want type-safe validation with Zod
|
|
142
|
+
- ✅ Require input sanitization and security checks
|
|
143
|
+
- ✅ Need to handle ISO 8601 timestamps or relative time
|
|
144
|
+
- ✅ Want consistent error handling across services
|
|
145
|
+
- ✅ Need correlation IDs for request tracing
|
|
146
|
+
|
|
147
|
+
Don't use this package if you:
|
|
148
|
+
|
|
149
|
+
- ❌ Build GraphQL APIs (use appropriate GraphQL schema tools)
|
|
150
|
+
- ❌ Work outside the @schafevormfenster ecosystem (fork and adapt instead)
|
|
151
|
+
- ❌ Need real-time WebSocket protocols (this is for REST only)
|
|
152
|
+
|
|
153
|
+
## What's included?
|
|
154
|
+
|
|
155
|
+
### Core Response Schemas
|
|
156
|
+
|
|
157
|
+
- **ResultSchema**: Single resource responses
|
|
158
|
+
- **ResultsSchema**: Collection responses
|
|
159
|
+
- **ErrorSchema**: Standardized error responses
|
|
160
|
+
- **HealthSchema**: Service health checks
|
|
161
|
+
- **OkaySchema**: Simple success acknowledgments
|
|
162
|
+
|
|
163
|
+
### Primitive Schemas
|
|
164
|
+
|
|
165
|
+
- **UuidSchema**: UUID validation
|
|
166
|
+
- **SlugSchema**: URL-safe slugs
|
|
167
|
+
- **LocationSchema**: Geographic locations
|
|
168
|
+
- **ISO8601Schema**: Timestamp validation
|
|
169
|
+
- **RelativeTimeSchema**: Relative time expressions
|
|
170
|
+
- And more...
|
|
171
|
+
|
|
172
|
+
### Utilities
|
|
173
|
+
|
|
174
|
+
- **Time Handling**: ISO 8601 parsing, relative time, week boundaries
|
|
175
|
+
- **Validation**: Suspicious pattern detection, parameter validation
|
|
176
|
+
- **Normalization**: List normalization, location normalization
|
|
177
|
+
- **Response Helpers**: Correlation IDs, header builders, environment detection
|
|
178
|
+
|
|
179
|
+
## Installation
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
pnpm add @schafevormfenster/rest-commons
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Quick Start
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import {
|
|
189
|
+
ResultSchema,
|
|
190
|
+
ErrorSchema,
|
|
191
|
+
UuidSchema,
|
|
192
|
+
detectSuspiciousPatterns,
|
|
193
|
+
getCorrelationId,
|
|
194
|
+
} from "@schafevormfenster/rest-commons";
|
|
195
|
+
|
|
196
|
+
// Define your data schema
|
|
197
|
+
const UserSchema = z.object({
|
|
198
|
+
id: UuidSchema,
|
|
199
|
+
name: z.string(),
|
|
200
|
+
email: z.string().email(),
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Create response schema
|
|
204
|
+
const UserResponseSchema = ResultSchema.extend({
|
|
205
|
+
data: UserSchema,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Use in your API route
|
|
209
|
+
export async function GET(request: Request) {
|
|
210
|
+
const correlationId = getCorrelationId(request);
|
|
211
|
+
|
|
212
|
+
// Your business logic here
|
|
213
|
+
const user = await fetchUser();
|
|
214
|
+
|
|
215
|
+
// Validate and return
|
|
216
|
+
const response = UserResponseSchema.parse({
|
|
217
|
+
status: 200,
|
|
218
|
+
timestamp: new Date().toISOString(),
|
|
219
|
+
data: user,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return Response.json(response);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Documentation
|
|
227
|
+
|
|
228
|
+
For detailed implementation guides and best practices, see:
|
|
229
|
+
|
|
230
|
+
- **[CONTRIBUTING.md](./CONTRIBUTING.md)** - How to use this package and develop REST endpoints
|
|
231
|
+
- **[REST Service Design Guide](../eslint-plugin/docs/rest-service-design-guide.md)** - Architectural patterns
|
|
232
|
+
- **[E2E Testing Guide](../eslint-plugin/docs/instructions/rest-api-e2e-testing-guide.md)** - Testing patterns
|
|
233
|
+
- **[Tech Stack](../eslint-plugin/docs/instructions/tech-stack.md)** - Technology choices
|
|
234
|
+
|
|
235
|
+
## Key Principles
|
|
236
|
+
|
|
237
|
+
This package embodies these principles:
|
|
238
|
+
|
|
239
|
+
1. **Contract-First Development**: Define schemas before implementation
|
|
240
|
+
2. **Type Safety**: Runtime validation generates compile-time types
|
|
241
|
+
3. **Consistency**: Standardized formats across all services
|
|
242
|
+
4. **Security**: Built-in input validation and sanitization
|
|
243
|
+
5. **Observability**: Correlation IDs and structured responses
|
|
244
|
+
6. **Developer Experience**: Self-documenting, autocomplete-friendly APIs
|
|
245
|
+
|
|
246
|
+
## Tech Stack
|
|
247
|
+
|
|
248
|
+
This package is built with:
|
|
249
|
+
|
|
250
|
+
- **Zod**: Schema validation and type inference
|
|
251
|
+
- **TypeScript**: Type-safe development
|
|
252
|
+
- **Vitest**: Unit testing
|
|
253
|
+
- **ESLint**: Code quality enforcement
|
|
254
|
+
|
|
255
|
+
## Contributing
|
|
256
|
+
|
|
257
|
+
This package is part of the @schafevormfenster monorepo. For contribution guidelines, see:
|
|
258
|
+
|
|
259
|
+
- [CONTRIBUTING.md](./CONTRIBUTING.md) - Development guide for this package
|
|
260
|
+
- Root monorepo CONTRIBUTING.md - General contribution guidelines
|
|
261
|
+
|
|
262
|
+
## Related Packages
|
|
263
|
+
|
|
264
|
+
- **@schafevormfenster/eslint-plugin**: Custom ESLint rules for REST APIs
|
|
265
|
+
- **@schafevormfenster/eslint-config**: ESLint configurations for the monorepo
|
|
266
|
+
- **@schafevormfenster/logging**: Structured logging utilities
|
|
267
|
+
- **@schafevormfenster/security**: Security helpers and utilities
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
See the root LICENSE file for license information.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
**Built with ❤️ by the Schafe vorm Fenster team**
|
package/bin/setup.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NPX script to sync coding instructions and update local Agent.md files
|
|
5
|
+
* Usage: npx @schafevormfenster/rest-commons setup
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
console.log('Setting up REST commons coding instructions...');
|
|
9
|
+
console.log('This script will be implemented to sync coding instructions to Agent.md files.');
|
|
10
|
+
console.log('Setup complete!');
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ApiErrorSchema: z.ZodObject<{
|
|
3
|
+
status: z.ZodNumber;
|
|
4
|
+
error: z.ZodString;
|
|
5
|
+
trace: z.ZodOptional<z.ZodAny>;
|
|
6
|
+
}, "strict", z.ZodTypeAny, {
|
|
7
|
+
status: number;
|
|
8
|
+
error: string;
|
|
9
|
+
trace?: any;
|
|
10
|
+
}, {
|
|
11
|
+
status: number;
|
|
12
|
+
error: string;
|
|
13
|
+
trace?: any;
|
|
14
|
+
}>;
|
|
15
|
+
export type ApiError = z.infer<typeof ApiErrorSchema>;
|
|
16
|
+
export declare class ApiErrorConstructor extends Error {
|
|
17
|
+
readonly status: number;
|
|
18
|
+
constructor(status: number, message: string);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=error.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.schema.d.ts","sourceRoot":"","sources":["../../src/api-schemas/error.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,cAAc;;;;;;;;;;;;EAMhB,CAAC;AAGZ,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAGtD,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const ApiErrorSchema = z
|
|
3
|
+
.object({
|
|
4
|
+
status: z.number().min(400).max(599),
|
|
5
|
+
error: z.string(),
|
|
6
|
+
trace: z.any().optional(),
|
|
7
|
+
})
|
|
8
|
+
.strict();
|
|
9
|
+
// Class for error handling with instanceof checks and throwing
|
|
10
|
+
export class ApiErrorConstructor extends Error {
|
|
11
|
+
status;
|
|
12
|
+
constructor(status, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.status = status;
|
|
15
|
+
this.name = "ApiError";
|
|
16
|
+
}
|
|
17
|
+
}
|