digital-products 2.1.3 → 2.4.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.
Files changed (122) hide show
  1. package/.turbo/turbo-build.log +4 -5
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +2 -0
  4. package/dist/api.js +7 -7
  5. package/dist/api.js.map +1 -1
  6. package/dist/app.js +6 -6
  7. package/dist/app.js.map +1 -1
  8. package/dist/client.d.ts +157 -0
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +69 -0
  11. package/dist/client.js.map +1 -0
  12. package/dist/content.js +7 -7
  13. package/dist/content.js.map +1 -1
  14. package/dist/data.d.ts.map +1 -1
  15. package/dist/data.js +6 -6
  16. package/dist/data.js.map +1 -1
  17. package/dist/dataset.js +5 -5
  18. package/dist/dataset.js.map +1 -1
  19. package/dist/index.d.ts +92 -13
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +139 -15
  22. package/dist/index.js.map +1 -1
  23. package/dist/mcp.d.ts +1 -1
  24. package/dist/mcp.d.ts.map +1 -1
  25. package/dist/mcp.js +17 -10
  26. package/dist/mcp.js.map +1 -1
  27. package/dist/product.js +2 -2
  28. package/dist/product.js.map +1 -1
  29. package/dist/sdk.d.ts.map +1 -1
  30. package/dist/sdk.js +52 -16
  31. package/dist/sdk.js.map +1 -1
  32. package/dist/site.d.ts.map +1 -1
  33. package/dist/site.js +12 -8
  34. package/dist/site.js.map +1 -1
  35. package/dist/types.d.ts +830 -12
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/types.js +495 -2
  38. package/dist/types.js.map +1 -1
  39. package/dist/worker.d.ts +205 -0
  40. package/dist/worker.d.ts.map +1 -0
  41. package/dist/worker.js +356 -0
  42. package/dist/worker.js.map +1 -0
  43. package/package.json +29 -13
  44. package/src/api.ts +7 -7
  45. package/src/app.ts +6 -6
  46. package/src/client.ts +192 -0
  47. package/src/content.ts +7 -7
  48. package/src/data.ts +12 -7
  49. package/src/dataset.ts +5 -5
  50. package/src/index.ts +151 -15
  51. package/src/mcp.ts +18 -11
  52. package/src/product.ts +2 -2
  53. package/src/sdk.ts +54 -15
  54. package/src/site.ts +12 -8
  55. package/src/types.ts +821 -12
  56. package/src/worker.ts +525 -0
  57. package/test/product.test.ts +53 -198
  58. package/test/unified-types.test.ts +589 -0
  59. package/test/worker.test.ts +912 -0
  60. package/vitest.config.ts +42 -0
  61. package/wrangler.jsonc +36 -0
  62. package/LICENSE +0 -21
  63. package/dist/features/define.d.ts +0 -63
  64. package/dist/features/define.d.ts.map +0 -1
  65. package/dist/features/define.js +0 -72
  66. package/dist/features/define.js.map +0 -1
  67. package/dist/features/flags.d.ts +0 -98
  68. package/dist/features/flags.d.ts.map +0 -1
  69. package/dist/features/flags.js +0 -145
  70. package/dist/features/flags.js.map +0 -1
  71. package/dist/features/toggles.d.ts +0 -75
  72. package/dist/features/toggles.d.ts.map +0 -1
  73. package/dist/features/toggles.js +0 -107
  74. package/dist/features/toggles.js.map +0 -1
  75. package/dist/tiers/define.d.ts +0 -63
  76. package/dist/tiers/define.d.ts.map +0 -1
  77. package/dist/tiers/define.js +0 -78
  78. package/dist/tiers/define.js.map +0 -1
  79. package/dist/tiers/entitlements.d.ts +0 -94
  80. package/dist/tiers/entitlements.d.ts.map +0 -1
  81. package/dist/tiers/entitlements.js +0 -94
  82. package/dist/tiers/entitlements.js.map +0 -1
  83. package/src/api.js +0 -128
  84. package/src/app.js +0 -106
  85. package/src/content.js +0 -77
  86. package/src/data.js +0 -106
  87. package/src/dataset.js +0 -49
  88. package/src/entities/ai.js +0 -858
  89. package/src/entities/content.js +0 -783
  90. package/src/entities/index.js +0 -88
  91. package/src/entities/interfaces.js +0 -929
  92. package/src/entities/lifecycle.js +0 -803
  93. package/src/entities/products.js +0 -797
  94. package/src/entities/web.js +0 -657
  95. package/src/features/define.ts +0 -130
  96. package/src/features/flags.ts +0 -247
  97. package/src/features/toggles.ts +0 -189
  98. package/src/index.js +0 -35
  99. package/src/mcp.js +0 -139
  100. package/src/pricing/billing.ts +0 -386
  101. package/src/pricing/plans.ts +0 -214
  102. package/src/product.js +0 -53
  103. package/src/registry.js +0 -31
  104. package/src/sdk.js +0 -127
  105. package/src/site.js +0 -112
  106. package/src/tiers/define.ts +0 -137
  107. package/src/tiers/entitlements.ts +0 -201
  108. package/src/types.js +0 -4
  109. package/test/analytics/events.test.ts +0 -319
  110. package/test/analytics/experiments.test.ts +0 -327
  111. package/test/features/define.test.ts +0 -187
  112. package/test/features/flags.test.ts +0 -259
  113. package/test/features/toggles.test.ts +0 -178
  114. package/test/lifecycle/stages.test.ts +0 -233
  115. package/test/lifecycle/transitions.test.ts +0 -207
  116. package/test/onboarding/flows.test.ts +0 -307
  117. package/test/pricing/billing.test.ts +0 -287
  118. package/test/pricing/plans.test.ts +0 -307
  119. package/test/roadmap/milestones.test.ts +0 -231
  120. package/test/roadmap/priorities.test.ts +0 -239
  121. package/test/tiers/define.test.ts +0 -192
  122. package/test/tiers/entitlements.test.ts +0 -220
