schemaorg-kit 1.0.1
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/LICENSE +21 -0
- package/README.md +289 -0
- package/dist/index.d.mts +50809 -0
- package/dist/index.d.ts +50809 -0
- package/dist/index.js +2145 -0
- package/dist/index.mjs +1991 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 schemaorg-kit contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# schemaorg-kit
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/schemaorg-kit)
|
|
4
|
+
[](https://github.com/6f5/schemaorg-kit/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
> Type-safe schema.org structured data for every Google rich result type — Zod validation, JSON-LD `@graph`, full TypeScript inference.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **35+ factory functions** covering all Google-supported rich result types
|
|
12
|
+
- **Zod v4 validation** with descriptive error messages at runtime
|
|
13
|
+
- **Full TypeScript autocomplete** — every field, every enum value
|
|
14
|
+
- **`@graph` support** for multi-entity pages with cross-references
|
|
15
|
+
- **Two APIs** — named factories (`createProduct`) or unified `schema("Product", {...})`
|
|
16
|
+
- **Dual ESM + CJS build** — works in Next.js, Remix, Astro, Node.js, and beyond
|
|
17
|
+
- **Zero dependencies** at runtime — Zod is a peer dependency you already have
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install schemaorg-kit zod
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Requires **Node.js ≥ 18** and **Zod ≥ 4.3**.
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { createProduct, createOffer, createBreadcrumbList } from "schemaorg-kit";
|
|
31
|
+
|
|
32
|
+
const product = createProduct({
|
|
33
|
+
name: "Running Shoes",
|
|
34
|
+
sku: "RS-001",
|
|
35
|
+
offers: createOffer({
|
|
36
|
+
price: 99.99,
|
|
37
|
+
priceCurrency: "USD",
|
|
38
|
+
availability: "InStock",
|
|
39
|
+
}).toObject(),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Inject directly into HTML
|
|
43
|
+
document.head.innerHTML += product.toScript();
|
|
44
|
+
|
|
45
|
+
// Or get the plain object
|
|
46
|
+
const jsonLd = product.toJsonLd(); // includes @context
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Output Methods
|
|
50
|
+
|
|
51
|
+
Every node returned by a factory exposes these methods:
|
|
52
|
+
|
|
53
|
+
| Method | Returns | Description |
|
|
54
|
+
|--------|---------|-------------|
|
|
55
|
+
| `.toObject()` | `T` | Raw validated object — use this when nesting inside another schema |
|
|
56
|
+
| `.toJsonLd()` | `Record<string, unknown>` | Object with `@context: "https://schema.org"` added |
|
|
57
|
+
| `.toScript()` | `string` | Full `<script type="application/ld+json">` tag, ready for HTML |
|
|
58
|
+
| `.toString()` | `string` | Pretty-printed JSON string |
|
|
59
|
+
| `.validate()` | `this` | Throws a `ZodError` if data is invalid (chainable) |
|
|
60
|
+
| `.safeParse()` | Zod result | Returns `{ success, data, error }` without throwing |
|
|
61
|
+
|
|
62
|
+
## Composing Schemas
|
|
63
|
+
|
|
64
|
+
Call `.toObject()` when embedding one schema inside another:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { createPerson, createOrganization, createArticle } from "schemaorg-kit";
|
|
68
|
+
|
|
69
|
+
const author = createPerson({ name: "Jane Doe", url: "https://janedoe.com" });
|
|
70
|
+
|
|
71
|
+
const article = createArticle({
|
|
72
|
+
headline: "Hello World",
|
|
73
|
+
author: author.toObject(), // <-- nest with .toObject()
|
|
74
|
+
publisher: createOrganization({
|
|
75
|
+
name: "Acme Blog",
|
|
76
|
+
url: "https://acmeblog.com",
|
|
77
|
+
logo: "https://acmeblog.com/logo.png",
|
|
78
|
+
}).toObject(),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
console.log(article.toScript());
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## `@graph` Support
|
|
85
|
+
|
|
86
|
+
Use `createGraph` to output multiple schema nodes in a single `<script>` tag with `@id` cross-references:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { createGraph, createWebPage, createArticle, createPerson } from "schemaorg-kit";
|
|
90
|
+
|
|
91
|
+
const graph = createGraph([
|
|
92
|
+
createWebPage({ "@id": "https://example.com/post#webpage", url: "https://example.com/post" }),
|
|
93
|
+
createArticle({
|
|
94
|
+
"@id": "https://example.com/post#article",
|
|
95
|
+
headline: "Hello World",
|
|
96
|
+
isPartOf: { "@id": "https://example.com/post#webpage" },
|
|
97
|
+
author: { "@id": "https://example.com/about#person" },
|
|
98
|
+
}),
|
|
99
|
+
createPerson({ "@id": "https://example.com/about#person", name: "Jane Doe" }),
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
console.log(graph.toScript());
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Unified Factory
|
|
106
|
+
|
|
107
|
+
As an alternative to named imports, use the `schema()` factory with any registered type name:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { schema } from "schemaorg-kit";
|
|
111
|
+
|
|
112
|
+
const product = schema("Product", { name: "Shoes", sku: "SH-001" });
|
|
113
|
+
const event = schema("Event", { name: "Conference", startDate: "2025-09-01" });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Supported Types
|
|
117
|
+
|
|
118
|
+
### Things
|
|
119
|
+
|
|
120
|
+
| Factory | Schema.org Type |
|
|
121
|
+
|---------|----------------|
|
|
122
|
+
| `createPerson` | `Person` |
|
|
123
|
+
| `createOrganization` | `Organization` |
|
|
124
|
+
| `createCorporation` | `Corporation` |
|
|
125
|
+
| `createNGO` | `NGO` |
|
|
126
|
+
| `createOnlineStore` | `OnlineStore` |
|
|
127
|
+
| `createOnlineBusiness` | `OnlineBusiness` |
|
|
128
|
+
| `createProduct` | `Product` |
|
|
129
|
+
| `createProductGroup` | `ProductGroup` |
|
|
130
|
+
| `createEvent` | `Event` |
|
|
131
|
+
| `createPlace` | `Place` |
|
|
132
|
+
| `createLocalBusiness` | `LocalBusiness` |
|
|
133
|
+
| `createRestaurant` | `Restaurant` |
|
|
134
|
+
| `createHotel` | `Hotel` |
|
|
135
|
+
| `createMovie` | `Movie` |
|
|
136
|
+
|
|
137
|
+
### Creative Works
|
|
138
|
+
|
|
139
|
+
| Factory | Schema.org Type |
|
|
140
|
+
|---------|----------------|
|
|
141
|
+
| `createBook` | `Book` (with ReadAction / BorrowAction) |
|
|
142
|
+
| `createArticle` | `Article` |
|
|
143
|
+
| `createNewsArticle` | `NewsArticle` |
|
|
144
|
+
| `createBlogPosting` | `BlogPosting` |
|
|
145
|
+
| `createWebPage` | `WebPage` |
|
|
146
|
+
| `createWebSite` | `WebSite` |
|
|
147
|
+
| `createDataset` | `Dataset` |
|
|
148
|
+
| `createRecipe` | `Recipe` |
|
|
149
|
+
| `createCourse` | `Course` |
|
|
150
|
+
| `createSoftwareApplication` | `SoftwareApplication` |
|
|
151
|
+
| `createMobileApplication` | `MobileApplication` |
|
|
152
|
+
| `createWebApplication` | `WebApplication` |
|
|
153
|
+
| `createMathSolver` | `MathSolver` |
|
|
154
|
+
|
|
155
|
+
### Intangibles & Other
|
|
156
|
+
|
|
157
|
+
| Factory | Schema.org Type |
|
|
158
|
+
|---------|----------------|
|
|
159
|
+
| `createOffer` | `Offer` |
|
|
160
|
+
| `createImageObject` | `ImageObject` |
|
|
161
|
+
| `createVideoObject` | `VideoObject` |
|
|
162
|
+
| `createJobPosting` | `JobPosting` |
|
|
163
|
+
| `createQAPage` / `createQuiz` | `QAPage` / `Quiz` |
|
|
164
|
+
| `createDiscussionForumPosting` | `DiscussionForumPosting` |
|
|
165
|
+
| `createProfilePage` | `ProfilePage` |
|
|
166
|
+
| `createVacationRental` | `VacationRental` |
|
|
167
|
+
| `createLanguage` | `Language` |
|
|
168
|
+
|
|
169
|
+
### Helpers
|
|
170
|
+
|
|
171
|
+
| Helper | What it does |
|
|
172
|
+
|--------|-------------|
|
|
173
|
+
| `createBreadcrumbList([...])` | Builds a `BreadcrumbList` from a plain array |
|
|
174
|
+
| `createFAQPage([...])` | Builds a `FAQPage` from `{question, answer}` pairs |
|
|
175
|
+
| `createCarousel([...])` | Wraps schema nodes in an `ItemList` carousel |
|
|
176
|
+
| `createPaywalledArticle(...)` | Article with `isAccessibleForFree: false` paywalled sections |
|
|
177
|
+
|
|
178
|
+
## Common Patterns
|
|
179
|
+
|
|
180
|
+
### Product with Price Range and Shipping
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import {
|
|
184
|
+
createProduct,
|
|
185
|
+
AggregateOfferSchema,
|
|
186
|
+
OfferShippingDetailsSchema,
|
|
187
|
+
DefinedRegionSchema,
|
|
188
|
+
} from "schemaorg-kit";
|
|
189
|
+
|
|
190
|
+
const product = createProduct({
|
|
191
|
+
name: "Premium Headphones",
|
|
192
|
+
offers: AggregateOfferSchema.parse({
|
|
193
|
+
lowPrice: 79,
|
|
194
|
+
highPrice: 129,
|
|
195
|
+
priceCurrency: "USD",
|
|
196
|
+
offerCount: 4,
|
|
197
|
+
offers: {
|
|
198
|
+
price: 79,
|
|
199
|
+
priceCurrency: "USD",
|
|
200
|
+
availability: "InStock",
|
|
201
|
+
shippingDetails: OfferShippingDetailsSchema.parse({
|
|
202
|
+
shippingRate: { value: 0, currency: "USD" },
|
|
203
|
+
shippingDestination: DefinedRegionSchema.parse({ addressCountry: "US" }),
|
|
204
|
+
deliveryTime: {
|
|
205
|
+
handlingTime: { minValue: 0, maxValue: 1, unitCode: "DAY" },
|
|
206
|
+
transitTime: { minValue: 3, maxValue: 5, unitCode: "DAY" },
|
|
207
|
+
},
|
|
208
|
+
}),
|
|
209
|
+
},
|
|
210
|
+
}),
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### FAQ Page
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { createFAQPage } from "schemaorg-kit";
|
|
218
|
+
|
|
219
|
+
const faq = createFAQPage([
|
|
220
|
+
{ question: "What is schemaorg-kit?", answer: "A type-safe schema.org builder." },
|
|
221
|
+
{ question: "Does it support @graph?", answer: "Yes, via createGraph()." },
|
|
222
|
+
]);
|
|
223
|
+
|
|
224
|
+
document.head.innerHTML += faq.toScript();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### BreadcrumbList
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { createBreadcrumbList } from "schemaorg-kit";
|
|
231
|
+
|
|
232
|
+
const breadcrumb = createBreadcrumbList([
|
|
233
|
+
{ name: "Home", url: "https://example.com" },
|
|
234
|
+
{ name: "Products", url: "https://example.com/products" },
|
|
235
|
+
{ name: "Shoes" }, // last item — url is optional
|
|
236
|
+
]);
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Extending with Custom Types
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { extendThing, makeFactory } from "schemaorg-kit";
|
|
243
|
+
import { z } from "zod";
|
|
244
|
+
|
|
245
|
+
const PodcastSchema = extendThing("PodcastSeries", {
|
|
246
|
+
webFeed: z.string().url(),
|
|
247
|
+
numberOfEpisodes: z.number().int().optional(),
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const createPodcast = makeFactory(PodcastSchema);
|
|
251
|
+
|
|
252
|
+
const podcast = createPodcast({
|
|
253
|
+
name: "My Show",
|
|
254
|
+
webFeed: "https://example.com/feed.rss",
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Project Structure
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
src/
|
|
262
|
+
├── core/
|
|
263
|
+
│ ├── base.ts # SchemaNode<T> class + makeFactory()
|
|
264
|
+
│ ├── registry.ts # Unified schema() factory + REGISTRY
|
|
265
|
+
│ └── graph.ts # SchemaGraph + createGraph()
|
|
266
|
+
├── types/
|
|
267
|
+
│ ├── shared/ # Reusable building blocks
|
|
268
|
+
│ │ ├── Offer.ts # Offer, AggregateOffer, MerchantReturnPolicy
|
|
269
|
+
│ │ ├── ShippingDetails.ts # OfferShippingDetails, DefinedRegion, ShippingDeliveryTime
|
|
270
|
+
│ │ ├── Rating.ts # Rating, AggregateRating, Review, EmployerAggregateRating
|
|
271
|
+
│ │ ├── VideoObject.ts # VideoObject, Clip, BroadcastEvent
|
|
272
|
+
│ │ └── ...
|
|
273
|
+
│ ├── things/ # Person, Organization, Product, Place, Event, ...
|
|
274
|
+
│ ├── creative-works/ # Article, WebPage, WebSite, Recipe, Book, ...
|
|
275
|
+
│ ├── intangibles/ # JobPosting, FAQPage, ItemList, ProfilePage, ...
|
|
276
|
+
│ └── lodging/ # VacationRental, Accommodation
|
|
277
|
+
├── helpers/ # Ergonomic wrappers (breadcrumb, faq, carousel, paywalled)
|
|
278
|
+
└── index.ts # Public API
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Links
|
|
282
|
+
|
|
283
|
+
- **Docs**: https://6f5.github.io/schemaorg-kit/
|
|
284
|
+
- **npm**: https://www.npmjs.com/package/schemaorg-kit
|
|
285
|
+
- **Issues**: https://github.com/6f5/schemaorg-kit/issues
|
|
286
|
+
|
|
287
|
+
## License
|
|
288
|
+
|
|
289
|
+
MIT
|