@inneropen/marvin-sdk 2.0.0 → 3.0.0

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/index.js CHANGED
@@ -1,3 +1,19 @@
1
+ import {
2
+ Collection,
3
+ Entry,
4
+ MarvinClient,
5
+ Resource,
6
+ Workspace,
7
+ config_exports,
8
+ createConfigFromEnv,
9
+ init_collection,
10
+ init_config,
11
+ init_entry,
12
+ init_marvin,
13
+ init_resource,
14
+ init_workspace,
15
+ marvin_exports
16
+ } from "./chunk-SGZG7U7V.js";
1
17
  import {
2
18
  BearerTokenAuth,
3
19
  HttpClient,
@@ -6,806 +22,21 @@ import {
6
22
  MarvinCache,
7
23
  MarvinConfigError,
8
24
  MarvinError,
25
+ MarvinNetworkError,
26
+ MarvinNotFoundError,
27
+ MarvinServerError,
9
28
  MarvinValidationError,
10
29
  NoAuth,
11
30
  SessionAuth,
12
- __esm,
13
- __export,
14
31
  __toCommonJS,
15
32
  createPaginatedResponse,
16
33
  extractData,
17
34
  init_core,
18
35
  isPaginatedResponse,
19
36
  offsetToPage,
20
- pageToOffset
21
- } from "./chunk-25F3IF6S.js";
22
-
23
- // src/client/config.ts
24
- var config_exports = {};
25
- __export(config_exports, {
26
- createConfigFromEnv: () => createConfigFromEnv,
27
- validateConfig: () => validateConfig
28
- });
29
- function validateConfig(config) {
30
- if (!config.apiUrl) {
31
- throw new Error("MARVIN_API_URL is required");
32
- }
33
- if (!config.siteClientToken) {
34
- throw new Error("MARVIN_SITE_CLIENT_TOKEN is required");
35
- }
36
- if (!config.workspaceSlug) {
37
- throw new Error("MARVIN_WORKSPACE_SLUG is required");
38
- }
39
- }
40
- function createConfigFromEnv(overrides) {
41
- return {
42
- apiUrl: overrides?.apiUrl || process.env.MARVIN_API_URL || "",
43
- siteClientToken: overrides?.siteClientToken || process.env.MARVIN_SITE_CLIENT_TOKEN || "",
44
- workspaceSlug: overrides?.workspaceSlug || process.env.MARVIN_WORKSPACE_SLUG || "",
45
- autoInitialize: overrides?.autoInitialize ?? false,
46
- cacheDuration: overrides?.cacheDuration ?? 5 * 60 * 1e3
47
- // 5 minutes
48
- };
49
- }
50
- var init_config = __esm({
51
- "src/client/config.ts"() {
52
- "use strict";
53
- }
54
- });
55
-
56
- // src/client/http.ts
57
- var MarvinHttpClient;
58
- var init_http = __esm({
59
- "src/client/http.ts"() {
60
- "use strict";
61
- init_core();
62
- MarvinHttpClient = class extends HttpClient {
63
- constructor(config) {
64
- super({
65
- baseUrl: config.apiUrl,
66
- auth: new BearerTokenAuth(config.siteClientToken),
67
- credentials: "same-origin"
68
- });
69
- }
70
- /**
71
- * Fetch endpoint (backward compatibility)
72
- */
73
- async fetch(endpoint) {
74
- return this.get(endpoint);
75
- }
76
- };
77
- }
78
- });
79
-
80
- // src/entries/entry.ts
81
- var Entry;
82
- var init_entry = __esm({
83
- "src/entries/entry.ts"() {
84
- "use strict";
85
- Entry = class {
86
- constructor(data, http, workspaceSlug) {
87
- this.data = data;
88
- this.http = http;
89
- this.workspaceSlug = workspaceSlug;
90
- }
91
- data;
92
- http;
93
- workspaceSlug;
94
- // Expose all entry data as properties
95
- get id() {
96
- return this.data.id;
97
- }
98
- get title() {
99
- return this.data.title;
100
- }
101
- get slug() {
102
- return this.data.slug;
103
- }
104
- get summary() {
105
- return this.data.summary;
106
- }
107
- get description() {
108
- return this.data.description;
109
- }
110
- /**
111
- * @deprecated Use field('body') or dataJson instead. Will be removed in v3.0.0
112
- */
113
- get contentMarkdown() {
114
- return this.data.contentMarkdown;
115
- }
116
- /**
117
- * Schema-driven content data (replaces contentMarkdown in v2.0.0).
118
- * Access specific fields using the field() helper method.
119
- * @since 2.0.0
120
- */
121
- get dataJson() {
122
- return this.data.dataJson;
123
- }
124
- get metadata() {
125
- return this.data.metadata;
126
- }
127
- get status() {
128
- return this.data.status;
129
- }
130
- get publishedAt() {
131
- return this.data.publishedAt;
132
- }
133
- get createdAt() {
134
- return this.data.createdAt;
135
- }
136
- get updatedAt() {
137
- return this.data.updatedAt;
138
- }
139
- get entryTypeId() {
140
- return this.data.entryTypeId;
141
- }
142
- get entryType() {
143
- return this.data.entryType;
144
- }
145
- /**
146
- * Get entry assets
147
- */
148
- get assets() {
149
- return this.data.assets || [];
150
- }
151
- /**
152
- * Get entry collections
153
- */
154
- get collections() {
155
- return this.data.collections || [];
156
- }
157
- /**
158
- * Get a specific field value from the entry's schema-driven content (dataJson).
159
- *
160
- * @param key - Field key as defined in the entry type's schema
161
- * @returns The field value, or undefined if not present
162
- * @since 2.0.0
163
- *
164
- * @example
165
- * ```typescript
166
- * const entry = await client.entries.get('my-entry');
167
- * const body = entry.field('body'); // Get markdown body
168
- * const difficulty = entry.field('difficulty'); // Get difficulty level
169
- * const heroImage = entry.field('heroImage'); // Get hero image UUID
170
- * ```
171
- */
172
- field(key) {
173
- return this.data.dataJson?.[key];
174
- }
175
- /**
176
- * Get all fields from the entry's schema-driven content.
177
- * @since 2.0.0
178
- */
179
- get fields() {
180
- return this.data.dataJson || {};
181
- }
182
- /**
183
- * Get related entries (future)
184
- */
185
- async relatedEntries() {
186
- throw new Error("Related entries not yet implemented");
187
- }
188
- /**
189
- * Get raw entry data
190
- */
191
- toJSON() {
192
- return this.data;
193
- }
194
- };
195
- }
196
- });
197
-
198
- // src/entries/entries.ts
199
- var EntriesModule;
200
- var init_entries = __esm({
201
- "src/entries/entries.ts"() {
202
- "use strict";
203
- init_entry();
204
- EntriesModule = class {
205
- constructor(http, workspaceSlug) {
206
- this.http = http;
207
- this.workspaceSlug = workspaceSlug;
208
- }
209
- http;
210
- workspaceSlug;
211
- /**
212
- * Get all published entries
213
- */
214
- async list(options = {}) {
215
- const queryString = this.http.buildQueryString({
216
- entry_type: options.entryType,
217
- collection: options.collection,
218
- limit: options.limit,
219
- offset: options.offset
220
- // Don't send status - backend always returns published
221
- });
222
- const endpoint = `/api/publish/${this.workspaceSlug}/entries${queryString}`;
223
- const response = await this.http.fetch(endpoint);
224
- return response.data || [];
225
- }
226
- /**
227
- * Get a single entry by slug
228
- */
229
- async get(slug) {
230
- const endpoint = `/api/publish/${this.workspaceSlug}/entries/${slug}`;
231
- const data = await this.http.fetch(endpoint);
232
- return new Entry(data, this.http, this.workspaceSlug);
233
- }
234
- /**
235
- * Convenience: Get all pages
236
- */
237
- async pages(options) {
238
- return this.list({ ...options, entryType: "page" });
239
- }
240
- /**
241
- * Convenience: Get all blog posts
242
- */
243
- async posts(options) {
244
- return this.list({ ...options, entryType: "blog" });
245
- }
246
- /**
247
- * Convenience: Get all projects
248
- */
249
- async projects(options) {
250
- return this.list({ ...options, entryType: "project" });
251
- }
252
- };
253
- }
254
- });
255
-
256
- // src/collections/collection.ts
257
- var Collection;
258
- var init_collection = __esm({
259
- "src/collections/collection.ts"() {
260
- "use strict";
261
- Collection = class {
262
- constructor(data, http, workspaceSlug) {
263
- this.data = data;
264
- this.http = http;
265
- this.workspaceSlug = workspaceSlug;
266
- }
267
- data;
268
- http;
269
- workspaceSlug;
270
- // Expose all collection data as properties
271
- get id() {
272
- return this.data.id;
273
- }
274
- get name() {
275
- return this.data.name;
276
- }
277
- get slug() {
278
- return this.data.slug;
279
- }
280
- get description() {
281
- return this.data.description;
282
- }
283
- get icon() {
284
- return this.data.icon;
285
- }
286
- get color() {
287
- return this.data.color;
288
- }
289
- get sortOrder() {
290
- return this.data.sortOrder;
291
- }
292
- get isSmart() {
293
- return this.data.isSmart;
294
- }
295
- get smartRules() {
296
- return this.data.smartRules;
297
- }
298
- get createdAt() {
299
- return this.data.createdAt;
300
- }
301
- get updatedAt() {
302
- return this.data.updatedAt;
303
- }
304
- /**
305
- * Get all entries in this collection
306
- */
307
- async entries() {
308
- return this.data.entries || [];
309
- }
310
- /**
311
- * Get assets in this collection (future)
312
- */
313
- async assets() {
314
- throw new Error("Collection assets not yet implemented");
315
- }
316
- /**
317
- * Get collection metadata (future)
318
- */
319
- async metadata() {
320
- throw new Error("Collection metadata not yet implemented");
321
- }
322
- /**
323
- * Get raw collection data
324
- */
325
- toJSON() {
326
- return this.data;
327
- }
328
- };
329
- }
330
- });
331
-
332
- // src/collections/collections.ts
333
- var CollectionsModule;
334
- var init_collections = __esm({
335
- "src/collections/collections.ts"() {
336
- "use strict";
337
- init_collection();
338
- CollectionsModule = class {
339
- constructor(http, workspaceSlug) {
340
- this.http = http;
341
- this.workspaceSlug = workspaceSlug;
342
- }
343
- http;
344
- workspaceSlug;
345
- /**
346
- * Get all collections
347
- */
348
- async list() {
349
- const endpoint = `/api/publish/${this.workspaceSlug}/collections`;
350
- const response = await this.http.fetch(endpoint);
351
- return response.data || [];
352
- }
353
- /**
354
- * Get a single collection by slug
355
- */
356
- async get(slug) {
357
- const endpoint = `/api/publish/${this.workspaceSlug}/collections/${slug}`;
358
- const data = await this.http.fetch(endpoint);
359
- return new Collection(data, this.http, this.workspaceSlug);
360
- }
361
- /**
362
- * Get entries in a collection
363
- */
364
- async entries(slug) {
365
- const collection = await this.get(slug);
366
- return collection.entries();
367
- }
368
- };
369
- }
370
- });
371
-
372
- // src/assets/assets.ts
373
- var AssetsModule;
374
- var init_assets = __esm({
375
- "src/assets/assets.ts"() {
376
- "use strict";
377
- AssetsModule = class {
378
- constructor(http, workspaceSlug) {
379
- this.http = http;
380
- this.workspaceSlug = workspaceSlug;
381
- }
382
- http;
383
- workspaceSlug;
384
- /**
385
- * Get all published assets
386
- */
387
- async list(options = {}) {
388
- const queryString = this.http.buildQueryString({
389
- type: options.type,
390
- limit: options.limit,
391
- offset: options.offset
392
- });
393
- const endpoint = `/api/publish/${this.workspaceSlug}/assets${queryString}`;
394
- const response = await this.http.fetch(endpoint);
395
- return response.data || [];
396
- }
397
- /**
398
- * Get a single published asset by slug or ID
399
- */
400
- async get(slugOrId) {
401
- const endpoint = `/api/publish/${this.workspaceSlug}/assets/${slugOrId}`;
402
- return this.http.fetch(endpoint);
403
- }
404
- /**
405
- * Convenience: Get all images
406
- */
407
- async images(options) {
408
- return this.list({ ...options, type: "image" });
409
- }
410
- /**
411
- * Convenience: Get all videos
412
- */
413
- async videos(options) {
414
- return this.list({ ...options, type: "video" });
415
- }
416
- /**
417
- * Convenience: Get all documents
418
- */
419
- async documents(options) {
420
- return this.list({ ...options, type: "document" });
421
- }
422
- };
423
- }
424
- });
425
-
426
- // src/resources/resource.ts
427
- var Resource;
428
- var init_resource = __esm({
429
- "src/resources/resource.ts"() {
430
- "use strict";
431
- Resource = class {
432
- constructor(data, http, workspaceSlug) {
433
- this.data = data;
434
- this.http = http;
435
- this.workspaceSlug = workspaceSlug;
436
- }
437
- data;
438
- http;
439
- workspaceSlug;
440
- // Expose all resource data as properties
441
- get id() {
442
- return this.data.id;
443
- }
444
- get name() {
445
- return this.data.name;
446
- }
447
- get slug() {
448
- return this.data.slug;
449
- }
450
- get resourceType() {
451
- return this.data.resourceType;
452
- }
453
- get description() {
454
- return this.data.description;
455
- }
456
- get externalId() {
457
- return this.data.externalId;
458
- }
459
- get url() {
460
- return this.data.url;
461
- }
462
- get metadata() {
463
- return this.data.metadata;
464
- }
465
- get createdAt() {
466
- return this.data.createdAt;
467
- }
468
- get updatedAt() {
469
- return this.data.updatedAt;
470
- }
471
- /**
472
- * Get all entries that reference this resource
473
- */
474
- async entries() {
475
- const endpoint = `/api/publish/${this.workspaceSlug}/resources/${this.data.slug}/entries`;
476
- return this.http.fetch(endpoint);
477
- }
478
- /**
479
- * Get assets related to this resource (future)
480
- */
481
- async assets() {
482
- throw new Error("Resource assets not yet implemented");
483
- }
484
- /**
485
- * Get raw resource data
486
- */
487
- toJSON() {
488
- return this.data;
489
- }
490
- };
491
- }
492
- });
493
-
494
- // src/resources/resources.ts
495
- var ResourcesModule;
496
- var init_resources = __esm({
497
- "src/resources/resources.ts"() {
498
- "use strict";
499
- init_resource();
500
- ResourcesModule = class {
501
- constructor(http, workspaceSlug) {
502
- this.http = http;
503
- this.workspaceSlug = workspaceSlug;
504
- }
505
- http;
506
- workspaceSlug;
507
- /**
508
- * Get all published resources
509
- */
510
- async list(options = {}) {
511
- const queryString = this.http.buildQueryString({
512
- resource_type: options.resourceType,
513
- limit: options.limit,
514
- offset: options.offset
515
- });
516
- const endpoint = `/api/publish/${this.workspaceSlug}/resources${queryString}`;
517
- const response = await this.http.fetch(endpoint);
518
- return response.data || [];
519
- }
520
- /**
521
- * Get a single resource by slug
522
- */
523
- async get(slug) {
524
- const endpoint = `/api/publish/${this.workspaceSlug}/resources/${slug}`;
525
- const data = await this.http.fetch(endpoint);
526
- return new Resource(data, this.http, this.workspaceSlug);
527
- }
528
- /**
529
- * Get entries that reference this resource
530
- */
531
- async entries(slug) {
532
- const resource = await this.get(slug);
533
- return resource.entries();
534
- }
535
- };
536
- }
537
- });
538
-
539
- // src/workspaces/workspace.ts
540
- var Workspace;
541
- var init_workspace = __esm({
542
- "src/workspaces/workspace.ts"() {
543
- "use strict";
544
- init_entries();
545
- init_collections();
546
- init_assets();
547
- init_resources();
548
- Workspace = class {
549
- constructor(http, slug) {
550
- this.http = http;
551
- this._slug = slug;
552
- this.entries = new EntriesModule(http, slug);
553
- this.collections = new CollectionsModule(http, slug);
554
- this.assets = new AssetsModule(http, slug);
555
- this.resources = new ResourcesModule(http, slug);
556
- }
557
- http;
558
- _site = null;
559
- _slug;
560
- entries;
561
- collections;
562
- assets;
563
- resources;
564
- /**
565
- * Get workspace slug
566
- */
567
- get slug() {
568
- return this._slug;
569
- }
570
- /**
571
- * Get site configuration (cached after first load)
572
- */
573
- get site() {
574
- return this._site;
575
- }
576
- /**
577
- * Load site configuration
578
- */
579
- async loadSite() {
580
- const endpoint = `/api/publish/${this._slug}/site`;
581
- this._site = await this.http.fetch(endpoint);
582
- return this._site;
583
- }
584
- /**
585
- * Get workspace info (name and slug only)
586
- */
587
- async getInfo() {
588
- const endpoint = `/api/publish/${this._slug}`;
589
- return this.http.fetch(endpoint);
590
- }
591
- /**
592
- * Get workspace settings (future)
593
- */
594
- async settings() {
595
- throw new Error("Workspace settings not yet implemented");
596
- }
597
- };
598
- }
599
- });
600
-
601
- // src/client/marvin.ts
602
- var marvin_exports = {};
603
- __export(marvin_exports, {
604
- MarvinClient: () => MarvinClient
605
- });
606
- var MarvinClient;
607
- var init_marvin = __esm({
608
- "src/client/marvin.ts"() {
609
- "use strict";
610
- init_config();
611
- init_http();
612
- init_core();
613
- init_workspace();
614
- MarvinClient = class {
615
- constructor(config) {
616
- this.config = config;
617
- validateConfig(config);
618
- this.http = new MarvinHttpClient(config);
619
- this.cache = new MarvinCache(config.cacheDuration);
620
- this.workspace = new Workspace(this.http, config.workspaceSlug);
621
- if (config.autoInitialize) {
622
- this.initialize();
623
- }
624
- }
625
- config;
626
- http;
627
- cache;
628
- workspace;
629
- initialized = false;
630
- /**
631
- * Initialize the SDK
632
- * Preloads site configuration and metadata
633
- */
634
- async initialize() {
635
- if (this.initialized) return;
636
- try {
637
- await this.workspace.loadSite();
638
- this.initialized = true;
639
- } catch (error) {
640
- console.warn("Marvin SDK initialization warning:", error);
641
- }
642
- }
643
- // ======================
644
- // Workspace-First API
645
- // ======================
646
- /**
647
- * Get the workspace object
648
- */
649
- async getWorkspace() {
650
- if (!this.initialized) {
651
- await this.initialize();
652
- }
653
- return this.workspace;
654
- }
655
- /**
656
- * Get site configuration (cached)
657
- */
658
- get site() {
659
- return this.workspace.site;
660
- }
661
- /**
662
- * Get workspace info (name and slug)
663
- */
664
- async getWorkspaceInfo() {
665
- return this.workspace.getInfo();
666
- }
667
- /**
668
- * Get entries module
669
- */
670
- get entries() {
671
- return this.workspace.entries;
672
- }
673
- /**
674
- * Get collections module
675
- */
676
- get collections() {
677
- return this.workspace.collections;
678
- }
679
- /**
680
- * Get assets module
681
- */
682
- get assets() {
683
- return this.workspace.assets;
684
- }
685
- /**
686
- * Get resources module
687
- */
688
- get resources() {
689
- return this.workspace.resources;
690
- }
691
- // ======================
692
- // Convenience Methods
693
- // ======================
694
- /**
695
- * Get a single entry by slug
696
- */
697
- async entry(slug) {
698
- return this.workspace.entries.get(slug);
699
- }
700
- /**
701
- * Get a single collection by slug
702
- */
703
- async collection(slug) {
704
- return this.workspace.collections.get(slug);
705
- }
706
- /**
707
- * Get all pages
708
- */
709
- async pages(options) {
710
- return this.workspace.entries.pages(options);
711
- }
712
- /**
713
- * Get all blog posts
714
- */
715
- async posts(options) {
716
- return this.workspace.entries.posts(options);
717
- }
718
- /**
719
- * Get all projects
720
- */
721
- async projects(options) {
722
- return this.workspace.entries.projects(options);
723
- }
724
- /**
725
- * Get a single resource by slug
726
- */
727
- async resource(slug) {
728
- return this.workspace.resources.get(slug);
729
- }
730
- // ======================
731
- // Backwards-Compatible Publishing API
732
- // ======================
733
- /**
734
- * @deprecated Use workspace.site or marvin.site instead
735
- * Get site configuration
736
- */
737
- async getSite() {
738
- return this.workspace.loadSite();
739
- }
740
- /**
741
- * @deprecated Use workspace.entries.list() instead
742
- * Get all published entries
743
- */
744
- async getEntries(options) {
745
- return this.workspace.entries.list(options);
746
- }
747
- /**
748
- * @deprecated Use workspace.entries.get() instead
749
- * Get a single published entry by slug
750
- */
751
- async getEntry(slug) {
752
- const entry = await this.workspace.entries.get(slug);
753
- return entry.toJSON();
754
- }
755
- /**
756
- * @deprecated Use workspace.collections.list() instead
757
- * Get all collections
758
- */
759
- async getCollections() {
760
- return this.workspace.collections.list();
761
- }
762
- /**
763
- * @deprecated Use workspace.collections.get() instead
764
- * Get a single collection by slug
765
- */
766
- async getCollection(slug) {
767
- const collection = await this.workspace.collections.get(slug);
768
- return collection.toJSON();
769
- }
770
- /**
771
- * @deprecated Use workspace.collections.entries() instead
772
- * Get all entries in a collection
773
- */
774
- async getCollectionEntries(slug) {
775
- return this.workspace.collections.entries(slug);
776
- }
777
- /**
778
- * @deprecated Use workspace.assets.list() instead
779
- * Get all published assets
780
- */
781
- async getAssets(options) {
782
- return this.workspace.assets.list(options);
783
- }
784
- /**
785
- * @deprecated Use workspace.resources.list() instead
786
- * Get all published resources
787
- */
788
- async getResources(options) {
789
- return this.workspace.resources.list(options);
790
- }
791
- /**
792
- * @deprecated Use workspace.resources.get() instead
793
- * Get a single resource by slug
794
- */
795
- async getResource(slug) {
796
- const resource = await this.workspace.resources.get(slug);
797
- return resource.toJSON();
798
- }
799
- /**
800
- * @deprecated Use workspace.resources.entries() instead
801
- * Get entries that reference a resource
802
- */
803
- async getResourceEntries(slug) {
804
- return this.workspace.resources.entries(slug);
805
- }
806
- };
807
- }
808
- });
37
+ pageToOffset,
38
+ validateEmail
39
+ } from "./chunk-WJC4X7TB.js";
809
40
 
810
41
  // src/index.ts
811
42
  init_marvin();
@@ -827,12 +58,14 @@ var AuthClient = class extends HttpClient {
827
58
  * Returns the created user object
828
59
  */
829
60
  async register(data) {
61
+ validateEmail(data.email, "Email");
830
62
  return this.post("/api/users/register", data);
831
63
  }
832
64
  /**
833
65
  * Request password reset (sends email with token)
834
66
  */
835
67
  async forgotPassword(data) {
68
+ validateEmail(data.email, "Email");
836
69
  return this.post("/api/users/forgot-password", data);
837
70
  }
838
71
  /**
@@ -888,6 +121,9 @@ export {
888
121
  MarvinClient,
889
122
  MarvinConfigError,
890
123
  MarvinError,
124
+ MarvinNetworkError,
125
+ MarvinNotFoundError,
126
+ MarvinServerError,
891
127
  MarvinValidationError,
892
128
  NoAuth,
893
129
  Resource,