package/src/client.ts ADDED
@@ -0,0 +1,192 @@
1
+ /**
2
+ * RPC Client for Digital Products
3
+ *
4
+ * Provides a typed RPC client that connects to the deployed
5
+ * digital-products worker using rpc.do for remote procedure calls.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { createDigitalProductsClient } from 'digital-products/client'
10
+ *
11
+ * const client = createDigitalProductsClient('https://digital-products.workers.dev')
12
+ * const product = await client.create({ name: 'My Product', description: 'A great product', version: '1.0.0' })
13
+ * const feature = await client.addFeature(product.id, { name: 'Search', description: 'Full-text search' })
14
+ * ```
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+
19
+ import { RPC, http } from 'rpc.do'
20
+
21
+ // ==================== Types ====================
22
+
23
+ interface ProductData {
24
+ id: string
25
+ name: string
26
+ description: string
27
+ version: string
28
+ status: 'draft' | 'active' | 'deprecated' | 'archived'
29
+ type?: string
30
+ features?: FeatureData[]
31
+ metadata?: Record<string, unknown>
32
+ tags?: string[]
33
+ createdAt: Date
34
+ updatedAt: Date
35
+ }
36
+
37
+ interface FeatureData {
38
+ id: string
39
+ name: string
40
+ description: string
41
+ status: 'draft' | 'beta' | 'ga' | 'deprecated'
42
+ productId: string
43
+ metadata?: Record<string, unknown>
44
+ createdAt: Date
45
+ updatedAt: Date
46
+ }
47
+
48
+ interface VersionData {
49
+ id: string
50
+ productId: string
51
+ version: string
52
+ changelog?: string
53
+ status: 'draft' | 'published' | 'deprecated'
54
+ features?: string[]
55
+ metadata?: Record<string, unknown>
56
+ createdAt: Date
57
+ publishedAt?: Date
58
+ }
59
+
60
+ interface BundleData {
61
+ id: string
62
+ name: string
63
+ description: string
64
+ productIds: string[]
65
+ pricing?: PricingData
66
+ metadata?: Record<string, unknown>
67
+ createdAt: Date
68
+ updatedAt: Date
69
+ }
70
+
71
+ interface PricingData {
72
+ model: 'free' | 'one-time' | 'subscription' | 'usage-based'
73
+ amount?: number
74
+ currency?: string
75
+ interval?: 'month' | 'year'
76
+ }
77
+
78
+ interface ListOptions {
79
+ limit?: number
80
+ offset?: number
81
+ status?: string
82
+ type?: string
83
+ orderBy?: string
84
+ order?: 'asc' | 'desc'
85
+ }
86
+
87
+ // ==================== API Type ====================
88
+
89
+ /**
90
+ * DigitalProductsAPI - Type-safe interface matching ProductServiceCore RPC methods
91
+ *
92
+ * This interface mirrors all public methods on ProductServiceCore so that
93
+ * the RPC client provides full type safety when calling remote methods.
94
+ */
95
+ export interface DigitalProductsAPI {
96
+ // Product CRUD
97
+ create(data: Partial<ProductData>): Promise<ProductData>
98
+ get(id: string): Promise<ProductData | null>
99
+ update(id: string, data: Partial<ProductData>): Promise<ProductData>
100
+ delete(id: string): Promise<boolean>
101
+ list(options?: ListOptions): Promise<ProductData[]>
102
+
103
+ // Feature Operations
104
+ addFeature(productId: string, featureData: Partial<FeatureData>): Promise<FeatureData>
105
+ updateFeature(featureId: string, data: Partial<FeatureData>): Promise<FeatureData>
106
+ removeFeature(featureId: string): Promise<boolean>
107
+ listFeatures(productId: string): Promise<FeatureData[]>
108
+
109
+ // Version Operations
110
+ publish(productId: string, versionStr: string, changelog?: string): Promise<VersionData>
111
+ listVersions(productId: string): Promise<VersionData[]>
112
+ getVersion(productId: string, versionStr: string): Promise<VersionData | null>
113
+ deprecateVersion(productId: string, versionStr: string): Promise<VersionData>
114
+
115
+ // Bundle Operations
116
+ compose(name: string, productIds: string[], options?: Partial<BundleData>): Promise<BundleData>
117
+ getBundle(bundleId: string): Promise<BundleData | null>
118
+ updateBundle(bundleId: string, data: Partial<BundleData>): Promise<BundleData>
119
+ listBundles(): Promise<BundleData[]>
120
+ }
121
+
122
+ // ==================== Client Options ====================
123
+
124
+ /**
125
+ * Options for creating a digital products RPC client
126
+ */
127
+ export interface DigitalProductsClientOptions {
128
+ /** Authentication token or API key */
129
+ token?: string
130
+ /** Request timeout in milliseconds */
131
+ timeout?: number
132
+ /** Custom headers to include in requests */
133
+ headers?: Record<string, string>
134
+ }
135
+
136
+ // ==================== Client Factory ====================
137
+
138
+ /** Default URL for the digital-products worker */
139
+ const DEFAULT_URL = 'https://digital-products.workers.dev'
140
+
141
+ /**
142
+ * Create a typed RPC client for the digital-products worker
143
+ *
144
+ * @param url - The URL of the deployed digital-products worker
145
+ * @param options - Optional client configuration
146
+ * @returns A typed RPC client with all ProductServiceCore methods
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * import { createDigitalProductsClient } from 'digital-products/client'
151
+ *
152
+ * // Connect to production
153
+ * const client = createDigitalProductsClient('https://digital-products.workers.dev')
154
+ *
155
+ * // Create a product
156
+ * const product = await client.create({
157
+ * name: 'My API',
158
+ * description: 'A powerful API service',
159
+ * version: '1.0.0',
160
+ * })
161
+ *
162
+ * // Add features
163
+ * await client.addFeature(product.id, { name: 'Rate Limiting', description: 'API rate limiting' })
164
+ * await client.addFeature(product.id, { name: 'Analytics', description: 'Usage analytics' })
165
+ *
166
+ * // Publish a version
167
+ * await client.publish(product.id, '1.0.0', 'Initial release')
168
+ *
169
+ * // Create a bundle
170
+ * const bundle = await client.compose('Enterprise Bundle', [product.id, otherProduct.id])
171
+ * ```
172
+ */
173
+ export function createDigitalProductsClient(
174
+ url: string = DEFAULT_URL,
175
+ options?: DigitalProductsClientOptions
176
+ ) {
177
+ return RPC<DigitalProductsAPI>(http(url, options?.token))
178
+ }
179
+
180
+ /**
181
+ * Default client instance connected to the production digital-products worker
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * import client from 'digital-products/client'
186
+ *
187
+ * const product = await client.create({ name: 'My Product', description: 'Great', version: '1.0.0' })
188
+ * ```
189
+ */
190
+ const client = createDigitalProductsClient()
191
+
192
+ export default client
package/src/content.ts CHANGED
@@ -44,14 +44,14 @@ export function Content(config: Omit<ContentDefinition, 'type'>): ContentDefinit
44
44
  description: config.description,
