@inneropen/marvin-sdk 2.0.0-next.18 → 2.0.0-next.3
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 +11 -136
- package/dist/{HttpClient-CdF3IHM1.d.cts → HttpClient-CLtgQGXH.d.cts} +2 -49
- package/dist/{HttpClient-CdF3IHM1.d.ts → HttpClient-CLtgQGXH.d.ts} +2 -49
- package/dist/chunk-25F3IF6S.js +396 -0
- package/dist/index.cjs +25 -536
- package/dist/index.d.cts +544 -20
- package/dist/index.d.ts +544 -20
- package/dist/index.js +791 -27
- package/dist/platform.cjs +42 -681
- package/dist/platform.d.cts +80 -803
- package/dist/platform.d.ts +80 -803
- package/dist/platform.js +32 -449
- package/dist/types/index.d.cts +1 -9
- package/dist/types/index.d.ts +1 -9
- package/package.json +7 -18
- package/dist/chunk-GJNOYXUQ.js +0 -980
- package/dist/chunk-WJC4X7TB.js +0 -738
- package/dist/marvin-Bx5k6tsF.d.cts +0 -654
- package/dist/marvin-g7dayc83.d.ts +0 -654
- package/dist/publish.cjs +0 -1487
- package/dist/publish.d.cts +0 -49
- package/dist/publish.d.ts +0 -49
- package/dist/publish.js +0 -75
package/dist/platform.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HttpClient,
|
|
3
|
-
MarvinValidationError,
|
|
4
3
|
SessionAuth,
|
|
5
4
|
init_core
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-25F3IF6S.js";
|
|
7
6
|
|
|
8
7
|
// src/platform/client.ts
|
|
9
8
|
init_core();
|
|
@@ -24,8 +23,7 @@ var EntriesModule = class {
|
|
|
24
23
|
* Get a single entry by ID
|
|
25
24
|
*/
|
|
26
25
|
async get(id) {
|
|
27
|
-
|
|
28
|
-
return this.http.get(`/api/platform/entries/${validId}`);
|
|
26
|
+
return this.http.get(`/api/platform/entries/${id}`);
|
|
29
27
|
}
|
|
30
28
|
/**
|
|
31
29
|
* Create a new entry
|
|
@@ -37,31 +35,26 @@ var EntriesModule = class {
|
|
|
37
35
|
* Update an entry
|
|
38
36
|
*/
|
|
39
37
|
async update(id, data) {
|
|
40
|
-
|
|
41
|
-
return this.http.patch(`/api/platform/entries/${validId}`, data);
|
|
38
|
+
return this.http.patch(`/api/platform/entries/${id}`, data);
|
|
42
39
|
}
|
|
43
40
|
/**
|
|
44
41
|
* Delete an entry
|
|
45
42
|
*/
|
|
46
43
|
async delete(id) {
|
|
47
|
-
|
|
48
|
-
return this.http.delete(`/api/platform/entries/${validId}`);
|
|
44
|
+
return this.http.delete(`/api/platform/entries/${id}`);
|
|
49
45
|
}
|
|
50
46
|
/**
|
|
51
47
|
* Get collections that this entry belongs to
|
|
52
48
|
*/
|
|
53
49
|
async listCollections(entryId) {
|
|
54
|
-
|
|
55
|
-
return this.http.get(`/api/platform/entries/${validId}/collections`);
|
|
50
|
+
return this.http.get(`/api/platform/entries/${entryId}/collections`);
|
|
56
51
|
}
|
|
57
52
|
/**
|
|
58
53
|
* Add entry to a collection
|
|
59
54
|
*/
|
|
60
55
|
async addToCollection(entryId, collectionId) {
|
|
61
|
-
const validEntryId = this.http.validatePathParam(entryId, "entry ID");
|
|
62
|
-
const validCollectionId = this.http.validatePathParam(collectionId, "collection ID");
|
|
63
56
|
return this.http.post(
|
|
64
|
-
`/api/platform/entries/${
|
|
57
|
+
`/api/platform/entries/${entryId}/collections/${collectionId}`,
|
|
65
58
|
{}
|
|
66
59
|
);
|
|
67
60
|
}
|
|
@@ -69,9 +62,7 @@ var EntriesModule = class {
|
|
|
69
62
|
* Remove entry from a collection
|
|
70
63
|
*/
|
|
71
64
|
async removeFromCollection(entryId, collectionId) {
|
|
72
|
-
|
|
73
|
-
const validCollectionId = this.http.validatePathParam(collectionId, "collection ID");
|
|
74
|
-
return this.http.delete(`/api/platform/entries/${validEntryId}/collections/${validCollectionId}`);
|
|
65
|
+
return this.http.delete(`/api/platform/entries/${entryId}/collections/${collectionId}`);
|
|
75
66
|
}
|
|
76
67
|
};
|
|
77
68
|
|
|
@@ -91,8 +82,7 @@ var CollectionsModule = class {
|
|
|
91
82
|
* Get a single collection by ID
|
|
92
83
|
*/
|
|
93
84
|
async get(id) {
|
|
94
|
-
|
|
95
|
-
return this.http.get(`/api/platform/collections/${validId}`);
|
|
85
|
+
return this.http.get(`/api/platform/collections/${id}`);
|
|
96
86
|
}
|
|
97
87
|
/**
|
|
98
88
|
* Create a new collection
|
|
@@ -104,29 +94,25 @@ var CollectionsModule = class {
|
|
|
104
94
|
* Update a collection
|
|
105
95
|
*/
|
|
106
96
|
async update(id, data) {
|
|
107
|
-
|
|
108
|
-
return this.http.patch(`/api/platform/collections/${validId}`, data);
|
|
97
|
+
return this.http.patch(`/api/platform/collections/${id}`, data);
|
|
109
98
|
}
|
|
110
99
|
/**
|
|
111
100
|
* Delete a collection
|
|
112
101
|
*/
|
|
113
102
|
async delete(id) {
|
|
114
|
-
|
|
115
|
-
return this.http.delete(`/api/platform/collections/${validId}`);
|
|
103
|
+
return this.http.delete(`/api/platform/collections/${id}`);
|
|
116
104
|
}
|
|
117
105
|
/**
|
|
118
106
|
* Get entries in a collection
|
|
119
107
|
*/
|
|
120
108
|
async getEntries(id) {
|
|
121
|
-
|
|
122
|
-
return this.http.get(`/api/platform/collections/${validId}/entries`);
|
|
109
|
+
return this.http.get(`/api/platform/collections/${id}/entries`);
|
|
123
110
|
}
|
|
124
111
|
/**
|
|
125
112
|
* Reorder entries in a collection
|
|
126
113
|
*/
|
|
127
114
|
async reorderEntries(id, entries) {
|
|
128
|
-
|
|
129
|
-
return this.http.patch(`/api/platform/collections/${validId}/entries/order`, { entries });
|
|
115
|
+
return this.http.patch(`/api/platform/collections/${id}/entries/order`, { entries });
|
|
130
116
|
}
|
|
131
117
|
};
|
|
132
118
|
|
|
@@ -146,8 +132,7 @@ var ResourcesModule = class {
|
|
|
146
132
|
* Get a single resource by ID
|
|
147
133
|
*/
|
|
148
134
|
async get(id) {
|
|
149
|
-
|
|
150
|
-
return this.http.get(`/api/platform/resources/${validId}`);
|
|
135
|
+
return this.http.get(`/api/platform/resources/${id}`);
|
|
151
136
|
}
|
|
152
137
|
/**
|
|
153
138
|
* Create a new resource
|
|
@@ -159,8 +144,7 @@ var ResourcesModule = class {
|
|
|
159
144
|
* Update a resource
|
|
160
145
|
*/
|
|
161
146
|
async update(id, data) {
|
|
162
|
-
|
|
163
|
-
return this.http.patch(`/api/platform/resources/${validId}`, data);
|
|
147
|
+
return this.http.patch(`/api/platform/resources/${id}`, data);
|
|
164
148
|
}
|
|
165
149
|
/**
|
|
166
150
|
* Delete a resource
|
|
@@ -177,53 +161,11 @@ var ResourcesModule = class {
|
|
|
177
161
|
};
|
|
178
162
|
|
|
179
163
|
// src/platform/assets.ts
|
|
180
|
-
init_core();
|
|
181
164
|
var AssetsModule = class {
|
|
182
165
|
constructor(http) {
|
|
183
166
|
this.http = http;
|
|
184
167
|
}
|
|
185
168
|
http;
|
|
186
|
-
/**
|
|
187
|
-
* Validate file before upload
|
|
188
|
-
*/
|
|
189
|
-
validateFile(file, options) {
|
|
190
|
-
const maxSize = options?.maxFileSize || 100 * 1024 * 1024;
|
|
191
|
-
const allowedTypes = options?.allowedMimeTypes;
|
|
192
|
-
if (file.size === 0) {
|
|
193
|
-
throw new MarvinValidationError("File is empty");
|
|
194
|
-
}
|
|
195
|
-
if (file.size > maxSize) {
|
|
196
|
-
const maxMB = Math.round(maxSize / (1024 * 1024));
|
|
197
|
-
const fileMB = Math.round(file.size / (1024 * 1024));
|
|
198
|
-
throw new MarvinValidationError(
|
|
199
|
-
`File size (${fileMB}MB) exceeds maximum allowed size of ${maxMB}MB`
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
if (allowedTypes && allowedTypes.length > 0) {
|
|
203
|
-
if (file instanceof File && file.type) {
|
|
204
|
-
const isAllowed = allowedTypes.some((allowed) => {
|
|
205
|
-
if (allowed.endsWith("/*")) {
|
|
206
|
-
const prefix = allowed.slice(0, -2);
|
|
207
|
-
return file.type.startsWith(prefix);
|
|
208
|
-
}
|
|
209
|
-
return file.type === allowed;
|
|
210
|
-
});
|
|
211
|
-
if (!isAllowed) {
|
|
212
|
-
throw new MarvinValidationError(
|
|
213
|
-
`File type "${file.type}" is not allowed. Allowed types: ${allowedTypes.join(", ")}`
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
if (file instanceof File) {
|
|
219
|
-
if (!file.name || file.name.trim().length === 0) {
|
|
220
|
-
throw new MarvinValidationError("File must have a valid name");
|
|
221
|
-
}
|
|
222
|
-
if (file.name.includes("..") || file.name.includes("/") || file.name.includes("\\")) {
|
|
223
|
-
throw new MarvinValidationError("Invalid filename: cannot contain path separators");
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
169
|
/**
|
|
228
170
|
* List all assets
|
|
229
171
|
*/
|
|
@@ -234,31 +176,16 @@ var AssetsModule = class {
|
|
|
234
176
|
* Get a single asset by ID
|
|
235
177
|
*/
|
|
236
178
|
async get(id) {
|
|
237
|
-
|
|
238
|
-
return this.http.get(`/api/platform/assets/${validId}`);
|
|
179
|
+
return this.http.get(`/api/platform/assets/${id}`);
|
|
239
180
|
}
|
|
240
181
|
/**
|
|
241
182
|
* Upload a new asset file
|
|
242
183
|
*
|
|
243
184
|
* @param file - The file to upload (File or Blob)
|
|
244
185
|
* @param metadata - Asset metadata (slug, name, altText, description, metadata)
|
|
245
|
-
* @param options - Upload options (file size limits, allowed types)
|
|
246
186
|
* @returns The created asset with extracted metadata
|
|
247
|
-
*
|
|
248
|
-
* @example
|
|
249
|
-
* ```typescript
|
|
250
|
-
* // Upload with default limits (100MB, all types)
|
|
251
|
-
* const asset = await assets.upload(file, { slug: 'my-image', name: 'My Image' });
|
|
252
|
-
*
|
|
253
|
-
* // Upload with restrictions
|
|
254
|
-
* const asset = await assets.upload(file,
|
|
255
|
-
* { slug: 'avatar', name: 'Avatar' },
|
|
256
|
-
* { maxFileSize: 5 * 1024 * 1024, allowedMimeTypes: ['image/*'] }
|
|
257
|
-
* );
|
|
258
|
-
* ```
|
|
259
187
|
*/
|
|
260
|
-
async upload(file, metadata
|
|
261
|
-
this.validateFile(file, options);
|
|
188
|
+
async upload(file, metadata) {
|
|
262
189
|
const formData = new FormData();
|
|
263
190
|
formData.append("file", file);
|
|
264
191
|
formData.append("slug", metadata.slug);
|
|
@@ -278,24 +205,13 @@ var AssetsModule = class {
|
|
|
278
205
|
* Update an asset (editable fields only: slug, name, altText, description, metadata)
|
|
279
206
|
*/
|
|
280
207
|
async update(id, data) {
|
|
281
|
-
|
|
282
|
-
return this.http.patch(`/api/platform/assets/${validId}`, data);
|
|
208
|
+
return this.http.patch(`/api/platform/assets/${id}`, data);
|
|
283
209
|
}
|
|
284
210
|
/**
|
|
285
211
|
* Delete an asset (removes file from storage and database)
|
|
286
212
|
*/
|
|
287
213
|
async delete(id) {
|
|
288
|
-
|
|
289
|
-
return this.http.delete(`/api/platform/assets/${validId}`);
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Get download URL for an asset file
|
|
293
|
-
* Use this to create download links or fetch the file directly
|
|
294
|
-
*/
|
|
295
|
-
getDownloadUrl(id, baseUrl) {
|
|
296
|
-
const validId = this.http.validatePathParam(id, "asset ID");
|
|
297
|
-
const base = baseUrl || (typeof window !== "undefined" && window.location ? window.location.origin : "");
|
|
298
|
-
return `${base}/api/platform/assets/${validId}/file`;
|
|
214
|
+
return this.http.delete(`/api/platform/assets/${id}`);
|
|
299
215
|
}
|
|
300
216
|
};
|
|
301
217
|
|
|
@@ -315,8 +231,7 @@ var APIClientsModule = class {
|
|
|
315
231
|
* Get a single API client by ID
|
|
316
232
|
*/
|
|
317
233
|
async get(id) {
|
|
318
|
-
|
|
319
|
-
return this.http.get(`/api/platform/api-clients/${validId}`);
|
|
234
|
+
return this.http.get(`/api/platform/api-clients/${id}`);
|
|
320
235
|
}
|
|
321
236
|
/**
|
|
322
237
|
* Create a new API client (returns client with token)
|
|
@@ -328,8 +243,7 @@ var APIClientsModule = class {
|
|
|
328
243
|
* Update an API client
|
|
329
244
|
*/
|
|
330
245
|
async update(id, data) {
|
|
331
|
-
|
|
332
|
-
return this.http.patch(`/api/platform/api-clients/${validId}`, data);
|
|
246
|
+
return this.http.patch(`/api/platform/api-clients/${id}`, data);
|
|
333
247
|
}
|
|
334
248
|
/**
|
|
335
249
|
* Delete an API client
|
|
@@ -493,15 +407,6 @@ var WorkspacesModule = class {
|
|
|
493
407
|
const url = `/api/admin/groups/${id}${force ? "?force=true" : ""}`;
|
|
494
408
|
await this.http.delete(url);
|
|
495
409
|
}
|
|
496
|
-
/**
|
|
497
|
-
* Export workspace data as JSON (collections, entry types, entries, site config)
|
|
498
|
-
*/
|
|
499
|
-
async export(options) {
|
|
500
|
-
const pretty = options?.pretty ?? true;
|
|
501
|
-
const endpoint = pretty ? "/api/platform/workspace/export/pretty" : "/api/platform/workspace/export";
|
|
502
|
-
const params = options?.includeSystemTypes ? { include_system_types: true } : void 0;
|
|
503
|
-
return this.http.get(endpoint, params);
|
|
504
|
-
}
|
|
505
410
|
/**
|
|
506
411
|
* Get workspace preferences
|
|
507
412
|
*/
|
|
@@ -549,23 +454,11 @@ var InvitesModule = class {
|
|
|
549
454
|
}
|
|
550
455
|
/**
|
|
551
456
|
* Generate invitation URL from a token
|
|
552
|
-
*
|
|
553
|
-
* @param token - Invitation token
|
|
554
|
-
* @param baseUrl - Base URL for the frontend (required in browser environments)
|
|
555
|
-
* @returns Full invitation URL
|
|
556
|
-
*
|
|
557
|
-
* @example
|
|
558
|
-
* ```typescript
|
|
559
|
-
* // Node.js (can use env vars)
|
|
560
|
-
* const url = invites.getInvitationUrl(token);
|
|
561
|
-
*
|
|
562
|
-
* // Browser (must provide baseUrl)
|
|
563
|
-
* const url = invites.getInvitationUrl(token, 'https://app.example.com');
|
|
564
|
-
* ```
|
|
457
|
+
* Uses MARVIN_FRONTEND_URL for the base URL, falls back to MARVIN_API_URL with common port mappings
|
|
565
458
|
*/
|
|
566
459
|
getInvitationUrl(token, baseUrl) {
|
|
567
460
|
let base = baseUrl;
|
|
568
|
-
if (!base
|
|
461
|
+
if (!base) {
|
|
569
462
|
base = process.env.MARVIN_FRONTEND_URL;
|
|
570
463
|
if (!base && process.env.MARVIN_API_URL) {
|
|
571
464
|
const apiUrl = process.env.MARVIN_API_URL;
|
|
@@ -577,17 +470,11 @@ var InvitesModule = class {
|
|
|
577
470
|
base = apiUrl;
|
|
578
471
|
}
|
|
579
472
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
if (typeof window !== "undefined" && window.location) {
|
|
583
|
-
base = window.location.origin;
|
|
584
|
-
} else {
|
|
585
|
-
throw new Error(
|
|
586
|
-
'baseUrl is required when not in Node.js environment. Pass the frontend URL as second argument: getInvitationUrl(token, "https://app.example.com")'
|
|
587
|
-
);
|
|
473
|
+
if (!base) {
|
|
474
|
+
base = "http://localhost:4321";
|
|
588
475
|
}
|
|
589
476
|
}
|
|
590
|
-
return `${base}/register?token=${
|
|
477
|
+
return `${base}/register?token=${token}`;
|
|
591
478
|
}
|
|
592
479
|
};
|
|
593
480
|
|
|
@@ -636,63 +523,11 @@ var NotificationsModule = class {
|
|
|
636
523
|
};
|
|
637
524
|
|
|
638
525
|
// src/platform/webhooks.ts
|
|
639
|
-
init_core();
|
|
640
526
|
var WebhooksModule = class {
|
|
641
527
|
constructor(http) {
|
|
642
528
|
this.http = http;
|
|
643
529
|
}
|
|
644
530
|
http;
|
|
645
|
-
/**
|
|
646
|
-
* Validate webhook URL to prevent SSRF attacks
|
|
647
|
-
*/
|
|
648
|
-
validateWebhookUrl(url) {
|
|
649
|
-
if (!url || typeof url !== "string") {
|
|
650
|
-
throw new MarvinValidationError("Webhook URL is required and must be a string");
|
|
651
|
-
}
|
|
652
|
-
let parsed;
|
|
653
|
-
try {
|
|
654
|
-
parsed = new URL(url);
|
|
655
|
-
} catch {
|
|
656
|
-
throw new MarvinValidationError("Invalid webhook URL format. Expected: https://example.com/webhook");
|
|
657
|
-
}
|
|
658
|
-
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
659
|
-
throw new MarvinValidationError(
|
|
660
|
-
`Webhook URL must use HTTP or HTTPS protocol. Got: ${parsed.protocol}`
|
|
661
|
-
);
|
|
662
|
-
}
|
|
663
|
-
const hostname = parsed.hostname.toLowerCase();
|
|
664
|
-
const blockedHosts = [
|
|
665
|
-
"localhost",
|
|
666
|
-
"127.0.0.1",
|
|
667
|
-
"0.0.0.0",
|
|
668
|
-
"::1",
|
|
669
|
-
"169.254.169.254",
|
|
670
|
-
// AWS metadata service
|
|
671
|
-
"[::]"
|
|
672
|
-
];
|
|
673
|
-
if (blockedHosts.some((blocked) => hostname === blocked || hostname.includes(blocked))) {
|
|
674
|
-
throw new MarvinValidationError(
|
|
675
|
-
"Webhook URL cannot target localhost or internal network addresses"
|
|
676
|
-
);
|
|
677
|
-
}
|
|
678
|
-
const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
679
|
-
const match = hostname.match(ipv4Regex);
|
|
680
|
-
if (match) {
|
|
681
|
-
const octets = match.slice(1).map(Number);
|
|
682
|
-
if (octets[0] === 10) {
|
|
683
|
-
throw new MarvinValidationError("Webhook URL cannot target private IP range (10.x.x.x)");
|
|
684
|
-
}
|
|
685
|
-
if (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31) {
|
|
686
|
-
throw new MarvinValidationError("Webhook URL cannot target private IP range (172.16-31.x.x)");
|
|
687
|
-
}
|
|
688
|
-
if (octets[0] === 192 && octets[1] === 168) {
|
|
689
|
-
throw new MarvinValidationError("Webhook URL cannot target private IP range (192.168.x.x)");
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (url.length > 2048) {
|
|
693
|
-
throw new MarvinValidationError("Webhook URL exceeds maximum length of 2048 characters");
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
531
|
/**
|
|
697
532
|
* List all webhooks for the current workspace
|
|
698
533
|
*/
|
|
@@ -704,43 +539,31 @@ var WebhooksModule = class {
|
|
|
704
539
|
* Get a webhook by ID
|
|
705
540
|
*/
|
|
706
541
|
async get(id) {
|
|
707
|
-
|
|
708
|
-
return this.http.get(`/api/groups/webhooks/${validId}`);
|
|
542
|
+
return this.http.get(`/api/groups/webhooks/${id}`);
|
|
709
543
|
}
|
|
710
544
|
/**
|
|
711
545
|
* Create a new webhook
|
|
712
|
-
* Validates URL to prevent SSRF attacks
|
|
713
546
|
*/
|
|
714
547
|
async create(data) {
|
|
715
|
-
if (data.url) {
|
|
716
|
-
this.validateWebhookUrl(data.url);
|
|
717
|
-
}
|
|
718
548
|
return this.http.post("/api/groups/webhooks", data);
|
|
719
549
|
}
|
|
720
550
|
/**
|
|
721
551
|
* Update a webhook
|
|
722
|
-
* Validates URL if provided to prevent SSRF attacks
|
|
723
552
|
*/
|
|
724
553
|
async update(id, data) {
|
|
725
|
-
|
|
726
|
-
if (data.url) {
|
|
727
|
-
this.validateWebhookUrl(data.url);
|
|
728
|
-
}
|
|
729
|
-
return this.http.put(`/api/groups/webhooks/${validId}`, data);
|
|
554
|
+
return this.http.put(`/api/groups/webhooks/${id}`, data);
|
|
730
555
|
}
|
|
731
556
|
/**
|
|
732
557
|
* Delete a webhook
|
|
733
558
|
*/
|
|
734
559
|
async delete(id) {
|
|
735
|
-
|
|
736
|
-
await this.http.delete(`/api/groups/webhooks/${validId}`);
|
|
560
|
+
await this.http.delete(`/api/groups/webhooks/${id}`);
|
|
737
561
|
}
|
|
738
562
|
/**
|
|
739
563
|
* Test a webhook
|
|
740
564
|
*/
|
|
741
565
|
async test(id) {
|
|
742
|
-
|
|
743
|
-
return this.http.post(`/api/groups/webhooks/${validId}/test`, {});
|
|
566
|
+
return this.http.post(`/api/groups/webhooks/${id}/test`, {});
|
|
744
567
|
}
|
|
745
568
|
/**
|
|
746
569
|
* Rerun failed webhooks
|
|
@@ -832,7 +655,6 @@ var AdminSystemModule = class {
|
|
|
832
655
|
}
|
|
833
656
|
/**
|
|
834
657
|
* Update email settings
|
|
835
|
-
* Note: Password field is write-only and will not be returned in response
|
|
836
658
|
*/
|
|
837
659
|
async updateEmailSettings(data) {
|
|
838
660
|
return this.http.put("/api/admin/email", data);
|
|
@@ -1108,235 +930,7 @@ var ThemeModule = class {
|
|
|
1108
930
|
}
|
|
1109
931
|
};
|
|
1110
932
|
|
|
1111
|
-
// src/platform/emailTemplates.ts
|
|
1112
|
-
var EmailTemplatesClient = class {
|
|
1113
|
-
constructor(http) {
|
|
1114
|
-
this.http = http;
|
|
1115
|
-
}
|
|
1116
|
-
http;
|
|
1117
|
-
/**
|
|
1118
|
-
* List all email templates for the workspace
|
|
1119
|
-
* @param groupId - Workspace ID
|
|
1120
|
-
*/
|
|
1121
|
-
async list(groupId) {
|
|
1122
|
-
return this.http.get(`/api/platform/workspaces/${groupId}/email-templates`);
|
|
1123
|
-
}
|
|
1124
|
-
/**
|
|
1125
|
-
* Get a specific email template
|
|
1126
|
-
* @param groupId - Workspace ID
|
|
1127
|
-
* @param templateId - Template ID
|
|
1128
|
-
*/
|
|
1129
|
-
async get(groupId, templateId) {
|
|
1130
|
-
return this.http.get(`/api/platform/workspaces/${groupId}/email-templates/${templateId}`);
|
|
1131
|
-
}
|
|
1132
|
-
/**
|
|
1133
|
-
* Create a new email template
|
|
1134
|
-
* @param groupId - Workspace ID
|
|
1135
|
-
* @param data - Template data
|
|
1136
|
-
*/
|
|
1137
|
-
async create(groupId, data) {
|
|
1138
|
-
return this.http.post(`/api/platform/workspaces/${groupId}/email-templates`, data);
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
* Update an email template
|
|
1142
|
-
* @param groupId - Workspace ID
|
|
1143
|
-
* @param templateId - Template ID
|
|
1144
|
-
* @param data - Updated template data
|
|
1145
|
-
*/
|
|
1146
|
-
async update(groupId, templateId, data) {
|
|
1147
|
-
return this.http.patch(`/api/platform/workspaces/${groupId}/email-templates/${templateId}`, data);
|
|
1148
|
-
}
|
|
1149
|
-
/**
|
|
1150
|
-
* Delete an email template
|
|
1151
|
-
* @param groupId - Workspace ID
|
|
1152
|
-
* @param templateId - Template ID
|
|
1153
|
-
*/
|
|
1154
|
-
async delete(groupId, templateId) {
|
|
1155
|
-
await this.http.delete(`/api/platform/workspaces/${groupId}/email-templates/${templateId}`);
|
|
1156
|
-
}
|
|
1157
|
-
/**
|
|
1158
|
-
* Send a test email using a template
|
|
1159
|
-
* @param groupId - Workspace ID
|
|
1160
|
-
* @param templateId - Template ID
|
|
1161
|
-
* @param recipientEmail - Test recipient email address
|
|
1162
|
-
*/
|
|
1163
|
-
async sendTest(groupId, templateId, recipientEmail) {
|
|
1164
|
-
return this.http.post(`/api/platform/workspaces/${groupId}/email-templates/${templateId}/test`, {
|
|
1165
|
-
recipient_email: recipientEmail
|
|
1166
|
-
});
|
|
1167
|
-
}
|
|
1168
|
-
};
|
|
1169
|
-
|
|
1170
|
-
// src/platform/scheduledTasks.ts
|
|
1171
|
-
var ScheduledTasksModule = class {
|
|
1172
|
-
constructor(http) {
|
|
1173
|
-
this.http = http;
|
|
1174
|
-
}
|
|
1175
|
-
http;
|
|
1176
|
-
/**
|
|
1177
|
-
* List all scheduled tasks for the current workspace
|
|
1178
|
-
*/
|
|
1179
|
-
async list() {
|
|
1180
|
-
return this.http.get("/api/platform/scheduled-tasks");
|
|
1181
|
-
}
|
|
1182
|
-
/**
|
|
1183
|
-
* Get a scheduled task by ID or slug
|
|
1184
|
-
*/
|
|
1185
|
-
async get(idOrSlug) {
|
|
1186
|
-
const validIdOrSlug = this.http.validatePathParam(idOrSlug, "idOrSlug");
|
|
1187
|
-
return this.http.get(`/api/platform/scheduled-tasks/${validIdOrSlug}`);
|
|
1188
|
-
}
|
|
1189
|
-
/**
|
|
1190
|
-
* Create a new scheduled task
|
|
1191
|
-
*/
|
|
1192
|
-
async create(data) {
|
|
1193
|
-
return this.http.post("/api/platform/scheduled-tasks", data);
|
|
1194
|
-
}
|
|
1195
|
-
/**
|
|
1196
|
-
* Update a scheduled task
|
|
1197
|
-
*/
|
|
1198
|
-
async update(idOrSlug, data) {
|
|
1199
|
-
const validIdOrSlug = this.http.validatePathParam(idOrSlug, "idOrSlug");
|
|
1200
|
-
return this.http.patch(`/api/platform/scheduled-tasks/${validIdOrSlug}`, data);
|
|
1201
|
-
}
|
|
1202
|
-
/**
|
|
1203
|
-
* Delete a scheduled task
|
|
1204
|
-
*/
|
|
1205
|
-
async delete(idOrSlug) {
|
|
1206
|
-
await this.http.delete(`/api/platform/scheduled-tasks/${idOrSlug}`);
|
|
1207
|
-
}
|
|
1208
|
-
/**
|
|
1209
|
-
* Manually trigger task execution (bypass schedule)
|
|
1210
|
-
*/
|
|
1211
|
-
async execute(idOrSlug) {
|
|
1212
|
-
await this.http.post(`/api/platform/scheduled-tasks/${idOrSlug}/execute`, {});
|
|
1213
|
-
}
|
|
1214
|
-
/**
|
|
1215
|
-
* Get task execution history
|
|
1216
|
-
*/
|
|
1217
|
-
async history(idOrSlug, options) {
|
|
1218
|
-
const params = new URLSearchParams();
|
|
1219
|
-
if (options?.limit) {
|
|
1220
|
-
params.set("limit", options.limit.toString());
|
|
1221
|
-
}
|
|
1222
|
-
const query = params.toString() ? `?${params.toString()}` : "";
|
|
1223
|
-
return this.http.get(
|
|
1224
|
-
`/api/platform/scheduled-tasks/${idOrSlug}/history${query}`
|
|
1225
|
-
);
|
|
1226
|
-
}
|
|
1227
|
-
/**
|
|
1228
|
-
* Get available task types
|
|
1229
|
-
*/
|
|
1230
|
-
async taskTypes(options) {
|
|
1231
|
-
const params = new URLSearchParams();
|
|
1232
|
-
if (options?.detailed) {
|
|
1233
|
-
params.set("detailed", "true");
|
|
1234
|
-
}
|
|
1235
|
-
const query = params.toString() ? `?${params.toString()}` : "";
|
|
1236
|
-
return this.http.get(`/api/platform/scheduled-tasks/task-types${query}`);
|
|
1237
|
-
}
|
|
1238
|
-
};
|
|
1239
|
-
|
|
1240
|
-
// src/platform/forms.ts
|
|
1241
|
-
init_core();
|
|
1242
|
-
var FormsModule = class {
|
|
1243
|
-
constructor(http) {
|
|
1244
|
-
this.http = http;
|
|
1245
|
-
}
|
|
1246
|
-
http;
|
|
1247
|
-
/**
|
|
1248
|
-
* Validate form submission data
|
|
1249
|
-
* - Prevents XSS by checking for script tags
|
|
1250
|
-
* - Validates data is a proper object
|
|
1251
|
-
* - Checks for reasonable size limits
|
|
1252
|
-
*/
|
|
1253
|
-
validateFormData(data) {
|
|
1254
|
-
if (!data || typeof data !== "object") {
|
|
1255
|
-
throw new MarvinValidationError("Form data must be a valid object");
|
|
1256
|
-
}
|
|
1257
|
-
const jsonString = JSON.stringify(data);
|
|
1258
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
1259
|
-
if (sizeInBytes > 1024 * 1024) {
|
|
1260
|
-
throw new MarvinValidationError("Form data exceeds maximum size of 1MB");
|
|
1261
|
-
}
|
|
1262
|
-
const checkForScripts = (value) => {
|
|
1263
|
-
if (typeof value === "string") {
|
|
1264
|
-
if (/<script[\s\S]*?>[\s\S]*?<\/script>/gi.test(value)) {
|
|
1265
|
-
throw new MarvinValidationError("Form data contains potentially malicious content");
|
|
1266
|
-
}
|
|
1267
|
-
} else if (Array.isArray(value)) {
|
|
1268
|
-
value.forEach(checkForScripts);
|
|
1269
|
-
} else if (value && typeof value === "object") {
|
|
1270
|
-
Object.values(value).forEach(checkForScripts);
|
|
1271
|
-
}
|
|
1272
|
-
};
|
|
1273
|
-
Object.values(data).forEach(checkForScripts);
|
|
1274
|
-
}
|
|
1275
|
-
/**
|
|
1276
|
-
* List all forms
|
|
1277
|
-
*/
|
|
1278
|
-
async list() {
|
|
1279
|
-
return this.http.get("/api/platform/forms");
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
* Get a single form by ID
|
|
1283
|
-
*/
|
|
1284
|
-
async get(id) {
|
|
1285
|
-
const validId = this.http.validatePathParam(id, "id");
|
|
1286
|
-
return this.http.get(`/api/platform/forms/${validId}`);
|
|
1287
|
-
}
|
|
1288
|
-
/**
|
|
1289
|
-
* Create a new form
|
|
1290
|
-
*/
|
|
1291
|
-
async create(data) {
|
|
1292
|
-
return this.http.post("/api/platform/forms", data);
|
|
1293
|
-
}
|
|
1294
|
-
/**
|
|
1295
|
-
* Update a form
|
|
1296
|
-
*/
|
|
1297
|
-
async update(id, data) {
|
|
1298
|
-
const validId = this.http.validatePathParam(id, "id");
|
|
1299
|
-
return this.http.patch(`/api/platform/forms/${validId}`, data);
|
|
1300
|
-
}
|
|
1301
|
-
/**
|
|
1302
|
-
* Delete a form
|
|
1303
|
-
*/
|
|
1304
|
-
async delete(id) {
|
|
1305
|
-
return this.http.delete(`/api/platform/forms/${id}`);
|
|
1306
|
-
}
|
|
1307
|
-
/**
|
|
1308
|
-
* Get submissions for a form
|
|
1309
|
-
*/
|
|
1310
|
-
async getSubmissions(formId) {
|
|
1311
|
-
return this.http.get(`/api/platform/forms/${formId}/submissions`);
|
|
1312
|
-
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Get a published form by slug (Publishing API - public access)
|
|
1315
|
-
*/
|
|
1316
|
-
async getPublishedForm(slug) {
|
|
1317
|
-
return this.http.get(`/api/publish/forms/${slug}`);
|
|
1318
|
-
}
|
|
1319
|
-
/**
|
|
1320
|
-
* Submit data to a published form (Publishing API - public access)
|
|
1321
|
-
* Validates data before submission to prevent XSS and malicious content
|
|
1322
|
-
*/
|
|
1323
|
-
async submitForm(slug, data) {
|
|
1324
|
-
const validSlug = this.http.validatePathParam(slug, "form slug");
|
|
1325
|
-
this.validateFormData(data);
|
|
1326
|
-
return this.http.post(`/api/publish/forms/${validSlug}/submit`, {
|
|
1327
|
-
dataJson: data
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
};
|
|
1331
|
-
|
|
1332
933
|
// src/platform/client.ts
|
|
1333
|
-
function createPlatformConfigFromEnv(overrides) {
|
|
1334
|
-
return {
|
|
1335
|
-
apiUrl: overrides?.apiUrl || process.env.MARVIN_API_URL || "http://localhost:8080",
|
|
1336
|
-
userToken: overrides?.userToken || process.env.MARVIN_USER_TOKEN,
|
|
1337
|
-
credentials: overrides?.credentials || "include"
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
934
|
var PlatformClient = class extends HttpClient {
|
|
1341
935
|
entries;
|
|
1342
936
|
collections;
|
|
@@ -1354,16 +948,13 @@ var PlatformClient = class extends HttpClient {
|
|
|
1354
948
|
eventLog;
|
|
1355
949
|
session;
|
|
1356
950
|
theme;
|
|
1357
|
-
emailTemplates;
|
|
1358
|
-
scheduledTasks;
|
|
1359
|
-
forms;
|
|
1360
951
|
// Admin modules
|
|
1361
952
|
adminUsers;
|
|
1362
953
|
adminSystem;
|
|
1363
954
|
adminMaintenance;
|
|
1364
955
|
constructor(config) {
|
|
1365
956
|
const httpConfig = {
|
|
1366
|
-
baseUrl: config.apiUrl
|
|
957
|
+
baseUrl: config.apiUrl,
|
|
1367
958
|
auth: new SessionAuth(config.userToken),
|
|
1368
959
|
credentials: config.credentials || "include"
|
|
1369
960
|
};
|
|
@@ -1384,17 +975,13 @@ var PlatformClient = class extends HttpClient {
|
|
|
1384
975
|
this.eventLog = new EventLogModule(this);
|
|
1385
976
|
this.session = new AuthModule(this);
|
|
1386
977
|
this.theme = new ThemeModule(this);
|
|
1387
|
-
this.emailTemplates = new EmailTemplatesClient(this);
|
|
1388
|
-
this.scheduledTasks = new ScheduledTasksModule(this);
|
|
1389
|
-
this.forms = new FormsModule(this);
|
|
1390
978
|
this.adminUsers = new AdminUsersModule(this);
|
|
1391
979
|
this.adminSystem = new AdminSystemModule(this);
|
|
1392
980
|
this.adminMaintenance = new AdminMaintenanceModule(this);
|
|
1393
981
|
}
|
|
1394
982
|
};
|
|
1395
983
|
function createPlatformClient(config) {
|
|
1396
|
-
|
|
1397
|
-
return new PlatformClient(finalConfig);
|
|
984
|
+
return new PlatformClient(config);
|
|
1398
985
|
}
|
|
1399
986
|
export {
|
|
1400
987
|
APIClientsModule,
|
|
@@ -1404,22 +991,18 @@ export {
|
|
|
1404
991
|
AssetsModule,
|
|
1405
992
|
AuthModule,
|
|
1406
993
|
CollectionsModule,
|
|
1407
|
-
EmailTemplatesClient,
|
|
1408
994
|
EntriesModule,
|
|
1409
995
|
EntryTypesModule,
|
|
1410
996
|
EventLogModule,
|
|
1411
997
|
EventsModule,
|
|
1412
|
-
FormsModule,
|
|
1413
998
|
InvitesModule,
|
|
1414
999
|
NotificationsModule,
|
|
1415
1000
|
PlatformClient,
|
|
1416
1001
|
ResourcesModule,
|
|
1417
|
-
ScheduledTasksModule,
|
|
1418
1002
|
ThemeModule,
|
|
1419
1003
|
UserModule,
|
|
1420
1004
|
WebhooksModule,
|
|
1421
1005
|
WorkspaceMembersModule,
|
|
1422
1006
|
WorkspacesModule,
|
|
1423
|
-
createPlatformClient
|
|
1424
|
-
createPlatformConfigFromEnv
|
|
1007
|
+
createPlatformClient
|
|
1425
1008
|
};
|