@inneropen/marvin-sdk 2.0.0-next.11 → 2.0.0-next.12
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/dist/{HttpClient-CLtgQGXH.d.cts → HttpClient-BX5Gqd0w.d.cts} +8 -0
- package/dist/{HttpClient-CLtgQGXH.d.ts → HttpClient-BX5Gqd0w.d.ts} +8 -0
- package/dist/{chunk-25F3IF6S.js → chunk-QBHM2XNX.js} +78 -6
- package/dist/index.cjs +179 -17
- package/dist/index.d.cts +75 -9
- package/dist/index.d.ts +75 -9
- package/dist/index.js +107 -12
- package/dist/platform.cjs +80 -5
- package/dist/platform.d.cts +1 -1
- package/dist/platform.d.ts +1 -1
- package/dist/platform.js +1 -1
- package/package.json +1 -1
|
@@ -60,6 +60,12 @@ interface HttpClientConfig {
|
|
|
60
60
|
defaultHeaders?: Record<string, string>;
|
|
61
61
|
credentials?: RequestCredentials;
|
|
62
62
|
timeout?: number;
|
|
63
|
+
debug?: boolean;
|
|
64
|
+
logger?: {
|
|
65
|
+
log: (message: string, ...args: unknown[]) => void;
|
|
66
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
67
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
68
|
+
};
|
|
63
69
|
}
|
|
64
70
|
declare class HttpClient {
|
|
65
71
|
private baseUrl;
|
|
@@ -67,6 +73,8 @@ declare class HttpClient {
|
|
|
67
73
|
private defaultHeaders;
|
|
68
74
|
private credentials;
|
|
69
75
|
private timeout;
|
|
76
|
+
private debug;
|
|
77
|
+
private logger;
|
|
70
78
|
constructor(config: HttpClientConfig);
|
|
71
79
|
/**
|
|
72
80
|
* Build full URL from endpoint
|
|
@@ -60,6 +60,12 @@ interface HttpClientConfig {
|
|
|
60
60
|
defaultHeaders?: Record<string, string>;
|
|
61
61
|
credentials?: RequestCredentials;
|
|
62
62
|
timeout?: number;
|
|
63
|
+
debug?: boolean;
|
|
64
|
+
logger?: {
|
|
65
|
+
log: (message: string, ...args: unknown[]) => void;
|
|
66
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
67
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
68
|
+
};
|
|
63
69
|
}
|
|
64
70
|
declare class HttpClient {
|
|
65
71
|
private baseUrl;
|
|
@@ -67,6 +73,8 @@ declare class HttpClient {
|
|
|
67
73
|
private defaultHeaders;
|
|
68
74
|
private credentials;
|
|
69
75
|
private timeout;
|
|
76
|
+
private debug;
|
|
77
|
+
private logger;
|
|
70
78
|
constructor(config: HttpClientConfig);
|
|
71
79
|
/**
|
|
72
80
|
* Build full URL from endpoint
|
|
@@ -20,7 +20,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
21
|
|
|
22
22
|
// src/core/errors/MarvinError.ts
|
|
23
|
-
var MarvinError, MarvinApiError, MarvinAuthError, MarvinConfigError, MarvinValidationError;
|
|
23
|
+
var MarvinError, MarvinApiError, MarvinAuthError, MarvinConfigError, MarvinValidationError, MarvinNotFoundError, MarvinNetworkError, MarvinServerError;
|
|
24
24
|
var init_MarvinError = __esm({
|
|
25
25
|
"src/core/errors/MarvinError.ts"() {
|
|
26
26
|
"use strict";
|
|
@@ -76,6 +76,33 @@ ${body}` : ""}`;
|
|
|
76
76
|
}
|
|
77
77
|
field;
|
|
78
78
|
};
|
|
79
|
+
MarvinNotFoundError = class _MarvinNotFoundError extends MarvinError {
|
|
80
|
+
constructor(message, endpoint) {
|
|
81
|
+
super(message, "NOT_FOUND", 404);
|
|
82
|
+
this.endpoint = endpoint;
|
|
83
|
+
this.name = "MarvinNotFoundError";
|
|
84
|
+
Object.setPrototypeOf(this, _MarvinNotFoundError.prototype);
|
|
85
|
+
}
|
|
86
|
+
endpoint;
|
|
87
|
+
};
|
|
88
|
+
MarvinNetworkError = class _MarvinNetworkError extends MarvinError {
|
|
89
|
+
constructor(message, originalError) {
|
|
90
|
+
super(message, "NETWORK_ERROR");
|
|
91
|
+
this.originalError = originalError;
|
|
92
|
+
this.name = "MarvinNetworkError";
|
|
93
|
+
Object.setPrototypeOf(this, _MarvinNetworkError.prototype);
|
|
94
|
+
}
|
|
95
|
+
originalError;
|
|
96
|
+
};
|
|
97
|
+
MarvinServerError = class _MarvinServerError extends MarvinError {
|
|
98
|
+
constructor(message, statusCode, endpoint) {
|
|
99
|
+
super(message, "SERVER_ERROR", statusCode);
|
|
100
|
+
this.endpoint = endpoint;
|
|
101
|
+
this.name = "MarvinServerError";
|
|
102
|
+
Object.setPrototypeOf(this, _MarvinServerError.prototype);
|
|
103
|
+
}
|
|
104
|
+
endpoint;
|
|
105
|
+
};
|
|
79
106
|
}
|
|
80
107
|
});
|
|
81
108
|
|
|
@@ -99,12 +126,16 @@ var init_HttpClient = __esm({
|
|
|
99
126
|
defaultHeaders;
|
|
100
127
|
credentials;
|
|
101
128
|
timeout;
|
|
129
|
+
debug;
|
|
130
|
+
logger;
|
|
102
131
|
constructor(config) {
|
|
103
132
|
this.baseUrl = config.baseUrl;
|
|
104
133
|
this.auth = config.auth;
|
|
105
134
|
this.defaultHeaders = config.defaultHeaders || {};
|
|
106
135
|
this.credentials = config.credentials || "same-origin";
|
|
107
136
|
this.timeout = config.timeout || 3e4;
|
|
137
|
+
this.debug = config.debug ?? false;
|
|
138
|
+
this.logger = config.logger ?? console;
|
|
108
139
|
}
|
|
109
140
|
/**
|
|
110
141
|
* Build full URL from endpoint
|
|
@@ -146,6 +177,10 @@ var init_HttpClient = __esm({
|
|
|
146
177
|
const headers = this.buildHeaders(options?.headers, isFormData);
|
|
147
178
|
const controller = new AbortController();
|
|
148
179
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
180
|
+
const startTime = Date.now();
|
|
181
|
+
if (this.debug) {
|
|
182
|
+
this.logger.log(`[Marvin] ${method} ${url}`);
|
|
183
|
+
}
|
|
149
184
|
try {
|
|
150
185
|
const response = await fetch(url, {
|
|
151
186
|
method,
|
|
@@ -155,11 +190,42 @@ var init_HttpClient = __esm({
|
|
|
155
190
|
signal: controller.signal
|
|
156
191
|
});
|
|
157
192
|
clearTimeout(timeoutId);
|
|
193
|
+
const duration = Date.now() - startTime;
|
|
194
|
+
if (this.debug) {
|
|
195
|
+
this.logger.log(
|
|
196
|
+
`[Marvin] ${response.status} ${response.statusText} (${duration}ms)`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
158
199
|
if (response.status === 401 && this.auth.handleUnauthorized) {
|
|
159
200
|
await this.auth.handleUnauthorized();
|
|
160
201
|
}
|
|
161
202
|
if (!response.ok) {
|
|
162
203
|
const errorText = await response.text().catch(() => "");
|
|
204
|
+
if (this.debug) {
|
|
205
|
+
this.logger.error(
|
|
206
|
+
`[Marvin] Error response: ${response.status} ${response.statusText}`,
|
|
207
|
+
errorText ? `Body: ${errorText}` : ""
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (response.status === 404) {
|
|
211
|
+
throw new MarvinNotFoundError(
|
|
212
|
+
`Resource not found: ${endpoint}`,
|
|
213
|
+
endpoint
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (response.status === 401 || response.status === 403) {
|
|
217
|
+
throw new MarvinAuthError(
|
|
218
|
+
`Authentication failed: ${response.statusText}`,
|
|
219
|
+
response.status
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
if (response.status >= 500) {
|
|
223
|
+
throw new MarvinServerError(
|
|
224
|
+
`Server error: ${response.status} ${response.statusText}`,
|
|
225
|
+
response.status,
|
|
226
|
+
endpoint
|
|
227
|
+
);
|
|
228
|
+
}
|
|
163
229
|
throw MarvinApiError.fromResponse(
|
|
164
230
|
response.status,
|
|
165
231
|
response.statusText,
|
|
@@ -174,18 +240,20 @@ var init_HttpClient = __esm({
|
|
|
174
240
|
return await response.json();
|
|
175
241
|
} catch (error) {
|
|
176
242
|
clearTimeout(timeoutId);
|
|
177
|
-
if (error instanceof MarvinApiError) {
|
|
243
|
+
if (error instanceof MarvinApiError || error instanceof MarvinNotFoundError || error instanceof MarvinAuthError || error instanceof MarvinServerError) {
|
|
178
244
|
throw error;
|
|
179
245
|
}
|
|
180
246
|
if (error instanceof Error) {
|
|
181
247
|
if (error.name === "AbortError") {
|
|
182
|
-
throw new
|
|
248
|
+
throw new MarvinNetworkError(
|
|
183
249
|
`Request timeout after ${this.timeout}ms`,
|
|
184
|
-
|
|
185
|
-
endpoint
|
|
250
|
+
error
|
|
186
251
|
);
|
|
187
252
|
}
|
|
188
|
-
throw new
|
|
253
|
+
throw new MarvinNetworkError(
|
|
254
|
+
`Network error: ${error.message}`,
|
|
255
|
+
error
|
|
256
|
+
);
|
|
189
257
|
}
|
|
190
258
|
throw error;
|
|
191
259
|
}
|
|
@@ -382,6 +450,10 @@ export {
|
|
|
382
450
|
MarvinAuthError,
|
|
383
451
|
MarvinConfigError,
|
|
384
452
|
MarvinValidationError,
|
|
453
|
+
MarvinNotFoundError,
|
|
454
|
+
MarvinNetworkError,
|
|
455
|
+
MarvinServerError,
|
|
456
|
+
init_errors,
|
|
385
457
|
HttpClient,
|
|
386
458
|
BearerTokenAuth,
|
|
387
459
|
SessionAuth,
|
package/dist/index.cjs
CHANGED
|
@@ -27,14 +27,21 @@ __export(config_exports, {
|
|
|
27
27
|
validateConfig: () => validateConfig
|
|
28
28
|
});
|
|
29
29
|
function validateConfig(config) {
|
|
30
|
+
const receivedKeys = Object.keys(config).join(", ");
|
|
30
31
|
if (!config.apiUrl) {
|
|
31
|
-
throw new Error(
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Missing required config parameter 'apiUrl'. Received config keys: ${receivedKeys || "(none)"}. Set this to your MARVIN_API_URL environment variable value.`
|
|
34
|
+
);
|
|
32
35
|
}
|
|
33
36
|
if (!config.siteClientToken) {
|
|
34
|
-
throw new Error(
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Missing required config parameter 'siteClientToken'. Received config keys: ${receivedKeys}. Set this to your MARVIN_SITE_CLIENT_TOKEN environment variable value.`
|
|
39
|
+
);
|
|
35
40
|
}
|
|
36
41
|
if (!config.workspaceSlug) {
|
|
37
|
-
throw new Error(
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Missing required config parameter 'workspaceSlug'. Received config keys: ${receivedKeys}. Set this to your MARVIN_WORKSPACE_SLUG environment variable value.`
|
|
44
|
+
);
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
function createConfigFromEnv(overrides) {
|
|
@@ -43,8 +50,10 @@ function createConfigFromEnv(overrides) {
|
|
|
43
50
|
siteClientToken: overrides?.siteClientToken || process.env.MARVIN_SITE_CLIENT_TOKEN || "",
|
|
44
51
|
workspaceSlug: overrides?.workspaceSlug || process.env.MARVIN_WORKSPACE_SLUG || "",
|
|
45
52
|
autoInitialize: overrides?.autoInitialize ?? false,
|
|
46
|
-
cacheDuration: overrides?.cacheDuration ?? 5 * 60 * 1e3
|
|
53
|
+
cacheDuration: overrides?.cacheDuration ?? 5 * 60 * 1e3,
|
|
47
54
|
// 5 minutes
|
|
55
|
+
debug: overrides?.debug ?? process.env.MARVIN_DEBUG === "true",
|
|
56
|
+
logger: overrides?.logger ?? console
|
|
48
57
|
};
|
|
49
58
|
}
|
|
50
59
|
var init_config = __esm({
|
|
@@ -54,7 +63,7 @@ var init_config = __esm({
|
|
|
54
63
|
});
|
|
55
64
|
|
|
56
65
|
// src/core/errors/MarvinError.ts
|
|
57
|
-
var MarvinError, MarvinApiError, MarvinAuthError, MarvinConfigError, MarvinValidationError;
|
|
66
|
+
var MarvinError, MarvinApiError, MarvinAuthError, MarvinConfigError, MarvinValidationError, MarvinNotFoundError, MarvinNetworkError, MarvinServerError;
|
|
58
67
|
var init_MarvinError = __esm({
|
|
59
68
|
"src/core/errors/MarvinError.ts"() {
|
|
60
69
|
"use strict";
|
|
@@ -110,6 +119,33 @@ ${body}` : ""}`;
|
|
|
110
119
|
}
|
|
111
120
|
field;
|
|
112
121
|
};
|
|
122
|
+
MarvinNotFoundError = class _MarvinNotFoundError extends MarvinError {
|
|
123
|
+
constructor(message, endpoint) {
|
|
124
|
+
super(message, "NOT_FOUND", 404);
|
|
125
|
+
this.endpoint = endpoint;
|
|
126
|
+
this.name = "MarvinNotFoundError";
|
|
127
|
+
Object.setPrototypeOf(this, _MarvinNotFoundError.prototype);
|
|
128
|
+
}
|
|
129
|
+
endpoint;
|
|
130
|
+
};
|
|
131
|
+
MarvinNetworkError = class _MarvinNetworkError extends MarvinError {
|
|
132
|
+
constructor(message, originalError) {
|
|
133
|
+
super(message, "NETWORK_ERROR");
|
|
134
|
+
this.originalError = originalError;
|
|
135
|
+
this.name = "MarvinNetworkError";
|
|
136
|
+
Object.setPrototypeOf(this, _MarvinNetworkError.prototype);
|
|
137
|
+
}
|
|
138
|
+
originalError;
|
|
139
|
+
};
|
|
140
|
+
MarvinServerError = class _MarvinServerError extends MarvinError {
|
|
141
|
+
constructor(message, statusCode, endpoint) {
|
|
142
|
+
super(message, "SERVER_ERROR", statusCode);
|
|
143
|
+
this.endpoint = endpoint;
|
|
144
|
+
this.name = "MarvinServerError";
|
|
145
|
+
Object.setPrototypeOf(this, _MarvinServerError.prototype);
|
|
146
|
+
}
|
|
147
|
+
endpoint;
|
|
148
|
+
};
|
|
113
149
|
}
|
|
114
150
|
});
|
|
115
151
|
|
|
@@ -133,12 +169,16 @@ var init_HttpClient = __esm({
|
|
|
133
169
|
defaultHeaders;
|
|
134
170
|
credentials;
|
|
135
171
|
timeout;
|
|
172
|
+
debug;
|
|
173
|
+
logger;
|
|
136
174
|
constructor(config) {
|
|
137
175
|
this.baseUrl = config.baseUrl;
|
|
138
176
|
this.auth = config.auth;
|
|
139
177
|
this.defaultHeaders = config.defaultHeaders || {};
|
|
140
178
|
this.credentials = config.credentials || "same-origin";
|
|
141
179
|
this.timeout = config.timeout || 3e4;
|
|
180
|
+
this.debug = config.debug ?? false;
|
|
181
|
+
this.logger = config.logger ?? console;
|
|
142
182
|
}
|
|
143
183
|
/**
|
|
144
184
|
* Build full URL from endpoint
|
|
@@ -180,6 +220,10 @@ var init_HttpClient = __esm({
|
|
|
180
220
|
const headers = this.buildHeaders(options?.headers, isFormData);
|
|
181
221
|
const controller = new AbortController();
|
|
182
222
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
223
|
+
const startTime = Date.now();
|
|
224
|
+
if (this.debug) {
|
|
225
|
+
this.logger.log(`[Marvin] ${method} ${url}`);
|
|
226
|
+
}
|
|
183
227
|
try {
|
|
184
228
|
const response = await fetch(url, {
|
|
185
229
|
method,
|
|
@@ -189,11 +233,42 @@ var init_HttpClient = __esm({
|
|
|
189
233
|
signal: controller.signal
|
|
190
234
|
});
|
|
191
235
|
clearTimeout(timeoutId);
|
|
236
|
+
const duration = Date.now() - startTime;
|
|
237
|
+
if (this.debug) {
|
|
238
|
+
this.logger.log(
|
|
239
|
+
`[Marvin] ${response.status} ${response.statusText} (${duration}ms)`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
192
242
|
if (response.status === 401 && this.auth.handleUnauthorized) {
|
|
193
243
|
await this.auth.handleUnauthorized();
|
|
194
244
|
}
|
|
195
245
|
if (!response.ok) {
|
|
196
246
|
const errorText = await response.text().catch(() => "");
|
|
247
|
+
if (this.debug) {
|
|
248
|
+
this.logger.error(
|
|
249
|
+
`[Marvin] Error response: ${response.status} ${response.statusText}`,
|
|
250
|
+
errorText ? `Body: ${errorText}` : ""
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
if (response.status === 404) {
|
|
254
|
+
throw new MarvinNotFoundError(
|
|
255
|
+
`Resource not found: ${endpoint}`,
|
|
256
|
+
endpoint
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
if (response.status === 401 || response.status === 403) {
|
|
260
|
+
throw new MarvinAuthError(
|
|
261
|
+
`Authentication failed: ${response.statusText}`,
|
|
262
|
+
response.status
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
if (response.status >= 500) {
|
|
266
|
+
throw new MarvinServerError(
|
|
267
|
+
`Server error: ${response.status} ${response.statusText}`,
|
|
268
|
+
response.status,
|
|
269
|
+
endpoint
|
|
270
|
+
);
|
|
271
|
+
}
|
|
197
272
|
throw MarvinApiError.fromResponse(
|
|
198
273
|
response.status,
|
|
199
274
|
response.statusText,
|
|
@@ -208,18 +283,20 @@ var init_HttpClient = __esm({
|
|
|
208
283
|
return await response.json();
|
|
209
284
|
} catch (error) {
|
|
210
285
|
clearTimeout(timeoutId);
|
|
211
|
-
if (error instanceof MarvinApiError) {
|
|
286
|
+
if (error instanceof MarvinApiError || error instanceof MarvinNotFoundError || error instanceof MarvinAuthError || error instanceof MarvinServerError) {
|
|
212
287
|
throw error;
|
|
213
288
|
}
|
|
214
289
|
if (error instanceof Error) {
|
|
215
290
|
if (error.name === "AbortError") {
|
|
216
|
-
throw new
|
|
291
|
+
throw new MarvinNetworkError(
|
|
217
292
|
`Request timeout after ${this.timeout}ms`,
|
|
218
|
-
|
|
219
|
-
endpoint
|
|
293
|
+
error
|
|
220
294
|
);
|
|
221
295
|
}
|
|
222
|
-
throw new
|
|
296
|
+
throw new MarvinNetworkError(
|
|
297
|
+
`Network error: ${error.message}`,
|
|
298
|
+
error
|
|
299
|
+
);
|
|
223
300
|
}
|
|
224
301
|
throw error;
|
|
225
302
|
}
|
|
@@ -418,7 +495,9 @@ var init_http2 = __esm({
|
|
|
418
495
|
super({
|
|
419
496
|
baseUrl: config.apiUrl,
|
|
420
497
|
auth: new BearerTokenAuth(config.siteClientToken),
|
|
421
|
-
credentials: "same-origin"
|
|
498
|
+
credentials: "same-origin",
|
|
499
|
+
debug: config.debug,
|
|
500
|
+
logger: config.logger
|
|
422
501
|
});
|
|
423
502
|
}
|
|
424
503
|
/**
|
|
@@ -555,6 +634,7 @@ var init_entries = __esm({
|
|
|
555
634
|
"src/entries/entries.ts"() {
|
|
556
635
|
"use strict";
|
|
557
636
|
init_entry();
|
|
637
|
+
init_errors();
|
|
558
638
|
EntriesModule = class {
|
|
559
639
|
constructor(http, workspaceSlug) {
|
|
560
640
|
this.http = http;
|
|
@@ -579,11 +659,19 @@ var init_entries = __esm({
|
|
|
579
659
|
}
|
|
580
660
|
/**
|
|
581
661
|
* Get a single entry by slug
|
|
662
|
+
* Returns null if entry is not found (404)
|
|
582
663
|
*/
|
|
583
664
|
async get(slug) {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
665
|
+
try {
|
|
666
|
+
const endpoint = `/api/publish/${this.workspaceSlug}/entries/${slug}`;
|
|
667
|
+
const data = await this.http.fetch(endpoint);
|
|
668
|
+
return new Entry(data, this.http, this.workspaceSlug);
|
|
669
|
+
} catch (error) {
|
|
670
|
+
if (error instanceof MarvinNotFoundError) {
|
|
671
|
+
return null;
|
|
672
|
+
}
|
|
673
|
+
throw error;
|
|
674
|
+
}
|
|
587
675
|
}
|
|
588
676
|
/**
|
|
589
677
|
* Convenience: Get all pages
|
|
@@ -689,6 +777,7 @@ var init_collections = __esm({
|
|
|
689
777
|
"src/collections/collections.ts"() {
|
|
690
778
|
"use strict";
|
|
691
779
|
init_collection();
|
|
780
|
+
init_errors();
|
|
692
781
|
CollectionsModule = class {
|
|
693
782
|
constructor(http, workspaceSlug) {
|
|
694
783
|
this.http = http;
|
|
@@ -706,19 +795,63 @@ var init_collections = __esm({
|
|
|
706
795
|
}
|
|
707
796
|
/**
|
|
708
797
|
* Get a single collection by slug
|
|
798
|
+
* Returns null if collection is not found (404)
|
|
709
799
|
*/
|
|
710
800
|
async get(slug) {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
801
|
+
try {
|
|
802
|
+
const endpoint = `/api/publish/${this.workspaceSlug}/collections/${slug}`;
|
|
803
|
+
const data = await this.http.fetch(endpoint);
|
|
804
|
+
return new Collection(data, this.http, this.workspaceSlug);
|
|
805
|
+
} catch (error) {
|
|
806
|
+
if (error instanceof MarvinNotFoundError) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
throw error;
|
|
810
|
+
}
|
|
714
811
|
}
|
|
715
812
|
/**
|
|
716
813
|
* Get entries in a collection
|
|
814
|
+
* Returns empty array if collection is not found
|
|
717
815
|
*/
|
|
718
816
|
async entries(slug) {
|
|
719
817
|
const collection = await this.get(slug);
|
|
818
|
+
if (!collection) {
|
|
819
|
+
return [];
|
|
820
|
+
}
|
|
720
821
|
return collection.entries();
|
|
721
822
|
}
|
|
823
|
+
/**
|
|
824
|
+
* Try multiple collection slugs in fallback order
|
|
825
|
+
* Returns the first collection that exists and has entries
|
|
826
|
+
*
|
|
827
|
+
* @param slugs - Collection slugs to try in order
|
|
828
|
+
* @param options - Options for fallback behavior
|
|
829
|
+
* @returns Entries from the first matching collection, or empty array
|
|
830
|
+
*
|
|
831
|
+
* @example
|
|
832
|
+
* ```ts
|
|
833
|
+
* // Try bench-notes, then journal, then blog
|
|
834
|
+
* const entries = await collections.fallback(['bench-notes', 'journal', 'blog']);
|
|
835
|
+
* ```
|
|
836
|
+
*/
|
|
837
|
+
async fallback(slugs, options = {}) {
|
|
838
|
+
const { requireEntries = true } = options;
|
|
839
|
+
for (const slug of slugs) {
|
|
840
|
+
try {
|
|
841
|
+
const collection = await this.get(slug);
|
|
842
|
+
if (!collection) {
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
const entries = await collection.entries();
|
|
846
|
+
if (!requireEntries || entries.length > 0) {
|
|
847
|
+
return entries;
|
|
848
|
+
}
|
|
849
|
+
} catch (error) {
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
return [];
|
|
854
|
+
}
|
|
722
855
|
};
|
|
723
856
|
}
|
|
724
857
|
});
|
|
@@ -1081,6 +1214,23 @@ var init_marvin = __esm({
|
|
|
1081
1214
|
async resource(slug) {
|
|
1082
1215
|
return this.workspace.resources.get(slug);
|
|
1083
1216
|
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Try multiple collection slugs in fallback order
|
|
1219
|
+
* Returns entries from the first collection that exists and has content
|
|
1220
|
+
*
|
|
1221
|
+
* @param slugs - Collection slugs to try in order
|
|
1222
|
+
* @param options - Options for fallback behavior
|
|
1223
|
+
* @returns Entries from the first matching collection, or empty array
|
|
1224
|
+
*
|
|
1225
|
+
* @example
|
|
1226
|
+
* ```ts
|
|
1227
|
+
* // Try bench-notes, then journal, then blog
|
|
1228
|
+
* const entries = await client.collectionFallback(['bench-notes', 'journal', 'blog']);
|
|
1229
|
+
* ```
|
|
1230
|
+
*/
|
|
1231
|
+
async collectionFallback(slugs, options) {
|
|
1232
|
+
return this.workspace.collections.fallback(slugs, options);
|
|
1233
|
+
}
|
|
1084
1234
|
// ======================
|
|
1085
1235
|
// Backwards-Compatible Publishing API
|
|
1086
1236
|
// ======================
|
|
@@ -1104,6 +1254,9 @@ var init_marvin = __esm({
|
|
|
1104
1254
|
*/
|
|
1105
1255
|
async getEntry(slug) {
|
|
1106
1256
|
const entry = await this.workspace.entries.get(slug);
|
|
1257
|
+
if (!entry) {
|
|
1258
|
+
return null;
|
|
1259
|
+
}
|
|
1107
1260
|
return entry.toJSON();
|
|
1108
1261
|
}
|
|
1109
1262
|
/**
|
|
@@ -1119,6 +1272,9 @@ var init_marvin = __esm({
|
|
|
1119
1272
|
*/
|
|
1120
1273
|
async getCollection(slug) {
|
|
1121
1274
|
const collection = await this.workspace.collections.get(slug);
|
|
1275
|
+
if (!collection) {
|
|
1276
|
+
return null;
|
|
1277
|
+
}
|
|
1122
1278
|
return collection.toJSON();
|
|
1123
1279
|
}
|
|
1124
1280
|
/**
|
|
@@ -1175,6 +1331,9 @@ __export(index_exports, {
|
|
|
1175
1331
|
MarvinClient: () => MarvinClient,
|
|
1176
1332
|
MarvinConfigError: () => MarvinConfigError,
|
|
1177
1333
|
MarvinError: () => MarvinError,
|
|
1334
|
+
MarvinNetworkError: () => MarvinNetworkError,
|
|
1335
|
+
MarvinNotFoundError: () => MarvinNotFoundError,
|
|
1336
|
+
MarvinServerError: () => MarvinServerError,
|
|
1178
1337
|
MarvinValidationError: () => MarvinValidationError,
|
|
1179
1338
|
NoAuth: () => NoAuth,
|
|
1180
1339
|
Resource: () => Resource,
|
|
@@ -1271,6 +1430,9 @@ function createMarvinClient(config) {
|
|
|
1271
1430
|
MarvinClient,
|
|
1272
1431
|
MarvinConfigError,
|
|
1273
1432
|
MarvinError,
|
|
1433
|
+
MarvinNetworkError,
|
|
1434
|
+
MarvinNotFoundError,
|
|
1435
|
+
MarvinServerError,
|
|
1274
1436
|
MarvinValidationError,
|
|
1275
1437
|
NoAuth,
|
|
1276
1438
|
Resource,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MarvinResource, MarvinEntry, MarvinAsset, MarvinCollection, MarvinEntryType, MarvinSite, GetResourcesOptions as GetResourcesOptions$1 } from './types/index.cjs';
|
|
2
2
|
export { GetAssetsOptions, GetEntriesOptions, MarvinPublishResponse } from './types/index.cjs';
|
|
3
|
-
import { H as HttpClient } from './HttpClient-
|
|
4
|
-
export { A as AuthStrategy, B as BearerTokenAuth, a as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-
|
|
3
|
+
import { H as HttpClient } from './HttpClient-BX5Gqd0w.cjs';
|
|
4
|
+
export { A as AuthStrategy, B as BearerTokenAuth, a as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-BX5Gqd0w.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Marvin SDK Configuration
|
|
@@ -14,6 +14,14 @@ interface MarvinConfig {
|
|
|
14
14
|
autoInitialize?: boolean;
|
|
15
15
|
/** Cache duration in milliseconds (default: 5 minutes) */
|
|
16
16
|
cacheDuration?: number;
|
|
17
|
+
/** Enable debug logging for HTTP requests and responses */
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
/** Custom logger function (defaults to console) */
|
|
20
|
+
logger?: {
|
|
21
|
+
log: (message: string, ...args: unknown[]) => void;
|
|
22
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
23
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
24
|
+
};
|
|
17
25
|
}
|
|
18
26
|
declare function createConfigFromEnv(overrides?: Partial<MarvinConfig>): MarvinConfig;
|
|
19
27
|
|
|
@@ -54,6 +62,27 @@ declare class MarvinValidationError extends MarvinError {
|
|
|
54
62
|
readonly field?: string | undefined;
|
|
55
63
|
constructor(message: string, field?: string | undefined);
|
|
56
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Resource not found errors (404)
|
|
67
|
+
*/
|
|
68
|
+
declare class MarvinNotFoundError extends MarvinError {
|
|
69
|
+
readonly endpoint: string;
|
|
70
|
+
constructor(message: string, endpoint: string);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Network/connectivity errors
|
|
74
|
+
*/
|
|
75
|
+
declare class MarvinNetworkError extends MarvinError {
|
|
76
|
+
readonly originalError?: Error | undefined;
|
|
77
|
+
constructor(message: string, originalError?: Error | undefined);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Server errors (5xx)
|
|
81
|
+
*/
|
|
82
|
+
declare class MarvinServerError extends MarvinError {
|
|
83
|
+
readonly endpoint: string;
|
|
84
|
+
constructor(message: string, statusCode: number, endpoint: string);
|
|
85
|
+
}
|
|
57
86
|
|
|
58
87
|
/**
|
|
59
88
|
* Pagination response types and helpers
|
|
@@ -270,12 +299,31 @@ declare class CollectionsModule {
|
|
|
270
299
|
list(): Promise<MarvinCollection[]>;
|
|
271
300
|
/**
|
|
272
301
|
* Get a single collection by slug
|
|
302
|
+
* Returns null if collection is not found (404)
|
|
273
303
|
*/
|
|
274
|
-
get(slug: string): Promise<Collection>;
|
|
304
|
+
get(slug: string): Promise<Collection | null>;
|
|
275
305
|
/**
|
|
276
306
|
* Get entries in a collection
|
|
307
|
+
* Returns empty array if collection is not found
|
|
277
308
|
*/
|
|
278
309
|
entries(slug: string): Promise<MarvinEntry[]>;
|
|
310
|
+
/**
|
|
311
|
+
* Try multiple collection slugs in fallback order
|
|
312
|
+
* Returns the first collection that exists and has entries
|
|
313
|
+
*
|
|
314
|
+
* @param slugs - Collection slugs to try in order
|
|
315
|
+
* @param options - Options for fallback behavior
|
|
316
|
+
* @returns Entries from the first matching collection, or empty array
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```ts
|
|
320
|
+
* // Try bench-notes, then journal, then blog
|
|
321
|
+
* const entries = await collections.fallback(['bench-notes', 'journal', 'blog']);
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
fallback(slugs: string[], options?: {
|
|
325
|
+
requireEntries?: boolean;
|
|
326
|
+
}): Promise<MarvinEntry[]>;
|
|
279
327
|
}
|
|
280
328
|
|
|
281
329
|
declare class Entry {
|
|
@@ -365,8 +413,9 @@ declare class EntriesModule {
|
|
|
365
413
|
list(options?: GetEntriesOptions): Promise<MarvinEntry[]>;
|
|
366
414
|
/**
|
|
367
415
|
* Get a single entry by slug
|
|
416
|
+
* Returns null if entry is not found (404)
|
|
368
417
|
*/
|
|
369
|
-
get(slug: string): Promise<Entry>;
|
|
418
|
+
get(slug: string): Promise<Entry | null>;
|
|
370
419
|
/**
|
|
371
420
|
* Convenience: Get all pages
|
|
372
421
|
*/
|
|
@@ -465,11 +514,11 @@ declare class MarvinClient {
|
|
|
465
514
|
/**
|
|
466
515
|
* Get a single entry by slug
|
|
467
516
|
*/
|
|
468
|
-
entry(slug: string): Promise<Entry>;
|
|
517
|
+
entry(slug: string): Promise<Entry | null>;
|
|
469
518
|
/**
|
|
470
519
|
* Get a single collection by slug
|
|
471
520
|
*/
|
|
472
|
-
collection(slug: string): Promise<Collection>;
|
|
521
|
+
collection(slug: string): Promise<Collection | null>;
|
|
473
522
|
/**
|
|
474
523
|
* Get all pages
|
|
475
524
|
*/
|
|
@@ -486,6 +535,23 @@ declare class MarvinClient {
|
|
|
486
535
|
* Get a single resource by slug
|
|
487
536
|
*/
|
|
488
537
|
resource(slug: string): Promise<Resource>;
|
|
538
|
+
/**
|
|
539
|
+
* Try multiple collection slugs in fallback order
|
|
540
|
+
* Returns entries from the first collection that exists and has content
|
|
541
|
+
*
|
|
542
|
+
* @param slugs - Collection slugs to try in order
|
|
543
|
+
* @param options - Options for fallback behavior
|
|
544
|
+
* @returns Entries from the first matching collection, or empty array
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* // Try bench-notes, then journal, then blog
|
|
549
|
+
* const entries = await client.collectionFallback(['bench-notes', 'journal', 'blog']);
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
552
|
+
collectionFallback(slugs: string[], options?: {
|
|
553
|
+
requireEntries?: boolean;
|
|
554
|
+
}): Promise<MarvinEntry[]>;
|
|
489
555
|
/**
|
|
490
556
|
* @deprecated Use workspace.site or marvin.site instead
|
|
491
557
|
* Get site configuration
|
|
@@ -500,7 +566,7 @@ declare class MarvinClient {
|
|
|
500
566
|
* @deprecated Use workspace.entries.get() instead
|
|
501
567
|
* Get a single published entry by slug
|
|
502
568
|
*/
|
|
503
|
-
getEntry(slug: string): Promise<MarvinEntry>;
|
|
569
|
+
getEntry(slug: string): Promise<MarvinEntry | null>;
|
|
504
570
|
/**
|
|
505
571
|
* @deprecated Use workspace.collections.list() instead
|
|
506
572
|
* Get all collections
|
|
@@ -510,7 +576,7 @@ declare class MarvinClient {
|
|
|
510
576
|
* @deprecated Use workspace.collections.get() instead
|
|
511
577
|
* Get a single collection by slug
|
|
512
578
|
*/
|
|
513
|
-
getCollection(slug: string): Promise<MarvinCollection>;
|
|
579
|
+
getCollection(slug: string): Promise<MarvinCollection | null>;
|
|
514
580
|
/**
|
|
515
581
|
* @deprecated Use workspace.collections.entries() instead
|
|
516
582
|
* Get all entries in a collection
|
|
@@ -621,4 +687,4 @@ declare function createAuthClient(apiUrl: string): AuthClient;
|
|
|
621
687
|
*/
|
|
622
688
|
declare function createMarvinClient(config?: Partial<MarvinConfig>): MarvinClient;
|
|
623
689
|
|
|
624
|
-
export { AuthClient, type AuthToken, Collection, Entry, type ForgotPasswordRequest, GetResourcesOptions$1 as GetResourcesOptions, HttpClient, type LoginRequest, MarvinApiError, MarvinAsset, MarvinAuthError, MarvinCache, MarvinClient, MarvinCollection, type MarvinConfig, MarvinConfigError, MarvinEntry, MarvinEntryType, MarvinError, MarvinResource, MarvinSite, MarvinValidationError, type PaginatedResponse, type PaginationMeta, type PaginationParams, type ResetPasswordRequest, Resource, type UserRegistration, Workspace, createAuthClient, createConfigFromEnv, createMarvinClient, createPaginatedResponse, extractData, isPaginatedResponse, offsetToPage, pageToOffset };
|
|
690
|
+
export { AuthClient, type AuthToken, Collection, Entry, type ForgotPasswordRequest, GetResourcesOptions$1 as GetResourcesOptions, HttpClient, type LoginRequest, MarvinApiError, MarvinAsset, MarvinAuthError, MarvinCache, MarvinClient, MarvinCollection, type MarvinConfig, MarvinConfigError, MarvinEntry, MarvinEntryType, MarvinError, MarvinNetworkError, MarvinNotFoundError, MarvinResource, MarvinServerError, MarvinSite, MarvinValidationError, type PaginatedResponse, type PaginationMeta, type PaginationParams, type ResetPasswordRequest, Resource, type UserRegistration, Workspace, createAuthClient, createConfigFromEnv, createMarvinClient, createPaginatedResponse, extractData, isPaginatedResponse, offsetToPage, pageToOffset };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MarvinResource, MarvinEntry, MarvinAsset, MarvinCollection, MarvinEntryType, MarvinSite, GetResourcesOptions as GetResourcesOptions$1 } from './types/index.js';
|
|
2
2
|
export { GetAssetsOptions, GetEntriesOptions, MarvinPublishResponse } from './types/index.js';
|
|
3
|
-
import { H as HttpClient } from './HttpClient-
|
|
4
|
-
export { A as AuthStrategy, B as BearerTokenAuth, a as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-
|
|
3
|
+
import { H as HttpClient } from './HttpClient-BX5Gqd0w.js';
|
|
4
|
+
export { A as AuthStrategy, B as BearerTokenAuth, a as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-BX5Gqd0w.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Marvin SDK Configuration
|
|
@@ -14,6 +14,14 @@ interface MarvinConfig {
|
|
|
14
14
|
autoInitialize?: boolean;
|
|
15
15
|
/** Cache duration in milliseconds (default: 5 minutes) */
|
|
16
16
|
cacheDuration?: number;
|
|
17
|
+
/** Enable debug logging for HTTP requests and responses */
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
/** Custom logger function (defaults to console) */
|
|
20
|
+
logger?: {
|
|
21
|
+
log: (message: string, ...args: unknown[]) => void;
|
|
22
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
23
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
24
|
+
};
|
|
17
25
|
}
|
|
18
26
|
declare function createConfigFromEnv(overrides?: Partial<MarvinConfig>): MarvinConfig;
|
|
19
27
|
|
|
@@ -54,6 +62,27 @@ declare class MarvinValidationError extends MarvinError {
|
|
|
54
62
|
readonly field?: string | undefined;
|
|
55
63
|
constructor(message: string, field?: string | undefined);
|
|
56
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Resource not found errors (404)
|
|
67
|
+
*/
|
|
68
|
+
declare class MarvinNotFoundError extends MarvinError {
|
|
69
|
+
readonly endpoint: string;
|
|
70
|
+
constructor(message: string, endpoint: string);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Network/connectivity errors
|
|
74
|
+
*/
|
|
75
|
+
declare class MarvinNetworkError extends MarvinError {
|
|
76
|
+
readonly originalError?: Error | undefined;
|
|
77
|
+
constructor(message: string, originalError?: Error | undefined);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Server errors (5xx)
|
|
81
|
+
*/
|
|
82
|
+
declare class MarvinServerError extends MarvinError {
|
|
83
|
+
readonly endpoint: string;
|
|
84
|
+
constructor(message: string, statusCode: number, endpoint: string);
|
|
85
|
+
}
|
|
57
86
|
|
|
58
87
|
/**
|
|
59
88
|
* Pagination response types and helpers
|
|
@@ -270,12 +299,31 @@ declare class CollectionsModule {
|
|
|
270
299
|
list(): Promise<MarvinCollection[]>;
|
|
271
300
|
/**
|
|
272
301
|
* Get a single collection by slug
|
|
302
|
+
* Returns null if collection is not found (404)
|
|
273
303
|
*/
|
|
274
|
-
get(slug: string): Promise<Collection>;
|
|
304
|
+
get(slug: string): Promise<Collection | null>;
|
|
275
305
|
/**
|
|
276
306
|
* Get entries in a collection
|
|
307
|
+
* Returns empty array if collection is not found
|
|
277
308
|
*/
|
|
278
309
|
entries(slug: string): Promise<MarvinEntry[]>;
|
|
310
|
+
/**
|
|
311
|
+
* Try multiple collection slugs in fallback order
|
|
312
|
+
* Returns the first collection that exists and has entries
|
|
313
|
+
*
|
|
314
|
+
* @param slugs - Collection slugs to try in order
|
|
315
|
+
* @param options - Options for fallback behavior
|
|
316
|
+
* @returns Entries from the first matching collection, or empty array
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```ts
|
|
320
|
+
* // Try bench-notes, then journal, then blog
|
|
321
|
+
* const entries = await collections.fallback(['bench-notes', 'journal', 'blog']);
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
fallback(slugs: string[], options?: {
|
|
325
|
+
requireEntries?: boolean;
|
|
326
|
+
}): Promise<MarvinEntry[]>;
|
|
279
327
|
}
|
|
280
328
|
|
|
281
329
|
declare class Entry {
|
|
@@ -365,8 +413,9 @@ declare class EntriesModule {
|
|
|
365
413
|
list(options?: GetEntriesOptions): Promise<MarvinEntry[]>;
|
|
366
414
|
/**
|
|
367
415
|
* Get a single entry by slug
|
|
416
|
+
* Returns null if entry is not found (404)
|
|
368
417
|
*/
|
|
369
|
-
get(slug: string): Promise<Entry>;
|
|
418
|
+
get(slug: string): Promise<Entry | null>;
|
|
370
419
|
/**
|
|
371
420
|
* Convenience: Get all pages
|
|
372
421
|
*/
|
|
@@ -465,11 +514,11 @@ declare class MarvinClient {
|
|
|
465
514
|
/**
|
|
466
515
|
* Get a single entry by slug
|
|
467
516
|
*/
|
|
468
|
-
entry(slug: string): Promise<Entry>;
|
|
517
|
+
entry(slug: string): Promise<Entry | null>;
|
|
469
518
|
/**
|
|
470
519
|
* Get a single collection by slug
|
|
471
520
|
*/
|
|
472
|
-
collection(slug: string): Promise<Collection>;
|
|
521
|
+
collection(slug: string): Promise<Collection | null>;
|
|
473
522
|
/**
|
|
474
523
|
* Get all pages
|
|
475
524
|
*/
|
|
@@ -486,6 +535,23 @@ declare class MarvinClient {
|
|
|
486
535
|
* Get a single resource by slug
|
|
487
536
|
*/
|
|
488
537
|
resource(slug: string): Promise<Resource>;
|
|
538
|
+
/**
|
|
539
|
+
* Try multiple collection slugs in fallback order
|
|
540
|
+
* Returns entries from the first collection that exists and has content
|
|
541
|
+
*
|
|
542
|
+
* @param slugs - Collection slugs to try in order
|
|
543
|
+
* @param options - Options for fallback behavior
|
|
544
|
+
* @returns Entries from the first matching collection, or empty array
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* // Try bench-notes, then journal, then blog
|
|
549
|
+
* const entries = await client.collectionFallback(['bench-notes', 'journal', 'blog']);
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
552
|
+
collectionFallback(slugs: string[], options?: {
|
|
553
|
+
requireEntries?: boolean;
|
|
554
|
+
}): Promise<MarvinEntry[]>;
|
|
489
555
|
/**
|
|
490
556
|
* @deprecated Use workspace.site or marvin.site instead
|
|
491
557
|
* Get site configuration
|
|
@@ -500,7 +566,7 @@ declare class MarvinClient {
|
|
|
500
566
|
* @deprecated Use workspace.entries.get() instead
|
|
501
567
|
* Get a single published entry by slug
|
|
502
568
|
*/
|
|
503
|
-
getEntry(slug: string): Promise<MarvinEntry>;
|
|
569
|
+
getEntry(slug: string): Promise<MarvinEntry | null>;
|
|
504
570
|
/**
|
|
505
571
|
* @deprecated Use workspace.collections.list() instead
|
|
506
572
|
* Get all collections
|
|
@@ -510,7 +576,7 @@ declare class MarvinClient {
|
|
|
510
576
|
* @deprecated Use workspace.collections.get() instead
|
|
511
577
|
* Get a single collection by slug
|
|
512
578
|
*/
|
|
513
|
-
getCollection(slug: string): Promise<MarvinCollection>;
|
|
579
|
+
getCollection(slug: string): Promise<MarvinCollection | null>;
|
|
514
580
|
/**
|
|
515
581
|
* @deprecated Use workspace.collections.entries() instead
|
|
516
582
|
* Get all entries in a collection
|
|
@@ -621,4 +687,4 @@ declare function createAuthClient(apiUrl: string): AuthClient;
|
|
|
621
687
|
*/
|
|
622
688
|
declare function createMarvinClient(config?: Partial<MarvinConfig>): MarvinClient;
|
|
623
689
|
|
|
624
|
-
export { AuthClient, type AuthToken, Collection, Entry, type ForgotPasswordRequest, GetResourcesOptions$1 as GetResourcesOptions, HttpClient, type LoginRequest, MarvinApiError, MarvinAsset, MarvinAuthError, MarvinCache, MarvinClient, MarvinCollection, type MarvinConfig, MarvinConfigError, MarvinEntry, MarvinEntryType, MarvinError, MarvinResource, MarvinSite, MarvinValidationError, type PaginatedResponse, type PaginationMeta, type PaginationParams, type ResetPasswordRequest, Resource, type UserRegistration, Workspace, createAuthClient, createConfigFromEnv, createMarvinClient, createPaginatedResponse, extractData, isPaginatedResponse, offsetToPage, pageToOffset };
|
|
690
|
+
export { AuthClient, type AuthToken, Collection, Entry, type ForgotPasswordRequest, GetResourcesOptions$1 as GetResourcesOptions, HttpClient, type LoginRequest, MarvinApiError, MarvinAsset, MarvinAuthError, MarvinCache, MarvinClient, MarvinCollection, type MarvinConfig, MarvinConfigError, MarvinEntry, MarvinEntryType, MarvinError, MarvinNetworkError, MarvinNotFoundError, MarvinResource, MarvinServerError, MarvinSite, MarvinValidationError, type PaginatedResponse, type PaginationMeta, type PaginationParams, type ResetPasswordRequest, Resource, type UserRegistration, Workspace, createAuthClient, createConfigFromEnv, createMarvinClient, createPaginatedResponse, extractData, isPaginatedResponse, offsetToPage, pageToOffset };
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ import {
|
|
|
6
6
|
MarvinCache,
|
|
7
7
|
MarvinConfigError,
|
|
8
8
|
MarvinError,
|
|
9
|
+
MarvinNetworkError,
|
|
10
|
+
MarvinNotFoundError,
|
|
11
|
+
MarvinServerError,
|
|
9
12
|
MarvinValidationError,
|
|
10
13
|
NoAuth,
|
|
11
14
|
SessionAuth,
|
|
@@ -15,10 +18,11 @@ import {
|
|
|
15
18
|
createPaginatedResponse,
|
|
16
19
|
extractData,
|
|
17
20
|
init_core,
|
|
21
|
+
init_errors,
|
|
18
22
|
isPaginatedResponse,
|
|
19
23
|
offsetToPage,
|
|
20
24
|
pageToOffset
|
|
21
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-QBHM2XNX.js";
|
|
22
26
|
|
|
23
27
|
// src/client/config.ts
|
|
24
28
|
var config_exports = {};
|
|
@@ -27,14 +31,21 @@ __export(config_exports, {
|
|
|
27
31
|
validateConfig: () => validateConfig
|
|
28
32
|
});
|
|
29
33
|
function validateConfig(config) {
|
|
34
|
+
const receivedKeys = Object.keys(config).join(", ");
|
|
30
35
|
if (!config.apiUrl) {
|
|
31
|
-
throw new Error(
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Missing required config parameter 'apiUrl'. Received config keys: ${receivedKeys || "(none)"}. Set this to your MARVIN_API_URL environment variable value.`
|
|
38
|
+
);
|
|
32
39
|
}
|
|
33
40
|
if (!config.siteClientToken) {
|
|
34
|
-
throw new Error(
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Missing required config parameter 'siteClientToken'. Received config keys: ${receivedKeys}. Set this to your MARVIN_SITE_CLIENT_TOKEN environment variable value.`
|
|
43
|
+
);
|
|
35
44
|
}
|
|
36
45
|
if (!config.workspaceSlug) {
|
|
37
|
-
throw new Error(
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Missing required config parameter 'workspaceSlug'. Received config keys: ${receivedKeys}. Set this to your MARVIN_WORKSPACE_SLUG environment variable value.`
|
|
48
|
+
);
|
|
38
49
|
}
|
|
39
50
|
}
|
|
40
51
|
function createConfigFromEnv(overrides) {
|
|
@@ -43,8 +54,10 @@ function createConfigFromEnv(overrides) {
|
|
|
43
54
|
siteClientToken: overrides?.siteClientToken || process.env.MARVIN_SITE_CLIENT_TOKEN || "",
|
|
44
55
|
workspaceSlug: overrides?.workspaceSlug || process.env.MARVIN_WORKSPACE_SLUG || "",
|
|
45
56
|
autoInitialize: overrides?.autoInitialize ?? false,
|
|
46
|
-
cacheDuration: overrides?.cacheDuration ?? 5 * 60 * 1e3
|
|
57
|
+
cacheDuration: overrides?.cacheDuration ?? 5 * 60 * 1e3,
|
|
47
58
|
// 5 minutes
|
|
59
|
+
debug: overrides?.debug ?? process.env.MARVIN_DEBUG === "true",
|
|
60
|
+
logger: overrides?.logger ?? console
|
|
48
61
|
};
|
|
49
62
|
}
|
|
50
63
|
var init_config = __esm({
|
|
@@ -64,7 +77,9 @@ var init_http = __esm({
|
|
|
64
77
|
super({
|
|
65
78
|
baseUrl: config.apiUrl,
|
|
66
79
|
auth: new BearerTokenAuth(config.siteClientToken),
|
|
67
|
-
credentials: "same-origin"
|
|
80
|
+
credentials: "same-origin",
|
|
81
|
+
debug: config.debug,
|
|
82
|
+
logger: config.logger
|
|
68
83
|
});
|
|
69
84
|
}
|
|
70
85
|
/**
|
|
@@ -201,6 +216,7 @@ var init_entries = __esm({
|
|
|
201
216
|
"src/entries/entries.ts"() {
|
|
202
217
|
"use strict";
|
|
203
218
|
init_entry();
|
|
219
|
+
init_errors();
|
|
204
220
|
EntriesModule = class {
|
|
205
221
|
constructor(http, workspaceSlug) {
|
|
206
222
|
this.http = http;
|
|
@@ -225,11 +241,19 @@ var init_entries = __esm({
|
|
|
225
241
|
}
|
|
226
242
|
/**
|
|
227
243
|
* Get a single entry by slug
|
|
244
|
+
* Returns null if entry is not found (404)
|
|
228
245
|
*/
|
|
229
246
|
async get(slug) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
247
|
+
try {
|
|
248
|
+
const endpoint = `/api/publish/${this.workspaceSlug}/entries/${slug}`;
|
|
249
|
+
const data = await this.http.fetch(endpoint);
|
|
250
|
+
return new Entry(data, this.http, this.workspaceSlug);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (error instanceof MarvinNotFoundError) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
233
257
|
}
|
|
234
258
|
/**
|
|
235
259
|
* Convenience: Get all pages
|
|
@@ -335,6 +359,7 @@ var init_collections = __esm({
|
|
|
335
359
|
"src/collections/collections.ts"() {
|
|
336
360
|
"use strict";
|
|
337
361
|
init_collection();
|
|
362
|
+
init_errors();
|
|
338
363
|
CollectionsModule = class {
|
|
339
364
|
constructor(http, workspaceSlug) {
|
|
340
365
|
this.http = http;
|
|
@@ -352,19 +377,63 @@ var init_collections = __esm({
|
|
|
352
377
|
}
|
|
353
378
|
/**
|
|
354
379
|
* Get a single collection by slug
|
|
380
|
+
* Returns null if collection is not found (404)
|
|
355
381
|
*/
|
|
356
382
|
async get(slug) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
383
|
+
try {
|
|
384
|
+
const endpoint = `/api/publish/${this.workspaceSlug}/collections/${slug}`;
|
|
385
|
+
const data = await this.http.fetch(endpoint);
|
|
386
|
+
return new Collection(data, this.http, this.workspaceSlug);
|
|
387
|
+
} catch (error) {
|
|
388
|
+
if (error instanceof MarvinNotFoundError) {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
360
393
|
}
|
|
361
394
|
/**
|
|
362
395
|
* Get entries in a collection
|
|
396
|
+
* Returns empty array if collection is not found
|
|
363
397
|
*/
|
|
364
398
|
async entries(slug) {
|
|
365
399
|
const collection = await this.get(slug);
|
|
400
|
+
if (!collection) {
|
|
401
|
+
return [];
|
|
402
|
+
}
|
|
366
403
|
return collection.entries();
|
|
367
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Try multiple collection slugs in fallback order
|
|
407
|
+
* Returns the first collection that exists and has entries
|
|
408
|
+
*
|
|
409
|
+
* @param slugs - Collection slugs to try in order
|
|
410
|
+
* @param options - Options for fallback behavior
|
|
411
|
+
* @returns Entries from the first matching collection, or empty array
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```ts
|
|
415
|
+
* // Try bench-notes, then journal, then blog
|
|
416
|
+
* const entries = await collections.fallback(['bench-notes', 'journal', 'blog']);
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
419
|
+
async fallback(slugs, options = {}) {
|
|
420
|
+
const { requireEntries = true } = options;
|
|
421
|
+
for (const slug of slugs) {
|
|
422
|
+
try {
|
|
423
|
+
const collection = await this.get(slug);
|
|
424
|
+
if (!collection) {
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
const entries = await collection.entries();
|
|
428
|
+
if (!requireEntries || entries.length > 0) {
|
|
429
|
+
return entries;
|
|
430
|
+
}
|
|
431
|
+
} catch (error) {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return [];
|
|
436
|
+
}
|
|
368
437
|
};
|
|
369
438
|
}
|
|
370
439
|
});
|
|
@@ -727,6 +796,23 @@ var init_marvin = __esm({
|
|
|
727
796
|
async resource(slug) {
|
|
728
797
|
return this.workspace.resources.get(slug);
|
|
729
798
|
}
|
|
799
|
+
/**
|
|
800
|
+
* Try multiple collection slugs in fallback order
|
|
801
|
+
* Returns entries from the first collection that exists and has content
|
|
802
|
+
*
|
|
803
|
+
* @param slugs - Collection slugs to try in order
|
|
804
|
+
* @param options - Options for fallback behavior
|
|
805
|
+
* @returns Entries from the first matching collection, or empty array
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```ts
|
|
809
|
+
* // Try bench-notes, then journal, then blog
|
|
810
|
+
* const entries = await client.collectionFallback(['bench-notes', 'journal', 'blog']);
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
async collectionFallback(slugs, options) {
|
|
814
|
+
return this.workspace.collections.fallback(slugs, options);
|
|
815
|
+
}
|
|
730
816
|
// ======================
|
|
731
817
|
// Backwards-Compatible Publishing API
|
|
732
818
|
// ======================
|
|
@@ -750,6 +836,9 @@ var init_marvin = __esm({
|
|
|
750
836
|
*/
|
|
751
837
|
async getEntry(slug) {
|
|
752
838
|
const entry = await this.workspace.entries.get(slug);
|
|
839
|
+
if (!entry) {
|
|
840
|
+
return null;
|
|
841
|
+
}
|
|
753
842
|
return entry.toJSON();
|
|
754
843
|
}
|
|
755
844
|
/**
|
|
@@ -765,6 +854,9 @@ var init_marvin = __esm({
|
|
|
765
854
|
*/
|
|
766
855
|
async getCollection(slug) {
|
|
767
856
|
const collection = await this.workspace.collections.get(slug);
|
|
857
|
+
if (!collection) {
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
768
860
|
return collection.toJSON();
|
|
769
861
|
}
|
|
770
862
|
/**
|
|
@@ -888,6 +980,9 @@ export {
|
|
|
888
980
|
MarvinClient,
|
|
889
981
|
MarvinConfigError,
|
|
890
982
|
MarvinError,
|
|
983
|
+
MarvinNetworkError,
|
|
984
|
+
MarvinNotFoundError,
|
|
985
|
+
MarvinServerError,
|
|
891
986
|
MarvinValidationError,
|
|
892
987
|
NoAuth,
|
|
893
988
|
Resource,
|
package/dist/platform.cjs
CHANGED
|
@@ -77,6 +77,40 @@ ${body}` : ""}`;
|
|
|
77
77
|
return new _MarvinApiError(message, status, endpoint, body);
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
|
+
var MarvinAuthError = class _MarvinAuthError extends MarvinError {
|
|
81
|
+
constructor(message, statusCode) {
|
|
82
|
+
super(message, "AUTH_ERROR", statusCode);
|
|
83
|
+
this.name = "MarvinAuthError";
|
|
84
|
+
Object.setPrototypeOf(this, _MarvinAuthError.prototype);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var MarvinNotFoundError = class _MarvinNotFoundError extends MarvinError {
|
|
88
|
+
constructor(message, endpoint) {
|
|
89
|
+
super(message, "NOT_FOUND", 404);
|
|
90
|
+
this.endpoint = endpoint;
|
|
91
|
+
this.name = "MarvinNotFoundError";
|
|
92
|
+
Object.setPrototypeOf(this, _MarvinNotFoundError.prototype);
|
|
93
|
+
}
|
|
94
|
+
endpoint;
|
|
95
|
+
};
|
|
96
|
+
var MarvinNetworkError = class _MarvinNetworkError extends MarvinError {
|
|
97
|
+
constructor(message, originalError) {
|
|
98
|
+
super(message, "NETWORK_ERROR");
|
|
99
|
+
this.originalError = originalError;
|
|
100
|
+
this.name = "MarvinNetworkError";
|
|
101
|
+
Object.setPrototypeOf(this, _MarvinNetworkError.prototype);
|
|
102
|
+
}
|
|
103
|
+
originalError;
|
|
104
|
+
};
|
|
105
|
+
var MarvinServerError = class _MarvinServerError extends MarvinError {
|
|
106
|
+
constructor(message, statusCode, endpoint) {
|
|
107
|
+
super(message, "SERVER_ERROR", statusCode);
|
|
108
|
+
this.endpoint = endpoint;
|
|
109
|
+
this.name = "MarvinServerError";
|
|
110
|
+
Object.setPrototypeOf(this, _MarvinServerError.prototype);
|
|
111
|
+
}
|
|
112
|
+
endpoint;
|
|
113
|
+
};
|
|
80
114
|
|
|
81
115
|
// src/core/http/HttpClient.ts
|
|
82
116
|
var HttpClient = class {
|
|
@@ -85,12 +119,16 @@ var HttpClient = class {
|
|
|
85
119
|
defaultHeaders;
|
|
86
120
|
credentials;
|
|
87
121
|
timeout;
|
|
122
|
+
debug;
|
|
123
|
+
logger;
|
|
88
124
|
constructor(config) {
|
|
89
125
|
this.baseUrl = config.baseUrl;
|
|
90
126
|
this.auth = config.auth;
|
|
91
127
|
this.defaultHeaders = config.defaultHeaders || {};
|
|
92
128
|
this.credentials = config.credentials || "same-origin";
|
|
93
129
|
this.timeout = config.timeout || 3e4;
|
|
130
|
+
this.debug = config.debug ?? false;
|
|
131
|
+
this.logger = config.logger ?? console;
|
|
94
132
|
}
|
|
95
133
|
/**
|
|
96
134
|
* Build full URL from endpoint
|
|
@@ -132,6 +170,10 @@ var HttpClient = class {
|
|
|
132
170
|
const headers = this.buildHeaders(options?.headers, isFormData);
|
|
133
171
|
const controller = new AbortController();
|
|
134
172
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
173
|
+
const startTime = Date.now();
|
|
174
|
+
if (this.debug) {
|
|
175
|
+
this.logger.log(`[Marvin] ${method} ${url}`);
|
|
176
|
+
}
|
|
135
177
|
try {
|
|
136
178
|
const response = await fetch(url, {
|
|
137
179
|
method,
|
|
@@ -141,11 +183,42 @@ var HttpClient = class {
|
|
|
141
183
|
signal: controller.signal
|
|
142
184
|
});
|
|
143
185
|
clearTimeout(timeoutId);
|
|
186
|
+
const duration = Date.now() - startTime;
|
|
187
|
+
if (this.debug) {
|
|
188
|
+
this.logger.log(
|
|
189
|
+
`[Marvin] ${response.status} ${response.statusText} (${duration}ms)`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
144
192
|
if (response.status === 401 && this.auth.handleUnauthorized) {
|
|
145
193
|
await this.auth.handleUnauthorized();
|
|
146
194
|
}
|
|
147
195
|
if (!response.ok) {
|
|
148
196
|
const errorText = await response.text().catch(() => "");
|
|
197
|
+
if (this.debug) {
|
|
198
|
+
this.logger.error(
|
|
199
|
+
`[Marvin] Error response: ${response.status} ${response.statusText}`,
|
|
200
|
+
errorText ? `Body: ${errorText}` : ""
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
if (response.status === 404) {
|
|
204
|
+
throw new MarvinNotFoundError(
|
|
205
|
+
`Resource not found: ${endpoint}`,
|
|
206
|
+
endpoint
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (response.status === 401 || response.status === 403) {
|
|
210
|
+
throw new MarvinAuthError(
|
|
211
|
+
`Authentication failed: ${response.statusText}`,
|
|
212
|
+
response.status
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
if (response.status >= 500) {
|
|
216
|
+
throw new MarvinServerError(
|
|
217
|
+
`Server error: ${response.status} ${response.statusText}`,
|
|
218
|
+
response.status,
|
|
219
|
+
endpoint
|
|
220
|
+
);
|
|
221
|
+
}
|
|
149
222
|
throw MarvinApiError.fromResponse(
|
|
150
223
|
response.status,
|
|
151
224
|
response.statusText,
|
|
@@ -160,18 +233,20 @@ var HttpClient = class {
|
|
|
160
233
|
return await response.json();
|
|
161
234
|
} catch (error) {
|
|
162
235
|
clearTimeout(timeoutId);
|
|
163
|
-
if (error instanceof MarvinApiError) {
|
|
236
|
+
if (error instanceof MarvinApiError || error instanceof MarvinNotFoundError || error instanceof MarvinAuthError || error instanceof MarvinServerError) {
|
|
164
237
|
throw error;
|
|
165
238
|
}
|
|
166
239
|
if (error instanceof Error) {
|
|
167
240
|
if (error.name === "AbortError") {
|
|
168
|
-
throw new
|
|
241
|
+
throw new MarvinNetworkError(
|
|
169
242
|
`Request timeout after ${this.timeout}ms`,
|
|
170
|
-
|
|
171
|
-
endpoint
|
|
243
|
+
error
|
|
172
244
|
);
|
|
173
245
|
}
|
|
174
|
-
throw new
|
|
246
|
+
throw new MarvinNetworkError(
|
|
247
|
+
`Network error: ${error.message}`,
|
|
248
|
+
error
|
|
249
|
+
);
|
|
175
250
|
}
|
|
176
251
|
throw error;
|
|
177
252
|
}
|
package/dist/platform.d.cts
CHANGED
package/dist/platform.d.ts
CHANGED
package/dist/platform.js
CHANGED