45
45
  version: config.version,
46
46
  format: config.format || 'markdown',
47
- source: config.source,
48
- schema: config.schema,
49
- frontmatter: config.frontmatter,
50
- categories: config.categories,
51
- workflow: config.workflow,
52
- metadata: config.metadata,
53
- tags: config.tags,
54
47
  status: config.status || 'active',
48
+ ...(config.source !== undefined && { source: config.source }),
49
+ ...(config.schema !== undefined && { schema: config.schema }),
50
+ ...(config.frontmatter !== undefined && { frontmatter: config.frontmatter }),
51
+ ...(config.categories !== undefined && { categories: config.categories }),
52
+ ...(config.workflow !== undefined && { workflow: config.workflow }),
53
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
54
+ ...(config.tags !== undefined && { tags: config.tags }),
55
55
  }
56
56
 
57
57
  return registerProduct(content)
package/src/data.ts CHANGED
@@ -2,7 +2,12 @@
2
2
  * Data() - Define structured data
3
3
  */
4
4
 
5
- import type { DataDefinition, IndexDefinition, RelationshipDefinition, ValidationRule } from './types.js'
5
+ import type {
6
+ DataDefinition,
7
+ IndexDefinition,
8
+ RelationshipDefinition,
9
+ ValidationRule,
10
+ } from './types.js'
6
11
  import type { SimpleSchema } from 'ai-functions'
