@inneropen/marvin-sdk 2.0.0-next.13 → 2.0.0-next.15

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 CHANGED
@@ -24,37 +24,57 @@ The SDK provides:
24
24
  ## Installation
25
25
 
26
26
  ```bash
27
- # Copy into your project
28
- cp -r /path/to/marvin/packages/marvin-sdk src/lib/marvin
27
+ npm install @inneropen/marvin-sdk
29
28
  ```
30
29
 
31
- Or symlink for development:
30
+ ## Entry Points
32
31
 
33
- ```bash
34
- ln -s /path/to/marvin/packages/marvin-sdk src/lib/marvin
32
+ The SDK provides three distinct entry points for different use cases:
33
+
34
+ ### 📖 Publishing API (`/publish`)
35
+ Read-only access to published content (frontends, websites)
36
+ ```typescript
37
+ import { createMarvinClient } from '@inneropen/marvin-sdk/publish';
38
+ ```
39
+ **Auth:** Site client tokens (`MARVIN_SITE_CLIENT_TOKEN`)
40
+
41
+ ### ⚙️ Platform API (`/platform`)
42
+ Full CRUD admin operations (backend, CLI, automation)
43
+ ```typescript
44
+ import { createPlatformClient } from '@inneropen/marvin-sdk/platform';
45
+ ```
46
+ **Auth:** User tokens (`MARVIN_USER_TOKEN`) or session cookies
47
+
48
+ ### 🔐 Auth API (Default export)
49
+ Public registration, login, password reset
50
+ ```typescript
51
+ import { createAuthClient } from '@inneropen/marvin-sdk';
35
52
  ```
53
+ **Auth:** None required (public endpoints)
36
54
 
37
- ## Quick Start
55
+ 📚 **[See complete authentication guide →](./AUTHENTICATION.md)**
56
+
57
+ ## Quick Start - Publishing API
38
58
 
39
59
  ### 1. Configure Environment
40
60
 
41
61
  ```env
42
62
  MARVIN_API_URL=https://marvin.example.com
43
- MARVIN_SITE_CLIENT_TOKEN=your-token-here
63
+ MARVIN_SITE_CLIENT_TOKEN=your-site-client-token
44
64
  MARVIN_WORKSPACE_SLUG=your-workspace
45
65
  ```
46
66
 
47
67
  ### 2. Create Client
48
68
 
49
- ```ts
50
- import { createMarvinClient } from './marvin-sdk';
69
+ ```typescript
70
+ import { createMarvinClient } from '@inneropen/marvin-sdk/publish';
51
71
 
52
72
  const marvin = createMarvinClient();
53
73
  ```
54
74
 
55
75
  ### 3. Fetch Content
56
76
 
57
- ```ts
77
+ ```typescript
58
78
  // Get workspace
59
79
  const workspace = await marvin.getWorkspace();
60
80
  console.log(workspace.site?.title);
@@ -71,6 +91,35 @@ const projects = await marvin.collection('projects');
71
91
  const projectEntries = await projects.entries();
