@docyrus/docyrus 0.0.18 → 0.0.20

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 (52) hide show
  1. package/agent-loader.js +5 -2
  2. package/agent-loader.js.map +2 -2
  3. package/main.js +185 -31
  4. package/main.js.map +2 -2
  5. package/package.json +3 -3
  6. package/resources/pi-agent/prompts/coder-system.md +106 -0
  7. package/resources/pi-agent/skills/docyrus-platform/SKILL.md +71 -0
  8. package/resources/pi-agent/skills/docyrus-platform/references/ai-capabilities.md +43 -0
  9. package/resources/pi-agent/skills/docyrus-platform/references/auth-and-multi-tenancy.md +35 -0
  10. package/resources/pi-agent/skills/docyrus-platform/references/automation-and-workflows.md +30 -0
  11. package/resources/pi-agent/skills/docyrus-platform/references/core-building-blocks.md +53 -0
  12. package/resources/pi-agent/skills/{docyrus-api-dev → docyrus-platform}/references/data-source-query-guide.md +32 -28
  13. package/resources/pi-agent/skills/docyrus-platform/references/developer-tools.md +28 -0
  14. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +503 -0
  15. package/resources/pi-agent/skills/{docyrus-api-dev → docyrus-platform}/references/formula-design-guide-llm.md +15 -23
  16. package/resources/pi-agent/skills/docyrus-platform/references/integrations-and-events.md +60 -0
  17. package/resources/pi-agent/skills/docyrus-platform/references/platform-services.md +58 -0
  18. package/resources/pi-agent/skills/docyrus-platform/references/querying-and-data-operations.md +27 -0
  19. package/resources/pi-agent/prompts/coder-append-system.md +0 -19
  20. package/resources/pi-agent/skills/docyrus-ai/SKILL.md +0 -28
  21. package/resources/pi-agent/skills/docyrus-api-dev/SKILL.md +0 -161
  22. package/resources/pi-agent/skills/docyrus-api-dev/references/api-client.md +0 -349
  23. package/resources/pi-agent/skills/docyrus-api-dev/references/authentication.md +0 -238
  24. package/resources/pi-agent/skills/docyrus-api-dev/references/query-and-formulas.md +0 -592
  25. package/resources/pi-agent/skills/docyrus-api-doctor/SKILL.md +0 -70
  26. package/resources/pi-agent/skills/docyrus-api-doctor/references/checklist-details.md +0 -588
  27. package/resources/pi-agent/skills/docyrus-app-dev/SKILL.md +0 -159
  28. package/resources/pi-agent/skills/docyrus-app-dev/references/api-client-and-auth.md +0 -275
  29. package/resources/pi-agent/skills/docyrus-app-dev/references/collections-and-patterns.md +0 -352
  30. package/resources/pi-agent/skills/docyrus-app-dev/references/data-source-query-guide.md +0 -2059
  31. package/resources/pi-agent/skills/docyrus-app-dev/references/formula-design-guide-llm.md +0 -320
  32. package/resources/pi-agent/skills/docyrus-app-dev/references/query-guide.md +0 -525
  33. package/resources/pi-agent/skills/docyrus-app-ui-design/SKILL.md +0 -466
  34. package/resources/pi-agent/skills/docyrus-app-ui-design/references/component-selection-guide.md +0 -602
  35. package/resources/pi-agent/skills/docyrus-app-ui-design/references/icon-usage-guide.md +0 -463
  36. package/resources/pi-agent/skills/docyrus-app-ui-design/references/preferred-components-catalog.md +0 -242
  37. package/resources/pi-agent/skills/docyrus-apps/SKILL.md +0 -54
  38. package/resources/pi-agent/skills/docyrus-architect/SKILL.md +0 -174
  39. package/resources/pi-agent/skills/docyrus-architect/references/custom-query-guide.md +0 -410
  40. package/resources/pi-agent/skills/docyrus-architect/references/data-source-query-guide.md +0 -2059
  41. package/resources/pi-agent/skills/docyrus-architect/references/formula-design-guide-llm.md +0 -320
  42. package/resources/pi-agent/skills/docyrus-architect/references/formula-reference.md +0 -145
  43. package/resources/pi-agent/skills/docyrus-auth/SKILL.md +0 -100
  44. package/resources/pi-agent/skills/docyrus-cli-app/SKILL.md +0 -279
  45. package/resources/pi-agent/skills/docyrus-cli-app/references/cli-manifest.md +0 -532
  46. package/resources/pi-agent/skills/docyrus-cli-app/references/list-query-examples.md +0 -248
  47. package/resources/pi-agent/skills/docyrus-curl/SKILL.md +0 -32
  48. package/resources/pi-agent/skills/docyrus-discover/SKILL.md +0 -63
  49. package/resources/pi-agent/skills/docyrus-ds/SKILL.md +0 -95
  50. package/resources/pi-agent/skills/docyrus-env/SKILL.md +0 -21
  51. package/resources/pi-agent/skills/docyrus-studio/SKILL.md +0 -369
  52. package/resources/pi-agent/skills/docyrus-tui/SKILL.md +0 -15