7
12
  import { registerProduct } from './product.js'
8
13
 
@@ -44,12 +49,12 @@ export function Data(config: Omit<DataDefinition, 'type'>): DataDefinition {
44
49
  version: config.version,
45
50
  schema: config.schema,
46
51
  provider: config.provider || 'fs',
47
- indexes: config.indexes,
48
- relationships: config.relationships,
49
- validation: config.validation,
50
- metadata: config.metadata,
51
- tags: config.tags,
52
52
  status: config.status || 'active',
53
+ ...(config.indexes !== undefined && { indexes: config.indexes }),
54
+ ...(config.relationships !== undefined && { relationships: config.relationships }),
55
+ ...(config.validation !== undefined && { validation: config.validation }),
56
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
57
+ ...(config.tags !== undefined && { tags: config.tags }),
53
58
  }
54
59
 
55
60
  return registerProduct(data)
@@ -124,6 +129,6 @@ export function Validate(
124
129
  field,
125
130
  rule,
126
131
  params: paramsOrMessage,
127
- message,
132
+ ...(message !== undefined && { message }),
128
133
  }
129
134
  }
package/src/dataset.ts CHANGED
@@ -40,13 +40,13 @@ export function Dataset(config: Omit<DatasetDefinition, 'type'>): DatasetDefinit
40
40
  version: config.version,
41
41
  format: config.format || 'json',
42
42
  schema: config.schema,
43
- source: config.source,
44
- size: config.size,
45
- license: config.license,
46
43
  updateFrequency: config.updateFrequency || 'static',
47
- metadata: config.metadata,
48
- tags: config.tags,
49
44
  status: config.status || 'active',