72
92
  ```
73
93
 
94
+ ## Quick Start - Platform API
95
+
96
+ ### Programmatic Admin Access
97
+
98
+ ```typescript
99
+ import { createPlatformClient } from '@inneropen/marvin-sdk/platform';
100
+
101
+ // From environment (MARVIN_USER_TOKEN)
102
+ const platform = createPlatformClient();
103
+
104
+ // Or explicit token
105
+ const platform = createPlatformClient({
106
+ userToken: 'your-user-token'
107
+ });
108
+
109
+ // Full CRUD operations
110
+ await platform.entries.create({
111
+ title: 'New Post',
112
+ content: 'Content here...',
113
+ collection_id: collectionId
114
+ });
115
+
116
+ await platform.entries.update(entryId, {
117
+ title: 'Updated Title'
118
+ });
119
+
120
+ await platform.entries.delete(entryId);
121
+ ```
122
+
74
123
  ## Architecture
75
124
 
76
125
  ### Workspace-First Design
@@ -33,11 +33,22 @@ declare class BearerTokenAuth implements AuthStrategy {
33
33
  /**
34
34
  * Session-based authentication (Platform/Admin APIs in browser)
35
35
  * Relies on HTTP-only cookies set by the server
36
+ * Optionally supports CSRF token protection
36
37
  */
37
38
  declare class SessionAuth implements AuthStrategy {
38
39
  private sessionToken?;
39
40
  private onUnauthorized?;
41
+ private csrfToken?;
40
42
  constructor(sessionToken?: string | undefined, onUnauthorized?: (() => Promise<void>) | undefined);
43
+ /**
44
+ * Set CSRF token for cross-site request forgery protection
45
+ * The token should be obtained from the server after login
46
+ */
47
+ setCsrfToken(token: string): void;
48
+ /**
49
+ * Get current CSRF token
50
+ */
51
+ getCsrfToken(): string | undefined;
41
52
  injectAuth(headers: Headers): void;
42
53
  handleUnauthorized(): Promise<void>;
43
54
  getDescription(): string;
@@ -54,6 +65,16 @@ declare class NoAuth implements AuthStrategy {
54
65
  * Base HTTP client for Marvin APIs
55
66
  */
56
67
 
68
+ interface RetryConfig {
69
+ /** Maximum number of retry attempts (default: 3) */
70
+ maxRetries: number;
71
+ /** Initial delay in ms before first retry (default: 1000) */
72
+ initialDelay: number;
73
+ /** Maximum delay in ms between retries (default: 10000) */
74
+ maxDelay: number;
75
+ /** HTTP status codes that should trigger a retry (default: [408, 429, 500, 502, 503, 504]) */
76
+ retryableStatuses: number[];
77
+ }
57
78
  interface HttpClientConfig {
58
79
  baseUrl: string;
59
80
  auth: AuthStrategy;
@@ -61,6 +82,7 @@ interface HttpClientConfig {
61
82
  credentials?: RequestCredentials;
62
83
  timeout?: number;
63
84
  debug?: boolean;
85
+ retry?: Partial<RetryConfig>;
64
86
  logger?: {
65
87
  log: (message: string, ...args: unknown[]) => void;
66
88
  warn: (message: string, ...args: unknown[]) => void;
@@ -74,8 +96,13 @@ declare class HttpClient {
74
96
  private credentials;
75
97
  private timeout;
76
98
  private debug;
99
+ private retryConfig;
77
100
  private logger;
78
101
  constructor(config: HttpClientConfig);
102
+ /**
103
+ * Validate path parameter to prevent path traversal attacks
104
+ */
105
+ validatePathParam(param: string | number, paramName?: string): string;
79
106
  /**
80
107
  * Build full URL from endpoint
81
108
  */
@@ -89,13 +116,25 @@ declare class HttpClient {
89
116
  */
90
117
  buildQueryString(params: Record<string, string | number | boolean | undefined>): string;
91
118
  /**
92
- * Perform HTTP request
119
+ * Sanitize data for logging by redacting sensitive fields
120
+ */
121
+ private sanitizeForLogging;
122
+ /**
123
+ * Calculate delay for retry with exponential backoff
124
+ */
125
+ private calculateRetryDelay;
126
+ /**
127
+ * Sleep for specified milliseconds
128
+ */
129
+ private sleep;
130
+ /**
131
+ * Perform HTTP request with automatic retry on transient failures
93
132
  */
94
133
  request<T>(method: string, endpoint: string, options?: {
95
134
  body?: unknown;
96
135
  headers?: Record<string, string>;
97
136
  params?: Record<string, string | number | boolean | undefined>;
98
- }): Promise<T>;
137
+ }, retryAttempt?: number): Promise<T>;
99
138
  /**
100
139
  * GET request
101
140
  */
@@ -33,11 +33,22 @@ declare class BearerTokenAuth implements AuthStrategy {
33
33
  /**
34
34
  * Session-based authentication (Platform/Admin APIs in browser)
35
35
  * Relies on HTTP-only cookies set by the server
36
+ * Optionally supports CSRF token protection
36
37
  */
37
38
  declare class SessionAuth implements AuthStrategy {
38
39
  private sessionToken?;
39
40
  private onUnauthorized?;
41
+ private csrfToken?;
40
42
  constructor(sessionToken?: string | undefined, onUnauthorized?: (() => Promise<void>) | undefined);
43
+ /**
44
+ * Set CSRF token for cross-site request forgery protection
45
+ * The token should be obtained from the server after login
46
+ */
47
+ setCsrfToken(token: string): void;
48
+ /**
49
+ * Get current CSRF token
50
+ */
51
+ getCsrfToken(): string | undefined;
41
52
  injectAuth(headers: Headers): void;
42
53
  handleUnauthorized(): Promise<void>;
43
54
  getDescription(): string;
@@ -54,6 +65,16 @@ declare class NoAuth implements AuthStrategy {
54
65
  * Base HTTP client for Marvin APIs
55
66
  */
56
67
 
68
+ interface RetryConfig {
69
+ /** Maximum number of retry attempts (default: 3) */
70
+ maxRetries: number;
71
+ /** Initial delay in ms before first retry (default: 1000) */
72
+ initialDelay: number;
73
+ /** Maximum delay in ms between retries (default: 10000) */
74
+ maxDelay: number;
75
+ /** HTTP status codes that should trigger a retry (default: [408, 429, 500, 502, 503, 504]) */
76
+ retryableStatuses: number[];
77
+ }
57
78
  interface HttpClientConfig {
58
79
  baseUrl: string;
59
80
  auth: AuthStrategy;
@@ -61,6 +82,7 @@ interface HttpClientConfig {
61
82
  credentials?: RequestCredentials;
62
83
  timeout?: number;
63
84
  debug?: boolean;
85
+ retry?: Partial<RetryConfig>;
64
86
  logger?: {
65
87
  log: (message: string, ...args: unknown[]) => void;
66
88
  warn: (message: string, ...args: unknown[]) => void;
@@ -74,8 +96,13 @@ declare class HttpClient {
74
96
  private credentials;
75
97
  private timeout;
76
98
  private debug;
99
+ private retryConfig;
77
100
  private logger;
78
101
  constructor(config: HttpClientConfig);
102
+ /**
103
+ * Validate path parameter to prevent path traversal attacks
104
+ */
105
+ validatePathParam(param: string | number, paramName?: string): string;
79
106
  /**
80
107
  * Build full URL from endpoint
81
108
  */
@@ -89,13 +116,25 @@ declare class HttpClient {
89
116
  */
90
117
  buildQueryString(params: Record<string, string | number | boolean | undefined>): string;
91
118
  /**
92
- * Perform HTTP request
119
+ * Sanitize data for logging by redacting sensitive fields
120
+ */
121
+ private sanitizeForLogging;
122
+ /**
123
+ * Calculate delay for retry with exponential backoff
124
+ */
125
+ private calculateRetryDelay;
126
+ /**
127
+ * Sleep for specified milliseconds
128
+ */
129
+ private sleep;
130
+ /**
131
+ * Perform HTTP request with automatic retry on transient failures
93
132
  */
94
133
  request<T>(method: string, endpoint: string, options?: {
95
134
  body?: unknown;
96
135
  headers?: Record<string, string>;
97
136
  params?: Record<string, string | number | boolean | undefined>;
98
- }): Promise<T>;
137
+ }, retryAttempt?: number): Promise<T>;
99
138
  /**
100
139
  * GET request
101
140
  */