@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.
Files changed (2) hide show
  1. package/README.md +168 -9
  2. 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
- ## Authentication
88
+ ## Server Client
44
89
 
45
- ### JWT Token
90
+ For backend applications that need automatic OAuth token management:
46
91
 
47
92
  ```typescript
48
- const client = createSaferCityClient({
49
- baseUrl: 'https://api.safercity.com',
50
- token: jwtToken, // Your JWT token
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
- // Update token later
54
- client.setToken(newToken);
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
- ### OAuth Token Flow
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.0",
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": "workspace:*"
40
+ "@safercity/sdk-core": "^0.1.2"
46
41
  },
47
42
  "devDependencies": {
48
43
  "@hey-api/client-fetch": "^0.6.0",