45
+ ...(config.source !== undefined && { source: config.source }),
46
+ ...(config.size !== undefined && { size: config.size }),
47
+ ...(config.license !== undefined && { license: config.license }),
48
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
49
+ ...(config.tags !== undefined && { tags: config.tags }),
50
50
  }
51
51
 
52
52
  return registerProduct(dataset)
package/src/index.ts CHANGED
@@ -1,20 +1,115 @@
1
1
  /**
2
2
  * digital-products - Primitives for defining and building digital products
3
3
  *
4
- * This package provides primitives for defining digital products:
5
- * - Apps: Interactive user-facing applications
6
- * - APIs: Programmatic interfaces
7
- * - Content: Text/media content with schemas
8
- * - Data: Structured data definitions
9
- * - Datasets: Curated data collections
10
- * - Sites: Websites and documentation
11
- * - MCPs: Model Context Protocol servers
12
- * - SDKs: Software development kits
4
+ * This package provides primitives for defining digital products using JSON-LD
5
+ * style conventions with `$id` and `$type` fields for schema.org.ai compatibility.
6
+ *
7
+ * ## Product Types
8
+ *
9
+ * - {@link Product} - Base product interface
10
+ * - {@link App} - Interactive user-facing applications (web, mobile, desktop)
11
+ * - {@link API} - Programmatic interfaces with versioning and auth
12
+ * - {@link Site} - Websites (marketing, docs, blog)
13
+ * - {@link Service} - Backend services with endpoints
14
+ * - {@link Feature} - Product features with lifecycle status
15
+ *
16
+ * ## Validation & Type Guards
17
+ *
18
+ * Each product type includes:
19
+ * - Zod schema for runtime validation (e.g., {@link AppSchema})
20
+ * - Type guard function (e.g., {@link isApp})
21
+ * - Factory function with defaults (e.g., {@link createApp})
22
+ *
23
+ * ## Builder Pattern (Legacy)
24
+ *
25
+ * The `*Builder` functions and `*Definition` types are maintained for
26
+ * backwards compatibility. New code should use the unified JSON-LD types.
13
27
  *
14
28
  * @packageDocumentation
29
+ *
30
+ * @example Creating an App
31
+ * ```typescript
32
+ * import { createApp, isApp, AppSchema, App } from 'digital-products'
33
+ *
34
+ * // Using factory function (recommended)
35
+ * const app = createApp({
36
+ * $id: 'https://schema.org.ai/apps/dashboard',
37
+ * name: 'Dashboard',
38
+ * description: 'Admin dashboard application',
39
+ * platform: 'web',
40
+ * url: 'https://dashboard.example.com'
41
+ * })
42
+ * // app.$type === 'https://schema.org.ai/App'
43
+ * // app.status === 'active' (default)
44
+ *
45
+ * // Type guard
46
+ * if (isApp(data)) {
47
+ * console.log(data.platform) // TypeScript knows this is App
48
+ * }
49
+ *
50
+ * // Zod validation
51
+ * const result = AppSchema.safeParse(untrustedData)
52
+ * if (result.success) {
53
+ * console.log(result.data.name)
54
+ * }
55
+ * ```
56
+ *
57
+ * @example Creating an API
58
+ * ```typescript
59
+ * import { createAPI, API, APISchema } from 'digital-products'
60
+ *
61
+ * const api = createAPI({
62
+ * $id: 'https://schema.org.ai/apis/users',
63
+ * name: 'Users API',
64
+ * description: 'User management REST API',
65
+ * baseUrl: 'https://api.example.com/v1',
66
+ * version: '1.0.0',
67
+ * authentication: 'bearer'
68
+ * })
69
+ * // api.$type === 'https://schema.org.ai/API'
70
+ * ```
71
+ *
72
+ * @example Creating a Site
73
+ * ```typescript
74
+ * import { createSite, Site, SiteSchema } from 'digital-products'
75
+ *
76
+ * const site = createSite({
77
+ * $id: 'https://schema.org.ai/sites/docs',
78
+ * name: 'Documentation',
79
+ * description: 'Product documentation site',
80
+ * url: 'https://docs.example.com',
81
+ * siteType: 'docs'
82
+ * })
83
+ * // site.$type === 'https://schema.org.ai/Site'
84
+ * ```
15
85
  */
