@goldenhippo/builder-cart-schemas 0.1.0 → 0.3.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/README.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # @goldenhippo/builder-cart-schemas
2
2
 
3
- Shared TypeScript types and Builder.io model definitions for Golden Hippo's cart/commerce Builder.io integration. This package provides factory functions for creating Builder.io content models and corresponding TypeScript content types for consuming model data.
3
+ Builder.io model definitions and TypeScript content types for Golden Hippo's cart/commerce integration. Provides factory functions for creating Builder.io content models and strongly-typed interfaces for consuming model data.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Using Content Types](#using-content-types)
9
+ - [Fetching typed content in Angular](#fetching-typed-content-in-angular)
10
+ - [Working with page types](#working-with-page-types)
11
+ - [Using core types](#using-core-types)
12
+ - [Exports](#exports)
13
+ - [Models](#models)
14
+ - [Data Models](#data-models)
15
+ - [Page Models](#page-models)
16
+ - [Section Models](#section-models)
17
+ - [Creating Model Definitions](#creating-model-definitions)
18
+ - [Model Dependencies](#model-dependencies)
19
+ - [Development](#development)
4
20
 
5
21
  ## Installation
6
22
 
@@ -8,6 +24,94 @@ Shared TypeScript types and Builder.io model definitions for Golden Hippo's cart
8
24
  npm install @goldenhippo/builder-cart-schemas
9
25
  ```
10
26
 
27
+ ## Using Content Types
28
+
29
+ Content types represent the shape of data returned from Builder.io's Content API. Use them to get type-safe access to model fields when fetching content.
30
+
31
+ ### Fetching typed content in Angular
32
+
33
+ ```typescript
34
+ import { Component, OnInit } from '@angular/core';
35
+ import { fetchOneEntry, fetchEntries } from '@builder.io/sdk-angular';
36
+ import type { BuilderProductContent, BuilderBlogCategoryContent } from '@goldenhippo/builder-cart-schemas';
37
+ import type { BuilderPageContent } from '@goldenhippo/builder-cart-schemas/page';
38
+
39
+ @Component({ selector: 'app-product', templateUrl: './product.component.html' })
40
+ export class ProductComponent implements OnInit {
41
+ product: BuilderProductContent | null = null;
42
+
43
+ async ngOnInit() {
44
+ const result = await fetchOneEntry({
45
+ model: 'product',
46
+ apiKey: environment.builderApiKey,
47
+ query: { 'data.gh.slug': 'example-product' },
48
+ });
49
+
50
+ this.product = result as BuilderProductContent;
51
+ }
52
+
53
+ get displayName(): string {
54
+ return this.product?.data?.displayName ?? '';
55
+ }
56
+
57
+ get featuredImage(): string {
58
+ return this.product?.data?.featuredImage ?? '';
59
+ }
60
+
61
+ get averageRating(): number {
62
+ return this.product?.data?.reviews?.averageRating ?? 0;
63
+ }
64
+ }
65
+ ```
66
+
67
+ ```typescript
68
+ // Fetching multiple entries
69
+ const categories = (await fetchEntries({
70
+ model: 'blog-category',
71
+ apiKey: environment.builderApiKey,
72
+ })) as BuilderBlogCategoryContent[];
73
+
74
+ categories.forEach((cat) => {
75
+ console.log(cat?.data?.name, cat?.data?.displayName);
76
+ });
77
+ ```
78
+
79
+ ### Working with page types
80
+
81
+ Page content uses a discriminated union based on `pageType`. TypeScript narrows the type automatically:
82
+
83
+ ```typescript
84
+ import type {
85
+ BuilderPageContent,
86
+ BuilderPdpPageContent,
87
+ BuilderBlogPageContent,
88
+ } from '@goldenhippo/builder-cart-schemas/page';
89
+
90
+ function renderPage(page: BuilderPageContent) {
91
+ const pageType = page?.data?.pageType;
92
+
93
+ if (pageType === 'Product') {
94
+ const pdp = page as BuilderPdpPageContent;
95
+ console.log(pdp?.data?.pdp?.product?.name);
96
+ console.log(pdp?.data?.pdp?.offerSelector?.osType);
97
+ }
98
+
99
+ if (pageType === 'Blog') {
100
+ const blog = page as BuilderBlogPageContent;
101
+ console.log(blog?.data?.blog?.author);
102
+ console.log(blog?.data?.blog?.publicationDate);
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Using core types
108
+
109
+ Core types like `ModelShape` and `BuilderIOFieldTypes` are available from the `@goldenhippo/builder-types` package:
110
+
111
+ ```typescript
112
+ import type { ModelShape, BuilderIOFieldTypes } from '@goldenhippo/builder-types';
113
+ ```
114
+
11
115
  ## Exports
12
116
 
13
117
  The package provides multiple entry points for granular imports:
@@ -19,8 +123,6 @@ The package provides multiple entry points for granular imports:
19
123
  | `@goldenhippo/builder-cart-schemas/page` | Page model creator and content types |
20
124
  | `@goldenhippo/builder-cart-schemas/section` | Section/component model creators and content types |
21
125
 
22
- Core types (`ModelShape`, `BuilderIOFieldTypes`, etc.) are available from `@goldenhippo/builder-types`.
23
-
24
126
  ## Models
25
127
 
26
128
  ### Data Models
@@ -28,6 +130,7 @@ Core types (`ModelShape`, `BuilderIOFieldTypes`, etc.) are available from `@gold
28
130
  | Model | Creator | Content Type |
29
131
  | ------------------------- | ---------------------------------------------------------- | -------------------------------------- |
30
132
  | Product | `createProductModel(props)` | `BuilderProductContent` |
133
+ | Product Group | `createProductGroupModel(props)` | `BuilderProductGroupContent` |
31
134
  | Product Category | `createCategoryModel()` | `BuilderProductCategoryContent` |
32
135
  | Product Tag | `createProductTagModel()` | `BuilderProductTagContent` |
33
136
  | Product Ingredient | `createIngredientsModel()` | `BuilderIngredientContent` |
@@ -50,9 +153,7 @@ Core types (`ModelShape`, `BuilderIOFieldTypes`, etc.) are available from `@gold
50
153
  | Site Banner | `createSiteBannerModel(editUrl)` | `BuilderSiteBannerModelContent` |
51
154
  | Default Website Section | `createDefaultWebsiteSectionModel(editUrl)` | `BuilderDefaultWebsiteSectionContent` |
52
155
 
53
- ## Usage
54
-
55
- ### Creating model definitions
156
+ ## Creating Model Definitions
56
157
 
57
158
  Model creators return a `ModelShape` object suitable for registration with Builder.io's API. Some models require IDs of other models they reference.
58
159
 
@@ -81,32 +182,6 @@ const pageModel = createPageModel({
81
182
  });
82
183
  ```
83
184
 
84
- ### Using content types
85
-
86
- Content types extend `BuilderContent` from `@builder.io/sdk` and represent the shape of data returned from Builder.io's Content API.
87
-
88
- ```typescript
89
- import type { BuilderProductContent, BuilderPageContent } from '@goldenhippo/builder-cart-schemas';
90
-
91
- // Type-safe access to product content
92
- function getProductName(product: BuilderProductContent): string {
93
- return product?.data?.displayName ?? product?.data?.name ?? '';
94
- }
95
-
96
- // Page content is a union type based on page type
97
- function handlePage(page: BuilderPageContent) {
98
- if (page?.data?.pageType === 'Product') {
99
- // TypeScript narrows to BuilderPdpPageContent
100
- }
101
- }
102
- ```
103
-
104
- ### Using core types
105
-
106
- ```typescript
107
- import type { ModelShape, BuilderIOFieldTypes } from '@goldenhippo/builder-types';
108
- ```
109
-
110
185
  ## Model Dependencies
111
186
 
112
187
  Models that reference other models require their Builder.io model IDs at creation time:
@@ -130,12 +205,3 @@ npm run typecheck # Type-check with tsc
130
205
  npm run test # Run tests with vitest
131
206
  npm run lint # Lint with eslint
132
207
  ```
133
-
134
- ## Build Output
135
-
136
- Built with [tsup](https://tsup.egoist.dev/) producing:
137
-
138
- - **CJS** (`.cjs`) — CommonJS for Node.js / legacy bundlers
139
- - **ESM** (`.js`) — ES modules for modern bundlers
140
- - **Declarations** (`.d.ts`, `.d.cts`) — TypeScript type definitions
141
- - **Source maps** (`.map`) — for debugging
@@ -1,5 +1,6 @@
1
- import { BuilderResponseBaseData, ModelShape } from '@goldenhippo/builder-types';
1
+ import { BuilderResponseBaseData, ModelShape, BuilderContentReference } from '@goldenhippo/builder-types';
2
2
  import { BuilderContent } from '@builder.io/sdk';
3
+ import { BuilderBlogPageContent } from '../page/index.mjs';
3
4
 
4
5
  declare enum HeaderType {
5
6
  BASIC = "BASIC",
@@ -76,6 +77,94 @@ declare enum SubscriptionCancelButtonType {
76
77
  Cancel = "cancel"
77
78
  }
78
79
 
80
+ declare const createCategoryModel: () => ModelShape;
81
+ type BuilderProductCategoryContent = BuilderContent & Partial<{
82
+ data: BuilderResponseBaseData & {
83
+ name: string;
84
+ description?: string;
85
+ desktopImage?: string;
86
+ mobileImage?: string;
87
+ hidden?: boolean;
88
+ slug?: string;
89
+ searchKeys?: string[];
90
+ };
91
+ }>;
92
+
93
+ declare const createIngredientsModel: () => ModelShape;
94
+ type BuilderIngredientContent = BuilderContent & Partial<{
95
+ data: BuilderResponseBaseData & {
96
+ name: string;
97
+ description?: string;
98
+ image?: string;
99
+ shortDescription?: string;
100
+ searchKeys?: string[];
101
+ };
102
+ }>;
103
+
104
+ declare const createProductUseCaseModel: () => ModelShape;
105
+ type BuilderProductUseCaseContent = BuilderContent & Partial<{
106
+ data: BuilderResponseBaseData & {
107
+ name: string;
108
+ description?: string;
109
+ searchKeys?: string[];
110
+ image?: string;
111
+ hidden?: boolean;
112
+ };
113
+ }>;
114
+
115
+ declare const createProductTagModel: () => ModelShape;
116
+ type BuilderProductTagContent = BuilderContent & Partial<{
117
+ data: BuilderResponseBaseData & {
118
+ name: string;
119
+ tagColor: string;
120
+ hidden?: boolean;
121
+ image?: string;
122
+ pluralDisplayName?: string;
123
+ };
124
+ }>;
125
+
126
+ interface ProductFilterModels {
127
+ categoryId: string;
128
+ useCaseId: string;
129
+ ingredientId: string;
130
+ tagId: string;
131
+ }
132
+ declare enum FilterApplicationType {
133
+ Inclusive = "Inclusive",
134
+ Exclusive = "Exclusive"
135
+ }
136
+ declare const createProductGridConfigModel: (models: ProductFilterModels) => ModelShape;
137
+ type BuilderProductGridFilterGroupContent = BuilderContent & Partial<{
138
+ data: BuilderResponseBaseData & {
139
+ displayName: string;
140
+ categories: {
141
+ category: {
142
+ id: string;
143
+ value: BuilderContentReference<BuilderProductCategoryContent>;
144
+ };
145
+ }[];
146
+ ingredients: {
147
+ ingredient: {
148
+ id: string;
149
+ value: BuilderContentReference<BuilderIngredientContent>;
150
+ };
151
+ }[];
152
+ useCases: {
153
+ useCase: {
154
+ id: string;
155
+ value: BuilderContentReference<BuilderProductUseCaseContent>;
156
+ };
157
+ }[];
158
+ tags: {
159
+ tag: {
160
+ id: string;
161
+ value: BuilderContentReference<BuilderProductTagContent>;
162
+ };
163
+ }[];
164
+ filterApplicationType: FilterApplicationType;
165
+ };
166
+ }>;
167
+
79
168
  declare const createBrandConfigModel: (gridFilterModelId: string, bannerModelId: string) => ModelShape;
80
169
  type BuilderBrandConfigContent = BuilderContent & Partial<{
81
170
  data: BuilderResponseBaseData & {
@@ -106,7 +195,7 @@ type BuilderBrandConfigContent = BuilderContent & Partial<{
106
195
  banners: {
107
196
  banner: {
108
197
  id: string;
109
- name: string;
198
+ value: BuilderContentReference<BuilderContent>;
110
199
  };
111
200
  alwaysShow: boolean;
112
201
  }[];
@@ -251,6 +340,7 @@ type BuilderBrandConfigContent = BuilderContent & Partial<{
251
340
  productGridFilterGroups: {
252
341
  filterConfig: {
253
342
  id: string;
343
+ value: BuilderContentReference<BuilderProductGridFilterGroupContent>;
254
344
  };
255
345
  }[];
256
346
  productGridHideRestricted: boolean;
@@ -422,6 +512,7 @@ type BuilderBlogCommentContent = BuilderContent & Partial<{
422
512
  blog: {
423
513
  id: string;
424
514
  name: string;
515
+ value: BuilderContentReference<BuilderBlogPageContent>;
425
516
  };
426
517
  };
427
518
  }>;
@@ -459,26 +550,26 @@ type BuilderProductContent = BuilderContent & Partial<{
459
550
  };
460
551
  tags?: {
461
552
  tag: {
462
- name: string;
463
- displayName: string;
553
+ id: string;
554
+ value: BuilderContentReference<BuilderProductTagContent>;
464
555
  };
465
556
  }[];
466
557
  categories?: {
467
558
  category: {
468
- name: string;
469
- displayName: string;
559
+ id: string;
560
+ value: BuilderContentReference<BuilderProductCategoryContent>;
470
561
  };
471
562
  }[];
472
563
  ingredients?: {
473
564
  ingredient: {
474
- name: string;
475
- displayName: string;
565
+ id: string;
566
+ value: BuilderContentReference<BuilderIngredientContent>;
476
567
  };
477
568
  }[];
478
569
  useCases?: {
479
570
  useCase: {
480
- name: string;
481
- displayName: string;
571
+ id: string;
572
+ value: BuilderContentReference<BuilderProductUseCaseContent>;
482
573
  };
483
574
  }[];
484
575
  gh: {
@@ -502,7 +593,10 @@ type BuilderProductGroupContent = BuilderContent & Partial<{
502
593
  gridTagline?: string;
503
594
  shortDescription?: string;
504
595
  products: {
505
- product: string;
596
+ product: {
597
+ id: string;
598
+ value: BuilderContentReference<BuilderProductContent>;
599
+ };
506
600
  displayName?: string;
507
601
  isTrialSize?: boolean;
508
602
  }[];
@@ -517,88 +611,4 @@ type BuilderProductGroupContent = BuilderContent & Partial<{
517
611
  };
518
612
  }>;
519
613
 
520
- declare const createCategoryModel: () => ModelShape;
521
- type BuilderProductCategoryContent = BuilderContent & Partial<{
522
- data: BuilderResponseBaseData & {
523
- name: string;
524
- description?: string;
525
- desktopImage?: string;
526
- mobileImage?: string;
527
- hidden?: boolean;
528
- slug?: string;
529
- searchKeys?: string[];
530
- };
531
- }>;
532
-
533
- interface ProductFilterModels {
534
- categoryId: string;
535
- useCaseId: string;
536
- ingredientId: string;
537
- tagId: string;
538
- }
539
- declare enum FilterApplicationType {
540
- Inclusive = "Inclusive",
541
- Exclusive = "Exclusive"
542
- }
543
- declare const createProductGridConfigModel: (models: ProductFilterModels) => ModelShape;
544
- type BuilderProductGridFilterGroupContent = BuilderContent & Partial<{
545
- data: BuilderResponseBaseData & {
546
- displayName: string;
547
- categories: {
548
- category: {
549
- id: string;
550
- } & Record<string, any>;
551
- }[];
552
- ingredients: {
553
- ingredient: {
554
- id: string;
555
- } & Record<string, any>;
556
- }[];
557
- useCases: {
558
- useCase: {
559
- id: string;
560
- } & Record<string, any>;
561
- }[];
562
- tags: {
563
- tag: {
564
- id: string;
565
- } & Record<string, any>;
566
- }[];
567
- filterApplicationType: FilterApplicationType;
568
- };
569
- }>;
570
-
571
- declare const createIngredientsModel: () => ModelShape;
572
- type BuilderIngredientContent = BuilderContent & Partial<{
573
- data: BuilderResponseBaseData & {
574
- name: string;
575
- description?: string;
576
- image?: string;
577
- shortDescription?: string;
578
- searchKeys?: string[];
579
- };
580
- }>;
581
-
582
- declare const createProductTagModel: () => ModelShape;
583
- type BuilderProductTagContent = BuilderContent & Partial<{
584
- data: BuilderResponseBaseData & {
585
- name: string;
586
- tagColor: string;
587
- hidden?: boolean;
588
- image?: string;
589
- pluralDisplayName?: string;
590
- };
591
- }>;
592
-
593
- declare const createProductUseCaseModel: () => ModelShape;
594
- type BuilderProductUseCaseContent = BuilderContent & Partial<{
595
- data: BuilderResponseBaseData & {
596
- name: string;
597
- description?: string;
598
- searchKeys?: string[];
599
- image?: string;
600
- hidden?: boolean;
601
- };
602
- }>;
603
-
604
614
  export { type BuilderBlogCategoryContent, type BuilderBlogCommentContent, type BuilderBrandConfigContent, type BuilderIngredientContent, type BuilderProductCategoryContent, type BuilderProductContent, type BuilderProductGridFilterGroupContent, type BuilderProductGroupContent, type BuilderProductTagContent, type BuilderProductUseCaseContent, createBlogCategoryModel, createBlogCommentModel, createBrandConfigModel, createCategoryModel, createIngredientsModel, createProductGridConfigModel, createProductGroupModel, createProductModel, createProductTagModel, createProductUseCaseModel };