@crossdelta/platform-sdk 0.11.2 → 0.12.0
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.
|
@@ -77,6 +77,56 @@ console.log(`Service running on http://localhost:${port}`)
|
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
80
|
+
## Environment Validation (Optional)
|
|
81
|
+
|
|
82
|
+
For services with required env vars, validate at startup with Zod:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// src/config/env.ts
|
|
86
|
+
import { z } from 'zod'
|
|
87
|
+
|
|
88
|
+
const envSchema = z.object({
|
|
89
|
+
PORT: z.string().transform(Number).default('8080'),
|
|
90
|
+
PUSHER_INSTANCE_ID: z.string().min(1),
|
|
91
|
+
PUSHER_SECRET_KEY: z.string().min(1),
|
|
92
|
+
NATS_URL: z.string().url().default('nats://localhost:4222'),
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
export type Env = z.infer<typeof envSchema>
|
|
96
|
+
|
|
97
|
+
// Validate at module load - crashes immediately if invalid
|
|
98
|
+
export const env = envSchema.parse(process.env)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
// src/index.ts
|
|
103
|
+
import '@crossdelta/telemetry'
|
|
104
|
+
import { Hono } from 'hono'
|
|
105
|
+
import { env } from './config/env'
|
|
106
|
+
|
|
107
|
+
const app = new Hono()
|
|
108
|
+
|
|
109
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
110
|
+
|
|
111
|
+
app.post('/notify', async (c) => {
|
|
112
|
+
const data = await c.req.json()
|
|
113
|
+
// Use validated env
|
|
114
|
+
await sendPush(env.PUSHER_INSTANCE_ID, env.PUSHER_SECRET_KEY, data)
|
|
115
|
+
return c.json({ success: true })
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
Bun.serve({ port: env.PORT, fetch: app.fetch })
|
|
119
|
+
console.log(`Service running on http://localhost:${env.PORT}`)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Benefits:**
|
|
123
|
+
- ✅ Fail-fast at startup (not at runtime)
|
|
124
|
+
- ✅ Type-safe env access (`env.PORT` is `number`)
|
|
125
|
+
- ✅ Clear error messages for missing vars
|
|
126
|
+
- ✅ Defaults for optional vars
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
80
130
|
## Rules
|
|
81
131
|
|
|
82
132
|
- ✅ `Bun.serve({ port, fetch: app.fetch })`
|
|
@@ -83,6 +83,58 @@ serve({ fetch: app.fetch, port }, (info) => {
|
|
|
83
83
|
|
|
84
84
|
---
|
|
85
85
|
|
|
86
|
+
## Environment Validation (Optional)
|
|
87
|
+
|
|
88
|
+
For services with required env vars, validate at startup with Zod:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
// src/config/env.ts
|
|
92
|
+
import { z } from 'zod'
|
|
93
|
+
|
|
94
|
+
const envSchema = z.object({
|
|
95
|
+
PORT: z.string().transform(Number).default('8080'),
|
|
96
|
+
PUSHER_INSTANCE_ID: z.string().min(1),
|
|
97
|
+
PUSHER_SECRET_KEY: z.string().min(1),
|
|
98
|
+
NATS_URL: z.string().url().default('nats://localhost:4222'),
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
export type Env = z.infer<typeof envSchema>
|
|
102
|
+
|
|
103
|
+
// Validate at module load - crashes immediately if invalid
|
|
104
|
+
export const env = envSchema.parse(process.env)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
// src/index.ts
|
|
109
|
+
import '@crossdelta/telemetry'
|
|
110
|
+
import { serve } from '@hono/node-server'
|
|
111
|
+
import { Hono } from 'hono'
|
|
112
|
+
import { env } from './config/env'
|
|
113
|
+
|
|
114
|
+
const app = new Hono()
|
|
115
|
+
|
|
116
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
117
|
+
|
|
118
|
+
app.post('/notify', async (c) => {
|
|
119
|
+
const data = await c.req.json()
|
|
120
|
+
// Use validated env
|
|
121
|
+
await sendPush(env.PUSHER_INSTANCE_ID, env.PUSHER_SECRET_KEY, data)
|
|
122
|
+
return c.json({ success: true })
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
serve({ fetch: app.fetch, port: env.PORT }, (info) => {
|
|
126
|
+
console.log(`Server running on http://localhost:${info.port}`)
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Benefits:**
|
|
131
|
+
- ✅ Fail-fast at startup (not at runtime)
|
|
132
|
+
- ✅ Type-safe env access (`env.PORT` is `number`)
|
|
133
|
+
- ✅ Clear error messages for missing vars
|
|
134
|
+
- ✅ Defaults for optional vars
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
86
138
|
## Rules
|
|
87
139
|
|
|
88
140
|
- ✅ `serve()` from `@hono/node-server`
|
|
@@ -22,9 +22,13 @@
|
|
|
22
22
|
import { z } from 'zod'
|
|
23
23
|
|
|
24
24
|
export const envSchema = z.object({
|
|
25
|
+
PORT: z.string().transform(Number).default('8080'),
|
|
25
26
|
PUSHER_INSTANCE_ID: z.string().min(1),
|
|
26
27
|
PUSHER_SECRET_KEY: z.string().min(1),
|
|
28
|
+
NATS_URL: z.string().url().default('nats://localhost:4222'),
|
|
27
29
|
})
|
|
30
|
+
|
|
31
|
+
export type Env = z.infer<typeof envSchema>
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
```ts
|
|
@@ -48,17 +52,26 @@ export class AppModule {}
|
|
|
48
52
|
// ✅ Service uses ConfigService - already validated at startup
|
|
49
53
|
import { Injectable } from '@nestjs/common'
|
|
50
54
|
import { ConfigService } from '@nestjs/config'
|
|
55
|
+
import type { Env } from './config/env.schema'
|
|
51
56
|
|
|
52
57
|
@Injectable()
|
|
53
58
|
export class MyService {
|
|
54
|
-
constructor(private config: ConfigService) {}
|
|
59
|
+
constructor(private config: ConfigService<Env, true>) {}
|
|
55
60
|
|
|
56
61
|
doSomething() {
|
|
57
|
-
const instanceId = this.config.
|
|
62
|
+
const instanceId = this.config.get('PUSHER_INSTANCE_ID') // Type-safe!
|
|
63
|
+
const port = this.config.get('PORT') // number (auto-transformed)
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
```
|
|
61
67
|
|
|
68
|
+
**Benefits:**
|
|
69
|
+
- ✅ Fail-fast at startup (not at runtime)
|
|
70
|
+
- ✅ Type-safe config access with `ConfigService<Env, true>`
|
|
71
|
+
- ✅ Clear error messages for missing vars
|
|
72
|
+
- ✅ Defaults for optional vars
|
|
73
|
+
- ✅ Auto-transform strings to numbers/booleans
|
|
74
|
+
|
|
62
75
|
---
|
|
63
76
|
|
|
64
77
|
## 🚨 CRITICAL: NestJS Structure (NO use-cases folder!)
|