16
86
 
17
- // Export all types
87
+ // =============================================================================
88
+ // UNIFIED TYPES (JSON-LD Style) - Recommended
89
+ // =============================================================================
90
+ //
91
+ // These exports from types.ts include:
92
+ //
93
+ // INTERFACES (JSON-LD style with $id/$type):
94
+ // - Product - Base product interface
95
+ // - App - Application (web, mobile, desktop)
96
+ // - API - API with versioning and authentication
97
+ // - Site - Website (marketing, docs, blog)
98
+ // - Service - Backend service with endpoints
99
+ // - Feature - Product feature with lifecycle
100
+ //
101
+ // ZOD SCHEMAS (runtime validation):
102
+ // - ProductSchema, AppSchema, APISchema, SiteSchema, ServiceSchema, FeatureSchema
103
+ //
104
+ // TYPE GUARDS:
105
+ // - isProduct, isApp, isAPI, isSite, isService, isFeature
106
+ //
107
+ // FACTORY FUNCTIONS (with sensible defaults):
108
+ // - createProduct, createApp, createAPI, createSite, createService, createFeature
109
+ //
110
+ // LEGACY TYPES (for backwards compatibility):
111
+ // - DigitalProduct, AppDefinition, APIDefinition, SiteDefinition, etc.
112
+ //
18
113
  export * from './types.js'
19
114
 
20
115
  // Export entity definitions (Nouns) as namespace to avoid conflicts with types
