@safercity/sdk 0.1.0 → 0.1.2
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/README.md +168 -9
- package/package.json +2 -7
package/README.md
CHANGED
|
@@ -12,6 +12,51 @@ bun add @safercity/sdk
|
|
|
12
12
|
yarn add @safercity/sdk
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Authentication Modes
|
|
16
|
+
|
|
17
|
+
The SDK supports three authentication modes for different deployment scenarios:
|
|
18
|
+
|
|
19
|
+
### Proxy Mode (Default - Most Secure)
|
|
20
|
+
|
|
21
|
+
Client -> Your Backend -> SaferCity API. Your backend adds tenant credentials, keeping secrets out of the client.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createSaferCityClient } from '@safercity/sdk';
|
|
25
|
+
|
|
26
|
+
// Client-side: requests go through your proxy
|
|
27
|
+
const client = createSaferCityClient({
|
|
28
|
+
baseUrl: '/api/safercity',
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Set up the proxy on your backend (see [Proxy Middleware](#proxy-middleware) below).
|
|
33
|
+
|
|
34
|
+
### Direct Mode
|
|
35
|
+
|
|
36
|
+
Client -> SaferCity API with an external user token. For white-label apps using external auth (Clerk, Auth0, better-auth).
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const client = createSaferCityClient({
|
|
40
|
+
baseUrl: 'https://api.safercity.com',
|
|
41
|
+
token: externalAuthToken,
|
|
42
|
+
tenantId: 'your-tenant-id',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Update token when it changes
|
|
46
|
+
client.setToken(newToken);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Cookie Mode
|
|
50
|
+
|
|
51
|
+
Browser with `credentials: include`. For first-party web apps using session cookies.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const client = createSaferCityClient({
|
|
55
|
+
baseUrl: 'https://api.safercity.com',
|
|
56
|
+
tenantId: 'your-tenant-id',
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
15
60
|
## Quick Start
|
|
16
61
|
|
|
17
62
|
```typescript
|
|
@@ -40,21 +85,116 @@ const { data: panic } = await client.panics.create({
|
|
|
40
85
|
console.log('Panic created:', panic.id);
|
|
41
86
|
```
|
|
42
87
|
|
|
43
|
-
##
|
|
88
|
+
## Server Client
|
|
44
89
|
|
|
45
|
-
|
|
90
|
+
For backend applications that need automatic OAuth token management:
|
|
46
91
|
|
|
47
92
|
```typescript
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
93
|
+
import { createServerClient } from '@safercity/sdk';
|
|
94
|
+
|
|
95
|
+
const client = createServerClient({
|
|
96
|
+
auth: {
|
|
97
|
+
clientId: process.env.SAFERCITY_CLIENT_ID!,
|
|
98
|
+
clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,
|
|
99
|
+
tenantId: 'tenant-123', // optional
|
|
100
|
+
},
|
|
101
|
+
baseUrl: 'https://api.safercity.com', // default
|
|
102
|
+
timeout: 30000,
|
|
51
103
|
});
|
|
52
104
|
|
|
53
|
-
//
|
|
54
|
-
|
|
105
|
+
// All requests are automatically authenticated with OAuth tokens
|
|
106
|
+
// Tokens are refreshed automatically before expiration
|
|
107
|
+
const users = await client.get('/v1/users');
|
|
108
|
+
|
|
109
|
+
// Manual token control
|
|
110
|
+
const token = await client.getAccessToken();
|
|
111
|
+
await client.refreshToken();
|
|
112
|
+
client.clearTokens();
|
|
55
113
|
```
|
|
56
114
|
|
|
57
|
-
###
|
|
115
|
+
### ServerClientConfig
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
interface ServerClientConfig {
|
|
119
|
+
baseUrl?: string; // default: "https://api.safercity.com"
|
|
120
|
+
auth: OAuthCredentials; // { clientId, clientSecret, tenantId? }
|
|
121
|
+
tokenStore?: TokenStorage; // custom token storage (default: in-memory)
|
|
122
|
+
timeout?: number; // default: 30000
|
|
123
|
+
fetch?: typeof fetch; // custom fetch implementation
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Proxy Middleware
|
|
128
|
+
|
|
129
|
+
Proxy middleware hides your SaferCity credentials from the client. The client sends requests to your backend, which forwards them to SaferCity with proper authentication.
|
|
130
|
+
|
|
131
|
+
### Next.js App Router
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// app/api/safercity/[...path]/route.ts
|
|
135
|
+
import { createNextHandler } from '@safercity/sdk';
|
|
136
|
+
|
|
137
|
+
const handler = createNextHandler({
|
|
138
|
+
clientId: process.env.SAFERCITY_CLIENT_ID!,
|
|
139
|
+
clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,
|
|
140
|
+
tenantId: 'tenant-123', // optional, can also come from request header
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export { handler as GET, handler as POST, handler as PUT, handler as DELETE, handler as PATCH };
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Express
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import express from 'express';
|
|
150
|
+
import { createExpressMiddleware } from '@safercity/sdk';
|
|
151
|
+
|
|
152
|
+
const app = express();
|
|
153
|
+
|
|
154
|
+
app.use(
|
|
155
|
+
'/api/safercity',
|
|
156
|
+
createExpressMiddleware({
|
|
157
|
+
clientId: process.env.SAFERCITY_CLIENT_ID!,
|
|
158
|
+
clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Generic Handler
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { createProxyHandler } from '@safercity/sdk';
|
|
167
|
+
|
|
168
|
+
const proxy = createProxyHandler({
|
|
169
|
+
clientId: process.env.SAFERCITY_CLIENT_ID!,
|
|
170
|
+
clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Use with any framework
|
|
174
|
+
const response = await proxy({
|
|
175
|
+
method: 'GET',
|
|
176
|
+
path: '/v1/users',
|
|
177
|
+
headers: {},
|
|
178
|
+
query: { limit: '10' },
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### ProxyConfig
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface ProxyConfig {
|
|
186
|
+
clientId: string;
|
|
187
|
+
clientSecret: string;
|
|
188
|
+
baseUrl?: string; // default: "https://api.safercity.com"
|
|
189
|
+
tenantId?: string; // optional, can be extracted from request
|
|
190
|
+
tokenStore?: TokenStorage; // custom token storage
|
|
191
|
+
pathPrefix?: string; // default: "/api/safercity"
|
|
192
|
+
forwardHeaders?: string[]; // default: ["content-type", "accept", "x-request-id"]
|
|
193
|
+
fetch?: typeof fetch;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## OAuth Token Flow
|
|
58
198
|
|
|
59
199
|
```typescript
|
|
60
200
|
const client = createSaferCityClient({
|
|
@@ -88,16 +228,29 @@ for await (const event of client.panics.streamUpdates('panic-123')) {
|
|
|
88
228
|
|
|
89
229
|
### Authentication
|
|
90
230
|
- `client.auth.whoami()` - Get current auth context
|
|
231
|
+
- `client.auth.check()` - Check if authenticated (optional auth)
|
|
232
|
+
|
|
233
|
+
### OAuth
|
|
91
234
|
- `client.oauth.token(body)` - Get access token
|
|
92
235
|
- `client.oauth.refresh(body)` - Refresh token
|
|
93
236
|
- `client.oauth.introspect(body)` - Introspect token
|
|
94
237
|
- `client.oauth.revoke(body)` - Revoke token
|
|
95
238
|
|
|
239
|
+
### Tenants
|
|
240
|
+
- `client.tenants.create(body)` - Create a new tenant
|
|
241
|
+
- `client.tenants.list(query?)` - List tenants
|
|
242
|
+
|
|
243
|
+
### Credentials
|
|
244
|
+
- `client.credentials.setup(body)` - Exchange setup token for credentials
|
|
245
|
+
- `client.credentials.list()` - List credentials
|
|
246
|
+
- `client.credentials.revoke(credentialId)` - Revoke credential
|
|
247
|
+
|
|
96
248
|
### Users
|
|
97
249
|
- `client.users.create(body)` - Create user
|
|
98
250
|
- `client.users.list(query?)` - List users
|
|
99
251
|
- `client.users.get(userId)` - Get user by ID
|
|
100
252
|
- `client.users.update(userId, body)` - Update user
|
|
253
|
+
- `client.users.updateStatus(userId, body)` - Update user status
|
|
101
254
|
- `client.users.delete(userId)` - Delete user
|
|
102
255
|
|
|
103
256
|
### Panics
|
|
@@ -106,7 +259,7 @@ for await (const event of client.panics.streamUpdates('panic-123')) {
|
|
|
106
259
|
- `client.panics.list(query?)` - List panics
|
|
107
260
|
- `client.panics.updateLocation(panicId, body)` - Update location
|
|
108
261
|
- `client.panics.cancel(panicId, body)` - Cancel panic
|
|
109
|
-
- `client.panics.streamUpdates(panicId)` - Stream updates (SSE)
|
|
262
|
+
- `client.panics.streamUpdates(panicId, options?)` - Stream updates (SSE)
|
|
110
263
|
|
|
111
264
|
### Subscriptions
|
|
112
265
|
- `client.subscriptions.listTypes()` - List subscription types
|
|
@@ -114,6 +267,12 @@ for await (const event of client.panics.streamUpdates('panic-123')) {
|
|
|
114
267
|
- `client.subscriptions.list(query?)` - List subscriptions
|
|
115
268
|
- `client.subscriptions.stats()` - Get stats
|
|
116
269
|
|
|
270
|
+
### Notifications
|
|
271
|
+
- `client.notifications.createSubscriber(body)` - Create subscriber
|
|
272
|
+
- `client.notifications.trigger(body)` - Trigger notification
|
|
273
|
+
- `client.notifications.getPreferences(userId)` - Get user preferences
|
|
274
|
+
- `client.notifications.updatePreferences(userId, body)` - Update preferences
|
|
275
|
+
|
|
117
276
|
### Location Safety
|
|
118
277
|
- `client.locationSafety.check(query)` - Check location safety
|
|
119
278
|
|
package/package.json
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@safercity/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Official SaferCity API client for TypeScript/JavaScript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SaferCity"
|
|
8
8
|
},
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "https://github.com/safercity/safercity-v2.git",
|
|
12
|
-
"directory": "packages/sdk/client"
|
|
13
|
-
},
|
|
14
9
|
"keywords": ["safercity", "api", "sdk", "typescript", "client"],
|
|
15
10
|
"sideEffects": false,
|
|
16
11
|
"type": "module",
|
|
@@ -42,7 +37,7 @@
|
|
|
42
37
|
"prepublishOnly": "bun run build"
|
|
43
38
|
},
|
|
44
39
|
"dependencies": {
|
|
45
|
-
"@safercity/sdk-core": "
|
|
40
|
+
"@safercity/sdk-core": "^0.1.2"
|
|
46
41
|
},
|
|
47
42
|
"devDependencies": {
|
|
48
43
|
"@hey-api/client-fetch": "^0.6.0",
|