@@ -0,0 +1,27 @@
1
+ # Querying & Data Operations
2
+
3
+ ## Record CRUD
4
+
5
+ - Create, read, update, delete individual records
6
+ - Bulk create, bulk update, bulk delete (batched for performance)
7
+ - Insert/update/delete with custom return value selection
8
+
9
+ ## Query Engine
10
+
11
+ Every list/get call accepts a structured query payload:
12
+
13
+ - **Column selection** — Pick specific fields, alias them, spread related data, apply functions
14
+ - **Filtering** — 50+ operators across comparison, text matching, date shortcuts (`today`, `this_week`, `last_30_days`), user-relative filters (`active_user`, `in_active_user_scope`), array containment, and null checks. Filter groups support AND/OR/NOT nesting
15
+ - **Sorting** — Multi-field, directional
16
+ - **Pagination** — Limit/offset with optional full count
17
+ - **Aggregations** — count, sum, avg, min, max with grouping
18
+ - **Formulas** — Virtual computed columns via JSONata expressions
19
+ - **Pivot** — Cross-tab matrix generation with date range series support
20
+ - **Child queries** — Fetch related records as nested JSON arrays in a single request
21
+ - **Expand** — Return full objects for relation and enum fields instead of IDs
22
+ - **Keyword search** — Full-text search across multiple fields
23
+
24
+ ## Detailed References
25
+
26
+ - For complete query payload reference with all parameters, operators, and examples, see [data-source-query-guide.md](data-source-query-guide.md).
27
+ - For block formula design (inline expressions and correlated subqueries), see [formula-design-guide-llm.md](formula-design-guide-llm.md).
@@ -1,19 +0,0 @@
1
- Docyrus is the primary domain for this session.
2
-
3
- Treat most user requests as Docyrus-related unless the prompt clearly says otherwise. When the task involves the Docyrus platform, prefer using the local `docyrus` CLI to inspect or mutate real state instead of guessing API details. Use `--json` whenever command output needs to be parsed or compared.
4
-
5
- When working on code:
6
-
7
- - Use the repository files and coding tools for implementation work.
8
- - Use the Docyrus CLI for platform state, tenant context, API discovery, schema inspection, and operational verification.
9
- - Respect the current Docyrus scope and auth context provided by the runtime skill.
10
- - Treat `.docyrus` and all auth material as sensitive.
11
-
12
- Useful Docyrus areas to reason about precisely:
13
-
14
- - auth accounts and tenant switching
15
- - apps
16
- - data sources and records
17
- - studio schema operations
18
- - discover/OpenAPI inspection
19
- - curl/raw API checks through the CLI
@@ -1,28 +0,0 @@
1
- ---
2
- name: docyrus-ai
3
- description: Chat with a Docyrus AI agent. Run `docyrus ai --help` for usage details.
4
- command: docyrus ai
5
- ---
6
-
7
- # docyrus ai
8
-
9
- Chat with a Docyrus AI agent
10
-
11
- ## Arguments
12
-
13
- | Name | Type | Required | Description |
14
- |------|------|----------|-------------|
15
- | `prompt` | `string` | yes | Prompt string; quote it when it contains spaces |
16
-
17
- ## Environment Variables
18
-
19
- | Name | Type | Required | Default | Description |
20
- |------|------|----------|---------|-------------|
21
- | `DOCYRUS_API_CLIENT_ID` | `string` | no | | Default Docyrus OAuth2 client id |
22
-
23
- ## Options
24
-
25
- | Flag | Type | Default | Description |
26
- |------|------|---------|-------------|
27
- | `--agentId` | `string` | | Agent ID; defaults to the Docyrus CLI agent |
28
- | `--deploymentId` | `string` | | Optional agent deployment ID |
@@ -1,161 +0,0 @@
1
- ---
2
- name: docyrus-api-dev
3
- description: Develop applications using the Docyrus API with @docyrus/api-client and @docyrus/signin libraries. Use when building apps that authenticate with Docyrus OAuth2 (PKCE, iframe, client credentials, device code), make REST API calls to Docyrus data source endpoints, or construct query payloads with filters, aggregations, formulas, pivots, and child queries. Triggers on tasks involving Docyrus API integration, @docyrus/api-client usage, @docyrus/signin authentication, data source query building, or Docyrus REST endpoint consumption.
4
- ---
5
-
6
- # Docyrus API Developer
7
-
8
- Integrate with the Docyrus API using `@docyrus/api-client` (REST client) and `@docyrus/signin` (React auth provider). Authenticate via OAuth2 PKCE, query data sources with powerful filtering/aggregation, and consume REST endpoints.
9
-
10
- ## Authentication Quick Start
11
-
12
- ### React Apps — Use @docyrus/signin
13
-
14
- ```tsx
15
- import { DocyrusAuthProvider, useDocyrusAuth, useDocyrusClient, SignInButton } from '@docyrus/signin'
16
-
17
- // 1. Wrap root
18
- <DocyrusAuthProvider
19
- apiUrl={import.meta.env.VITE_API_BASE_URL}
20
- clientId={import.meta.env.VITE_OAUTH2_CLIENT_ID}
21
- redirectUri={import.meta.env.VITE_OAUTH2_REDIRECT_URI}
22
- scopes={['offline_access', 'Read.All', 'DS.ReadWrite.All', 'Users.Read']}
23
- callbackPath="/auth/callback"
24
- >
25
- <App />
26
- </DocyrusAuthProvider>
27
-
28
- // 2. Use hooks
29
- function App() {
30
- const { status, signOut } = useDocyrusAuth()
31
- const client = useDocyrusClient() // RestApiClient | null
32
-
33
- if (status === 'loading') return <Spinner />
34
- if (status === 'unauthenticated') return <SignInButton />
35
-
36
- // client is ready — make API calls
37
- const user = await client!.get('/v1/users/me')
38
- }
39
- ```
40
-
41
- ### Non-React / Server — Use OAuth2Client Directly
42
-
43
- ```typescript
44
- import { RestApiClient, OAuth2Client, OAuth2TokenManagerAdapter, BrowserOAuth2TokenStorage } from '@docyrus/api-client'
45
-
46
- const tokenStorage = new BrowserOAuth2TokenStorage(localStorage)
47
- const oauth2 = new OAuth2Client({
48
- baseURL: 'https://api.docyrus.com',
49
- clientId: 'your-client-id',
50
- redirectUri: 'http://localhost:3000/callback',
51
- usePKCE: true,
52
- tokenStorage,
53
- })
54
-
55
- // Auth Code flow
56
- const { url } = await oauth2.getAuthorizationUrl({ scope: 'openid offline_access Users.Read' })
57
- window.location.href = url
58
- // After redirect:
59
- const tokens = await oauth2.handleCallback(window.location.href)
60
-
61
- // Create API client with auto-refresh
62
- const client = new RestApiClient({
63
- baseURL: 'https://api.docyrus.com',
64
- tokenManager: new OAuth2TokenManagerAdapter(tokenStorage, async () => {
65
- return (await oauth2.refreshAccessToken()).accessToken
66
- }),
67
- })
68
- ```
69
-
70
- ## API Endpoints
71
-
72
- ### Data Source Items (Dynamic per tenant)
73
- ```
74
- GET /v1/apps/{appSlug}/data-sources/{slug}/items — List with query payload
75
- GET /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Get one
76
- POST /v1/apps/{appSlug}/data-sources/{slug}/items — Create
77
- PATCH /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Update
78
- DELETE /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Delete one
79
- DELETE /v1/apps/{appSlug}/data-sources/{slug}/items — Delete many (body: { recordIds })
80
- ```
81
-
82
- Endpoints exist only if the data source is defined in the tenant. Check the tenant's OpenAPI spec at `GET /v1/api/openapi.json`.
83
-
84
- ### System Endpoints (Always Available)
85
- ```
86
- GET /v1/users — List users
87
- POST /v1/users — Create user
88
- GET /v1/users/me — Current user profile
89
- PATCH /v1/users/me — Update current user
90
- ```
91
-
92
- ### Making API Calls
93
-
94
- ```typescript
95
- // List items with query payload
96
- const items = await client.get('/v1/apps/base/data-sources/project/items', {
97
- columns: 'name, status, record_owner(firstname,lastname)',
98
- filters: { rules: [{ field: 'status', operator: '!=', value: 'archived' }] },
99
- orderBy: 'created_on DESC',
100
- limit: 50,
101
- })
102
-
103
- // Get single item
104
- const item = await client.get('/v1/apps/base/data-sources/project/items/uuid-here', {
105
- columns: 'name, description, status',
106
- })
107
-
108
- // Create
109
- const newItem = await client.post('/v1/apps/base/data-sources/project/items', {
110
- name: 'New Project',
111
- status: 'status-enum-id',
112
- })
113
-
114
- // Update
115
- await client.patch('/v1/apps/base/data-sources/project/items/uuid-here', {
116
- name: 'Updated Name',
117
- })
118
-
119
- // Delete
120
- await client.delete('/v1/apps/base/data-sources/project/items/uuid-here')
121
- ```
122
-
123
- ## Query Payload Summary
124
-
125
- The GET items endpoint accepts a powerful query payload:
126
-
127
- | Feature | Purpose |
128
- |---------|---------|
129
- | `columns` | Select fields, expand relations `field(subfields)`, alias `alias:field`, spread `...field()` |
130
- | `filters` | Nested AND/OR groups with 50+ operators (comparison, date shortcuts, user-related) |
131
- | `filterKeyword` | Full-text search across all searchable fields |
132
- | `orderBy` | Sort by fields with direction, including related fields |
133
- | `limit`/`offset` | Pagination (default limit: 100) |
134
- | `fullCount` | Return total matching count alongside results |
135
- | `calculations` | Aggregations: count, sum, avg, min, max with grouping |
136
- | `formulas` | Computed virtual columns (simple functions, block AST, correlated subqueries) |
137
- | `childQueries` | Fetch related child records as nested JSON arrays |
138
- | `pivot` | Cross-tab matrix queries with date range series |
139
- | `expand` | Return full objects for relation/user/enum fields instead of IDs |
140
-
141
- **For full query and formula references, read**:
142
- - `references/data-source-query-guide.md`
143
- - `references/formula-design-guide-llm.md`
144
-
145
- ## Critical Rules
146
-
147
- 1. **Always send `columns`** in list/get calls. Without it, only `id` is returned.
148
- 2. **Data source endpoints are dynamic** — they exist only for data sources defined in the tenant.
149
- 3. **Use `id` field** for `count` calculations. Use the actual field slug for `sum`, `avg`, `min`, `max`.
150
- 4. **Child query keys must appear in `columns`** — if childQuery key is `orders`, include `orders` in columns.
151
- 5. **Formula keys must appear in `columns`** — if formula key is `total`, include `total` in columns.
152
- 6. **Filter by related field** using `rel_{{relation_field}}/{{field}}` syntax.
153
-
154
- ## References
155
-
156
- Read these files when you need detailed information:
157
-
158
- - **`references/api-client.md`** — Full RestApiClient API, OAuth2Client (all flows: PKCE, client credentials, device code), token managers, interceptors, error classes, SSE/streaming, file upload/download, HTML to PDF, retry logic
159
- - **`references/authentication.md`** — @docyrus/signin React provider, useDocyrusAuth/useDocyrusClient hooks, SignInButton, standalone vs iframe auth modes, env vars, API client access pattern
160
- - **`references/data-source-query-guide.md`** — Up-to-date query payload guide: columns, filters, orderBy, pagination, calculations, formulas, child queries, pivots, and operator reference
161
- - **`references/formula-design-guide-llm.md`** — Up-to-date formula design guide for building and validating `formulas` payloads
@@ -1,349 +0,0 @@
1
- # @docyrus/api-client Reference
2
-
3
- ## Table of Contents
4
-
5
- 1. [RestApiClient](#restapiclient)
6
- 2. [HTTP Methods](#http-methods)
7
- 3. [Configuration](#configuration)
8
- 4. [Token Management](#token-management)
9
- 5. [OAuth2Client](#oauth2client)
10
- 6. [Interceptors](#interceptors)
11
- 7. [Error Handling](#error-handling)
12
- 8. [Streaming](#streaming)
13
- 9. [File Operations](#file-operations)
14
- 10. [Utilities](#utilities)
15
-
16
- ---
17
-
18
- ## RestApiClient
19
-
20
- ```typescript
21
- import { RestApiClient, MemoryTokenManager } from '@docyrus/api-client'
22
-
23
- const client = new RestApiClient({
24
- baseURL: 'https://api.docyrus.com',
25
- tokenManager: new MemoryTokenManager(),
26
- timeout: 5000,
27
- headers: { 'X-API-Version': '1.0' },
28
- })
29
- ```
30
-
31
- ---
32
-
33
- ## HTTP Methods
34
-
35
- ```typescript
36
- // GET with query params
37
- const users = await client.get<User[]>('/v1/users', { params: { page: 1, limit: 10 } })
38
-
39
- // POST with body
40
- const newUser = await client.post<User>('/v1/users', { name: 'John', email: 'john@example.com' })
41
-
42
- // PATCH (partial update)
43
- const updated = await client.patch<User>('/v1/users/123', { name: 'Jane' })
44
-
45
- // PUT (full replace)
46
- await client.put('/v1/users/123', { name: 'Jane', email: 'jane@example.com' })
47
-
48
- // DELETE
49
- await client.delete('/v1/users/123')
50
-
51
- // DELETE with body
52
- await client.delete('/v1/items', { recordIds: ['id1', 'id2'] })
53
- ```
54
-
55
- ### Typed Responses
56
-
57
- ```typescript
58
- interface ApiResponse<T> { data: T; meta: { page: number; total: number } }
59
- const response = await client.get<ApiResponse<User[]>>('/v1/users')
60
- const users: User[] = response.data.data
61
- ```
62
-
63
- ---
64
-
65
- ## Configuration
66
-
67
- ```typescript
68
- interface ApiClientConfig {
69
- baseURL?: string // Base URL for all requests
70
- tokenManager?: TokenManager // Token manager instance
71
- headers?: Record<string, string> // Default headers
72
- timeout?: number // Request timeout in ms
73
- fetch?: typeof fetch // Custom fetch implementation
74
- FormData?: typeof FormData // Custom FormData
75
- AbortController?: typeof AbortController
76
- storage?: Storage // Browser storage for persistence
77
- }
78
- ```
79
-
80
- ---
81
-
82
- ## Token Management
83
-
84
- ### MemoryTokenManager (default)
85
- ```typescript
86
- import { MemoryTokenManager } from '@docyrus/api-client'
87
- const tokenManager = new MemoryTokenManager()
88
- ```
89
-
90
- ### StorageTokenManager (persistent)
91
- ```typescript
92
- import { StorageTokenManager } from '@docyrus/api-client'
93
- const tokenManager = new StorageTokenManager(localStorage, 'auth_token')
94
- ```
95
-
96
- ### AsyncTokenManager (custom)
97
- ```typescript
98
- import { AsyncTokenManager } from '@docyrus/api-client'
99
- const tokenManager = new AsyncTokenManager({
100
- async getToken() { return await secureStorage.get('token') },
101
- async setToken(token) { await secureStorage.set('token', token) },
102
- async clearToken() { await secureStorage.remove('token') },
103
- })
104
- ```
105
-
106
- ### Set Token Directly
107
- ```typescript
108
- await client.setAccessToken('your-auth-token')
109
- ```
110
-
111
- ---
112
-
113
- ## OAuth2Client
114
-
115
- Full OAuth2 support with PKCE, Device Code, and Client Credentials flows.
116
-
117
- ### Setup
118
- ```typescript
119
- import { OAuth2Client, BrowserOAuth2TokenStorage } from '@docyrus/api-client'
120
-
121
- const oauth2 = new OAuth2Client({
122
- baseURL: 'https://api.docyrus.com',
123
- clientId: 'your-client-id',
124
- clientSecret: 'your-client-secret', // optional for public clients
125
- redirectUri: 'http://localhost:3000/callback',
126
- defaultScopes: ['openid', 'offline_access'],
127
- usePKCE: true, // default: true
128
- tokenStorage: new BrowserOAuth2TokenStorage(localStorage),
129
- })
130
- ```
131
-
132
- ### Authorization Code Flow (PKCE)
133
- ```typescript
134
- // Step 1: Generate auth URL
135
- const { url, state, codeVerifier } = await oauth2.getAuthorizationUrl({
136
- scope: 'openid offline_access Users.Read',
137
- })
138
-
139
- // Step 2: Redirect user
140
- window.location.href = url
141
-
142
- // Step 3: Handle callback
143
- const tokens = await oauth2.handleCallback(window.location.href)
144
- // tokens: { accessToken, refreshToken, ... }
145
- ```
146
-
147
- ### Client Credentials Flow (server-to-server)
148
- ```typescript
149
- const tokens = await oauth2.getClientCredentialsToken({
150
- scope: 'Read.All',
151
- delegatedUserId: 'user-id-to-impersonate',
152
- })
153
- ```
154
-
155
- ### Device Code Flow (CLI/headless)
156
- ```typescript
157
- const deviceAuth = await oauth2.startDeviceAuthorization('openid offline_access')
158
- console.log(`Go to: ${deviceAuth.verification_uri}`)
159
- console.log(`Enter code: ${deviceAuth.user_code}`)
160
-
161
- const tokens = await oauth2.pollDeviceAuthorization(
162
- deviceAuth.device_code, deviceAuth.interval, deviceAuth.expires_in,
163
- { onExpired: () => console.log('Code expired'), signal: abortController.signal },
164
- )
165
- ```
166
-
167
- ### Token Operations
168
- ```typescript
169
- const tokens = await oauth2.getTokens()
170
- const isExpired = await oauth2.isTokenExpired()
171
- const accessToken = await oauth2.getValidAccessToken() // auto-refreshes
172
- const newTokens = await oauth2.refreshAccessToken()
173
- await oauth2.revokeToken(tokens.refreshToken)
174
- const tokenInfo = await oauth2.introspectToken(tokens.accessToken)
175
- await oauth2.logout()
176
- ```
177
-
178
- ### Integrate OAuth2 with RestApiClient
179
- ```typescript
180
- import { RestApiClient, OAuth2Client, OAuth2TokenManagerAdapter, BrowserOAuth2TokenStorage } from '@docyrus/api-client'
181
-
182
- const tokenStorage = new BrowserOAuth2TokenStorage(localStorage)
183
- const oauth2 = new OAuth2Client({ baseURL: 'https://api.docyrus.com', clientId: 'id', tokenStorage })
184
-
185
- const tokenManager = new OAuth2TokenManagerAdapter(tokenStorage, async () => {
186
- const tokens = await oauth2.refreshAccessToken()
187
- return tokens.accessToken
188
- })
189
-
190
- const apiClient = new RestApiClient({ baseURL: 'https://api.docyrus.com', tokenManager })
191
- ```
192
-
193
- ### Rate Limit Check
194
- ```typescript
195
- const rateLimit = await oauth2.checkRateLimit()
196
- // { remaining, limit, reset }
197
- ```
198
-
199
- ### PKCE Utilities
200
- ```typescript
201
- import { generatePKCEChallenge, generateCodeVerifier, generateCodeChallenge, generateState, generateNonce } from '@docyrus/api-client'
202
-
203
- const pkce = await generatePKCEChallenge()
204
- // { codeVerifier, codeChallenge, codeChallengeMethod: 'S256' }
205
- ```
206
-
207
- ---
208
-
209
- ## Interceptors
210
-
211
- ```typescript
212
- client.use({
213
- // Transform outgoing requests
214
- async request(config) {
215
- config.headers = { ...config.headers, 'X-Request-Time': new Date().toISOString() }
216
- return config
217
- },
218
- // Transform incoming responses
219
- async response(response, request) {
220
- console.log(`${request.url} took ${Date.now() - request.timestamp}ms`)
221
- return response
222
- },
223
- // Handle errors globally
224
- async error(error, request, response) {
225
- if (error.status === 401) { await refreshToken() }
226
- return { error, request, response }
227
- },
228
- })
229
- ```
230
-
231
- ### Common Interceptor: Unwrap Response Data
232
- ```typescript
233
- client.use({
234
- response: (response) => {
235
- if (response.data?.data && typeof response.data === 'object' && !Array.isArray(response.data)) {
236
- response.data = response.data.data
237
- }
238
- return response
239
- },
240
- })
241
- ```
242
-
243
- ---
244
-
245
- ## Error Handling
246
-
247
- ```typescript
248
- import {
249
- ApiError, NetworkError, TimeoutError,
250
- AuthenticationError, // 401
251
- AuthorizationError, // 403
252
- NotFoundError, // 404
253
- RateLimitError, // 429 — has error.retryAfter
254
- ValidationError,
255
- // OAuth2-specific
256
- OAuth2Error, InvalidGrantError, InvalidClientError,
257
- AccessDeniedError, ExpiredTokenError, AuthorizationPendingError,
258
- } from '@docyrus/api-client'
259
-
260
- try {
261
- await client.get('/resource')
262
- } catch (error) {
263
- if (error instanceof AuthenticationError) { /* re-login */ }
264
- else if (error instanceof AuthorizationError) { /* forbidden */ }
265
- else if (error instanceof NotFoundError) { /* 404 */ }
266
- else if (error instanceof RateLimitError) { /* retry after error.retryAfter */ }
267
- else if (error instanceof NetworkError) { /* offline */ }
268
- else if (error instanceof TimeoutError) { /* timed out */ }
269
- }
270
- ```
271
-
272
- ---
273
-
274
- ## Streaming
275
-
276
- ### Server-Sent Events (SSE)
277
- ```typescript
278
- const eventSource = client.sse('/events', {
279
- onMessage(data) { console.log('Received:', data) },
280
- onError(error) { console.error(error) },
281
- onComplete() { console.log('Stream completed') },
282
- })
283
- eventSource.close()
284
- ```
285
-
286
- ### Chunked Streaming
287
- ```typescript
288
- for await (const chunk of client.stream('/stream', {
289
- method: 'POST',
290
- body: { query: 'stream data' },
291
- })) {
292
- console.log('Chunk:', chunk)
293
- }
294
- ```
295
-
296
- ---
297
-
298
- ## File Operations
299
-
300
- ### Upload
301
- ```typescript
302
- const formData = new FormData()
303
- formData.append('file', fileInput.files[0])
304
- formData.append('description', 'My file')
305
- await client.post('/upload', formData)
306
- ```
307
-
308
- ### Download
309
- ```typescript
310
- const response = await client.get('/download/file.pdf', { responseType: 'blob' })
311
- const url = URL.createObjectURL(response.data)
312
- const link = document.createElement('a')
313
- link.href = url
314
- link.download = 'file.pdf'
315
- link.click()
316
- ```
317
-
318
- ### HTML to PDF
319
- ```typescript
320
- await client.html2pdf({
321
- html: '<html><body>Content</body></html>',
322
- // or: url: 'https://example.com',
323
- options: { format: 'A4', margin: { top: 10, bottom: 10, left: 10, right: 10 }, landscape: false },
324
- })
325
- ```
326
-
327
- ### Custom Query/Report
328
- ```typescript
329
- const results = await client.runCustomQuery(customQueryId, options)
330
- // PUT reports/runCustomQuery/:customQueryId
331
- ```
332
-
333
- ---
334
-
335
- ## Utilities
336
-
337
- ```typescript
338
- import { buildUrl, isAbortError, parseContentDisposition, createAbortSignal, jsonToQueryString, withRetry } from '@docyrus/api-client'
339
-
340
- const url = buildUrl('/api/users', { page: 1, limit: 10 })
341
- // '/api/users?page=1&limit=10'
342
-
343
- const signal = createAbortSignal(5000) // 5s timeout
344
-
345
- const response = await withRetry(() => client.get('/flaky'), {
346
- retries: 3, retryDelay: 1000,
347
- retryCondition: (error) => error.status >= 500,
348
- })
349
- ```