@@ -43,13 +138,54 @@ export {
43
138
  // Export registry
44
139
  export { registry } from './registry.js'
45
140
 
46
- // Export product constructors
47
- export { Product, createProduct, registerProduct } from './product.js'
48
- export { App, Route, State, Auth } from './app.js'
49
- export { API, Endpoint, APIAuth, RateLimit } from './api.js'
141
+ // =============================================================================
142
+ // BUILDER PATTERN (Legacy API)
143
+ // =============================================================================
144
+ //
145
+ // These builder functions create *Definition types (e.g., AppDefinition),
146
+ // which use `id` and `type` fields instead of JSON-LD `$id`/`$type`.
147
+ //
148
+ // For new code, prefer the unified types above:
149
+ // - createApp() creates App with $id/$type (JSON-LD)
150
+ // - AppBuilder() creates AppDefinition with id/type (legacy)
151
+ //
152
+ // The *Builder exports are renamed to avoid conflicts with the type interfaces.
153
+ // The original function names (App, API, Site) are also exported for backwards
154
+ // compatibility - TypeScript allows functions and types to share the same name.
155
+ //
156
+
157
+ /** @deprecated Use createProduct() from unified types instead */
158
+ export {
159
+ Product as ProductBuilder,
160
+ createProduct as createProductDefinition,
161
+ registerProduct,
162
+ } from './product.js'
163
+
164
+ /** @deprecated Use createApp() from unified types instead */
165
+ export { App as AppBuilder, Route, State, Auth } from './app.js'
166
+
167
+ /** @deprecated Use createAPI() from unified types instead */
168
+ export { API as APIBuilder, Endpoint, APIAuth, RateLimit } from './api.js'
169
+
50
170
  export { Content, Workflow } from './content.js'
51
171
  export { Data, Index, Relationship, Validate } from './data.js'
52
172
  export { Dataset } from './dataset.js'
53
- export { Site, Nav, SEO, Analytics } from './site.js'
173
+
174
+ /** @deprecated Use createSite() from unified types instead */
175
+ export { Site as SiteBuilder, Nav, SEO, Analytics } from './site.js'
176
+
54
177
  export { MCP, Tool, Resource, Prompt, MCPConfig } from './mcp.js'
55
178
  export { SDK, Export, Example } from './sdk.js'
179
+
180
+ // Re-export builder functions under original names for backwards compatibility.
181
+ // This allows: import { Site } from 'digital-products'; Site({...}) // builder
182
+ // While also: import type { Site } from 'digital-products'; const x: Site = {...} // type
183
+ // TypeScript allows function and type/interface with same name.
184
+ import { Product as ProductFn } from './product.js'
185
+ import { App as AppFn } from './app.js'
186
+ import { API as APIFn } from './api.js'
187
+ import { Site as SiteFn } from './site.js'
188
+
189
+ // Export builder functions - these shadow the type exports at runtime
190
+ // (which is fine since TypeScript types are erased at compile time)
191
+ export { ProductFn as Product, AppFn as App, APIFn as API, SiteFn as Site }
package/src/mcp.ts CHANGED
@@ -44,13 +44,13 @@ export function MCP(config: Omit<MCPDefinition, 'type'>): MCPDefinition {
44
44
  description: config.description,
45
45
  version: config.version,
46
46
  transport: config.transport,
47
- tools: config.tools,
48
- resources: config.resources,
49
- prompts: config.prompts,
50
- config: config.config,
51
- metadata: config.metadata,
52
- tags: config.tags,
53
47
  status: config.status || 'active',
48
+ ...(config.tools !== undefined && { tools: config.tools }),
49
+ ...(config.resources !== undefined && { resources: config.resources }),
50
+ ...(config.prompts !== undefined && { prompts: config.prompts }),
51
+ ...(config.config !== undefined && { config: config.config }),
52
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
53
+ ...(config.tags !== undefined && { tags: config.tags }),
54
54
  }
55
55
 
56
56
  return registerProduct(mcp)
@@ -78,14 +78,14 @@ export function MCP(config: Omit<MCPDefinition, 'type'>): MCPDefinition {
78
78
  export function Tool(
79
79
  name: string,
80
80
  description: string,
81
- inputSchema: SimpleSchema,
81
+ inputSchema: Record<string, unknown>,
82
82
  handler?: (input: unknown) => Promise<unknown>
83
83
  ): MCPTool {
84
84
  return {
85
85
  name,
86
86
  description,
87
- inputSchema,
88
- handler,
87
+ inputSchema: inputSchema as MCPTool['inputSchema'],
88
+ ...(handler !== undefined && { handler }),
89
89
  }
90
90
  }
91
91
 
@@ -112,7 +112,7 @@ export function Resource(
112
112
  uri,
113
113
  name,
114
114
  description,
115
- mimeType,
115
+ ...(mimeType !== undefined && { mimeType }),
116
116
  }
117
117
  }
118
118
 
@@ -135,11 +135,18 @@ export function Prompt(
135
135
  template: string,
136
136
  args?: SimpleSchema
137
137
  ): MCPPrompt {
138
+ if (args !== undefined) {
139
+ return {
140
+ name,
141
+ description,
142
+ template,
143
+ arguments: args as Record<string, unknown>,
144
+ }
145
+ }
138
146
  return {
139
147
  name,
140
148
  description,
141
149
  template,
142
- arguments: args,
143
150
  }
144
151
  }
145
152
 
package/src/product.ts CHANGED
@@ -24,9 +24,9 @@ export function Product(config: Omit<DigitalProduct, 'type'>): DigitalProduct {
24
24
  name: config.name,
25
25
  description: config.description,
26
26
  version: config.version,
27
- metadata: config.metadata,
28
- tags: config.tags,
29
27
  status: config.status || 'active',
28
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
29
+ ...(config.tags !== undefined && { tags: config.tags }),
30
30
  }
31
31
 
32
32
  return product
package/src/sdk.ts CHANGED
@@ -62,14 +62,14 @@ export function SDK(config: Omit<SDKDefinition, 'type'>): SDKDefinition {
62
62
  description: config.description,
63
63
  version: config.version,
64
64
  language: config.language,
65
- api: config.api,
66
- exports: config.exports,
67
- install: config.install,
68
- docs: config.docs,
69
- examples: config.examples,
70
- metadata: config.metadata,
71
- tags: config.tags,
72
65
  status: config.status || 'active',
66
+ ...(config.api !== undefined && { api: config.api }),
67
+ ...(config.exports !== undefined && { exports: config.exports }),
68
+ ...(config.install !== undefined && { install: config.install }),
69
+ ...(config.docs !== undefined && { docs: config.docs }),
70
+ ...(config.examples !== undefined && { examples: config.examples }),
71
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
72
+ ...(config.tags !== undefined && { tags: config.tags }),
73
73
  }
74
74
 
75
75
  return registerProduct(sdk)
@@ -108,14 +108,53 @@ export function Export(
108
108
  methods?: SDKExport[]
109
109
  }
110
110
  ): SDKExport {
111
- return {
112
- type,
113
- name,
114
- description,
115
- parameters: options?.parameters,
116
- returns: options?.returns,
117
- methods: options?.methods,
111
+ const base = { type, name, description }
112
+
113
+ // Build the result object conditionally to satisfy exactOptionalPropertyTypes
114
+ // Cast to Record<string, unknown> to match the local SimpleSchema type
115
+ if (
116
+ options?.parameters !== undefined &&
117
+ options?.returns !== undefined &&
118
+ options?.methods !== undefined
119
+ ) {
120
+ return {
121
+ ...base,
122
+ parameters: options.parameters as Record<string, unknown>,
123
+ returns: options.returns as Record<string, unknown>,
124
+ methods: options.methods,
125
+ }
126
+ }
127
+ if (options?.parameters !== undefined && options?.returns !== undefined) {
128
+ return {
129
+ ...base,
130
+ parameters: options.parameters as Record<string, unknown>,
131
+ returns: options.returns as Record<string, unknown>,
132
+ }
133
+ }
134
+ if (options?.parameters !== undefined && options?.methods !== undefined) {
135
+ return {
136
+ ...base,
137
+ parameters: options.parameters as Record<string, unknown>,
138
+ methods: options.methods,
139
+ }
140
+ }
141
+ if (options?.returns !== undefined && options?.methods !== undefined) {
142
+ return {
143
+ ...base,
144
+ returns: options.returns as Record<string, unknown>,
145
+ methods: options.methods,
146
+ }
147
+ }
148
+ if (options?.parameters !== undefined) {
149
+ return { ...base, parameters: options.parameters as Record<string, unknown> }
150
+ }
151
+ if (options?.returns !== undefined) {
152
+ return { ...base, returns: options.returns as Record<string, unknown> }
153
+ }
154
+ if (options?.methods !== undefined) {
155
+ return { ...base, methods: options.methods }
118
156
  }
157
+ return base
119
158
  }
120
159
 
121
160
  /**
@@ -143,6 +182,6 @@ export function Example(
143
182
  title,
144
183
  description,
145
184
  code,
146
- output,
185
+ ...(output !== undefined && { output }),
147
186
  }
148
187
  }
package/src/site.ts CHANGED
@@ -52,14 +52,14 @@ export function Site(config: Omit<SiteDefinition, 'type'>): SiteDefinition {
52
52
  description: config.description,
53
53
  version: config.version,
54
54
  generator: config.generator || 'next',
55
- structure: config.structure,
56
- navigation: config.navigation,
57
- seo: config.seo,
58
- analytics: config.analytics,
59
- deployment: config.deployment,
60
- metadata: config.metadata,
61
- tags: config.tags,
62
55
  status: config.status || 'active',
56
+ ...(config.structure !== undefined && { structure: config.structure }),
57
+ ...(config.navigation !== undefined && { navigation: config.navigation }),
58
+ ...(config.seo !== undefined && { seo: config.seo }),
59
+ ...(config.analytics !== undefined && { analytics: config.analytics }),
60
+ ...(config.deployment !== undefined && { deployment: config.deployment }),
61
+ ...(config.metadata !== undefined && { metadata: config.metadata }),
62
+ ...(config.tags !== undefined && { tags: config.tags }),
63
63
  }
64
64
 
65
65
  return registerProduct(site)
@@ -123,5 +123,9 @@ export function Analytics(
123
123
  id: string,
124
124
  config?: Record<string, unknown>
125
125
  ): AnalyticsConfig {
126
- return { provider, id, config }
126
+ return {
127
+ provider,
128
+ id,
129
+ ...(config !== undefined && { config }),
130
+ }
127
131
  }