digital-products 2.1.3 → 2.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.
Files changed (122) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +2 -0
  3. package/dist/api.js +7 -7
  4. package/dist/api.js.map +1 -1
  5. package/dist/app.js +6 -6
  6. package/dist/app.js.map +1 -1
  7. package/dist/client.d.ts +157 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +69 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/content.js +7 -7
  12. package/dist/content.js.map +1 -1
  13. package/dist/data.d.ts.map +1 -1
  14. package/dist/data.js +6 -6
  15. package/dist/data.js.map +1 -1
  16. package/dist/dataset.js +5 -5
  17. package/dist/dataset.js.map +1 -1
  18. package/dist/index.d.ts +92 -13
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +139 -15
  21. package/dist/index.js.map +1 -1
  22. package/dist/mcp.d.ts +1 -1
  23. package/dist/mcp.d.ts.map +1 -1
  24. package/dist/mcp.js +17 -10
  25. package/dist/mcp.js.map +1 -1
  26. package/dist/product.js +2 -2
  27. package/dist/product.js.map +1 -1
  28. package/dist/sdk.d.ts.map +1 -1
  29. package/dist/sdk.js +52 -16
  30. package/dist/sdk.js.map +1 -1
  31. package/dist/site.d.ts.map +1 -1
  32. package/dist/site.js +12 -8
  33. package/dist/site.js.map +1 -1
  34. package/dist/types.d.ts +830 -12
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js +495 -2
  37. package/dist/types.js.map +1 -1
  38. package/dist/worker.d.ts +205 -0
  39. package/dist/worker.d.ts.map +1 -0
  40. package/dist/worker.js +356 -0
  41. package/dist/worker.js.map +1 -0
  42. package/package.json +29 -13
  43. package/src/api.ts +7 -7
  44. package/src/app.ts +6 -6
  45. package/src/client.ts +192 -0
  46. package/src/content.ts +7 -7
  47. package/src/data.ts +12 -7
  48. package/src/dataset.ts +5 -5
  49. package/src/index.ts +151 -15
  50. package/src/mcp.ts +18 -11
  51. package/src/product.ts +2 -2
  52. package/src/sdk.ts +54 -15
  53. package/src/site.ts +12 -8
  54. package/src/types.ts +821 -12
  55. package/src/worker.ts +525 -0
  56. package/test/product.test.ts +53 -198
  57. package/test/unified-types.test.ts +589 -0
  58. package/test/worker.test.ts +912 -0
  59. package/vitest.config.ts +42 -0
  60. package/wrangler.jsonc +36 -0
  61. package/.turbo/turbo-build.log +0 -5
  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/mcp.js DELETED
@@ -1,139 +0,0 @@
1
- /**
2
- * MCP() - Define a Model Context Protocol server
3
- */
4
- import { registerProduct } from './product.js';
5
- /**
6
- * Create an MCP server definition
7
- *
8
- * @example
9
- * ```ts
10
- * const mcpServer = MCP({
11
- * id: 'my-mcp',
12
- * name: 'My MCP Server',
13
- * description: 'Custom MCP server for AI tools',
14
- * version: '1.0.0',
15
- * transport: 'stdio',
16
- * tools: [
17
- * Tool('searchFiles', 'Search for files in the project', {
18
- * query: 'Search query',
19
- * path: 'Directory to search in',
20
- * }),
21
- * Tool('readFile', 'Read file contents', {
22
- * path: 'File path to read',
23
- * }),
24
- * ],
25
- * resources: [
26
- * Resource('file://', 'Project Files', 'Access to project files'),
27
- * ],
28
- * prompts: [
29
- * Prompt('codeReview', 'Review code for best practices',
30
- * 'Review the following code:\n\n{{code}}'),
31
- * ],
32
- * })
33
- * ```
34
- */
35
- export function MCP(config) {
36
- const mcp = {
37
- type: 'mcp',
38
- id: config.id,
39
- name: config.name,
40
- description: config.description,
41
- version: config.version,
42
- transport: config.transport,
43
- tools: config.tools,
44
- resources: config.resources,
45
- prompts: config.prompts,
46
- config: config.config,
47
- metadata: config.metadata,
48
- tags: config.tags,
49
- status: config.status || 'active',
50
- };
51
- return registerProduct(mcp);
52
- }
53
- /**
54
- * Helper to create an MCP tool
55
- *
56
- * @example
57
- * ```ts
58
- * const tool = Tool(
59
- * 'searchCode',
60
- * 'Search code using regex',
61
- * {
62
- * pattern: 'Regex pattern to search for',
63
- * path: 'Directory to search in',
64
- * },
65
- * async (input) => {
66
- * // Tool implementation
67
- * return { matches: [] }
68
- * }
69
- * )
70
- * ```
71
- */
72
- export function Tool(name, description, inputSchema, handler) {
73
- return {
74
- name,
75
- description,
76
- inputSchema,
77
- handler,
78
- };
79
- }
80
- /**
81
- * Helper to create an MCP resource
82
- *
83
- * @example
84
- * ```ts
85
- * const resource = Resource(
86
- * 'file://project',
87
- * 'Project Files',
88
- * 'Access to all project files',
89
- * 'application/json'
90
- * )
91
- * ```
92
- */
93
- export function Resource(uri, name, description, mimeType) {
94
- return {
95
- uri,
96
- name,
97
- description,
98
- mimeType,
99
- };
100
- }
101
- /**
102
- * Helper to create an MCP prompt
103
- *
104
- * @example
105
- * ```ts
106
- * const prompt = Prompt(
107
- * 'summarize',
108
- * 'Summarize text',
109
- * 'Summarize the following:\n\n{{text}}',
110
- * { text: 'Text to summarize' }
111
- * )
112
- * ```
113
- */
114
- export function Prompt(name, description, template, args) {
115
- return {
116
- name,
117
- description,
118
- template,
119
- arguments: args,
120
- };
121
- }
122
- /**
123
- * Helper to configure MCP server
124
- *
125
- * @example
126
- * ```ts
127
- * const config = MCPConfig({
128
- * port: 3000,
129
- * host: 'localhost',
130
- * auth: {
131
- * type: 'bearer',
132
- * token: process.env.MCP_TOKEN,
133
- * },
134
- * })
135
- * ```
136
- */
137
- export function MCPConfig(config) {
138
- return config;
139
- }
@@ -1,386 +0,0 @@
1
- /**
2
- * Billing Service
3
- * Subscription and invoice management
4
- */
5
-
6
- import { randomUUID } from 'crypto'
7
-
8
- /**
9
- * Subscription status
10
- */
11
- export type SubscriptionStatus = 'active' | 'trialing' | 'canceled' | 'past_due' | 'paused'
12
-
13
- /**
14
- * Invoice status
15
- */
16
- export type InvoiceStatus = 'draft' | 'open' | 'paid' | 'void' | 'uncollectible'
17
-
18
- /**
19
- * Payment method type
20
- */
21
- export type PaymentMethodType = 'card' | 'bank_transfer' | 'paypal'
22
-
23
- /**
24
- * Subscription definition
25
- */
26
- export interface Subscription {
27
- id: string
28
- customerId: string
29
- planId: string
30
- status: SubscriptionStatus
31
- startDate: Date
32
- currentPeriodStart: Date
33
- currentPeriodEnd: Date
34
- trialEnd?: Date
35
- cancelAtPeriodEnd: boolean
36
- scheduledPlanId?: string
37
- metadata?: Record<string, unknown>
38
- }
39
-
40
- /**
41
- * Invoice definition
42
- */
43
- export interface Invoice {
44
- id: string
45
- subscriptionId: string
46
- customerId: string
47
- status: InvoiceStatus
48
- subtotal: number
49
- discountAmount: number
50
- total: number
51
- currency: string
52
- usageCharges?: { metric: string; quantity: number; amount: number }[]
53
- paidAt?: Date
54
- createdAt: Date
55
- dueDate: Date
56
- }
57
-
58
- /**
59
- * Payment method
60
- */
61
- export interface PaymentMethod {
62
- id: string
63
- customerId: string
64
- type: PaymentMethodType
65
- details: {
66
- last4?: string
67
- brand?: string
68
- expMonth?: number
69
- expYear?: number
70
- }
71
- isDefault: boolean
72
- }
73
-
74
- /**
75
- * Usage record
76
- */
77
- export interface UsageRecord {
78
- subscriptionId: string
79
- metric: string
80
- quantity: number
81
- timestamp: Date
82
- }
83
-
84
- /**
85
- * Billing event
86
- */
87
- export interface BillingEvent {
88
- type: string
89
- timestamp: Date
90
- data: Record<string, unknown>
91
- }
92
-
93
- /**
94
- * Billing service options
95
- */
96
- export interface BillingServiceOptions {
97
- planPrices?: Record<string, number>
98
- coupons?: Record<string, number>
99
- }
100
-
101
- /**
102
- * Billing service interface
103
- */
104
- export interface BillingService {
105
- // Subscriptions
106
- createSubscription(params: {
107
- customerId: string
108
- planId: string
109
- startDate: Date
110
- trialDays?: number
111
- }): Subscription
112
-
113
- cancelSubscription(
114
- subscriptionId: string,
115
- options: { immediate: boolean }
116
- ): Subscription
117
-
118
- changeSubscription(
119
- subscriptionId: string,
120
- options: { newPlanId: string; prorate: boolean }
121
- ): Subscription
122
-
123
- getSubscription(id: string): Subscription | undefined
124
- getSubscriptionsByCustomer(customerId: string): Subscription[]
125
-
126
- // Invoices
127
- generateInvoice(
128
- subscriptionId: string,
129
- options?: { couponCode?: string }
130
- ): Invoice
131
-
132
- markInvoicePaid(
133
- invoiceId: string,
134
- options: { paymentMethodId: string; paidAt: Date }
135
- ): Invoice
136
-
137
- getInvoice(id: string): Invoice | undefined
138
- getInvoicesByCustomer(customerId: string): Invoice[]
139
-
140
- // Usage
141
- recordUsage(
142
- subscriptionId: string,
143
- usage: { metric: string; quantity: number; timestamp: Date }
144
- ): void
145
-
146
- // Payment methods
147
- addPaymentMethod(params: {
148
- customerId: string
149
- type: PaymentMethodType
150
- details: PaymentMethod['details']
151
- }): PaymentMethod
152
-
153
- setDefaultPaymentMethod(customerId: string, paymentMethodId: string): void
154
- getDefaultPaymentMethod(customerId: string): PaymentMethod | undefined
155
- getPaymentMethods(customerId: string): PaymentMethod[]
156
- removePaymentMethod(paymentMethodId: string): void
157
-
158
- // Events
159
- on(event: string, handler: (e: BillingEvent) => void): void
160
- off(event: string, handler: (e: BillingEvent) => void): void
161
- }
162
-
163
- /**
164
- * Create a billing service
165
- */
166
- export function createBillingService(options: BillingServiceOptions = {}): BillingService {
167
- const subscriptions = new Map<string, Subscription>()
168
- const invoices = new Map<string, Invoice>()
169
- const paymentMethods = new Map<string, PaymentMethod>()
170
- const usageRecords: UsageRecord[] = []
171
- const eventHandlers = new Map<string, Set<(e: BillingEvent) => void>>()
172
-
173
- const defaultPrices: Record<string, number> = {
174
- 'pro-monthly': 29,
175
- 'enterprise-monthly': 99,
176
- metered: 0,
177
- ...options.planPrices,
178
- }
179
-
180
- const coupons: Record<string, number> = {
181
- SAVE20: 20,
182
- ...options.coupons,
183
- }
184
-
185
- const emit = (type: string, data: Record<string, unknown>) => {
186
- const event: BillingEvent = { type, timestamp: new Date(), data }
187
- const handlers = eventHandlers.get(type)
188
- if (handlers) {
189
- for (const handler of handlers) {
190
- handler(event)
191
- }
192
- }
193
- }
194
-
195
- return {
196
- createSubscription(params): Subscription {
197
- const id = randomUUID()
198
- const periodEnd = new Date(params.startDate)
199
- periodEnd.setMonth(periodEnd.getMonth() + 1)
200
-
201
- let trialEnd: Date | undefined
202
- let status: SubscriptionStatus = 'active'
203
-
204
- if (params.trialDays) {
205
- trialEnd = new Date(params.startDate)
206
- trialEnd.setDate(trialEnd.getDate() + params.trialDays)
207
- status = 'trialing'
208
- }
209
-
210
- const subscription: Subscription = {
211
- id,
212
- customerId: params.customerId,
213
- planId: params.planId,
214
- status,
215
- startDate: params.startDate,
216
- currentPeriodStart: params.startDate,
217
- currentPeriodEnd: periodEnd,
218
- trialEnd,
219
- cancelAtPeriodEnd: false,
220
- }
221
-
222
- subscriptions.set(id, subscription)
223
- emit('subscription.created', { subscriptionId: id, customerId: params.customerId })
224
- return subscription
225
- },
226
-
227
- cancelSubscription(subscriptionId, options): Subscription {
228
- const subscription = subscriptions.get(subscriptionId)
229
- if (!subscription) {
230
- throw new Error('Subscription not found')
231
- }
232
-
233
- if (options.immediate) {
234
- subscription.status = 'canceled'
235
- } else {
236
- subscription.cancelAtPeriodEnd = true
237
- }
238
-
239
- emit('subscription.canceled', { subscriptionId })
240
- return subscription
241
- },
242
-
243
- changeSubscription(subscriptionId, options): Subscription {
244
- const subscription = subscriptions.get(subscriptionId)
245
- if (!subscription) {
246
- throw new Error('Subscription not found')
247
- }
248
-
249
- if (options.prorate) {
250
- subscription.planId = options.newPlanId
251
- } else {
252
- subscription.scheduledPlanId = options.newPlanId
253
- }
254
-
255
- emit('subscription.updated', { subscriptionId, newPlanId: options.newPlanId })
256
- return subscription
257
- },
258
-
259
- getSubscription(id): Subscription | undefined {
260
- return subscriptions.get(id)
261
- },
262
-
263
- getSubscriptionsByCustomer(customerId): Subscription[] {
264
- return Array.from(subscriptions.values()).filter((s) => s.customerId === customerId)
265
- },
266
-
267
- generateInvoice(subscriptionId, invoiceOptions = {}): Invoice {
268
- const subscription = subscriptions.get(subscriptionId)
269
- if (!subscription) {
270
- throw new Error('Subscription not found')
271
- }
272
-
273
- const id = randomUUID()
274
- const subtotal = defaultPrices[subscription.planId] ?? 29
275
- let discountAmount = 0
276
-
277
- if (invoiceOptions.couponCode && coupons[invoiceOptions.couponCode]) {
278
- discountAmount = (subtotal * coupons[invoiceOptions.couponCode]) / 100
279
- }
280
-
281
- // Add usage charges if applicable
282
- let usageCharges: Invoice['usageCharges']
283
- const subscriptionUsage = usageRecords.filter((u) => u.subscriptionId === subscriptionId)
284
- if (subscriptionUsage.length > 0) {
285
- usageCharges = subscriptionUsage.map((u) => ({
286
- metric: u.metric,
287
- quantity: u.quantity,
288
- amount: u.quantity * 0.001, // Example rate
289
- }))
290
- }
291
-
292
- const invoice: Invoice = {
293
- id,
294
- subscriptionId,
295
- customerId: subscription.customerId,
296
- status: 'draft',
297
- subtotal,
298
- discountAmount,
299
- total: subtotal - discountAmount + (usageCharges?.reduce((sum, c) => sum + c.amount, 0) ?? 0),
300
- currency: 'USD',
301
- usageCharges,
302
- createdAt: new Date(),
303
- dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
304
- }
305
-
306
- invoices.set(id, invoice)
307
- return invoice
308
- },
309
-
310
- markInvoicePaid(invoiceId, options): Invoice {
311
- const invoice = invoices.get(invoiceId)
312
- if (!invoice) {
313
- throw new Error('Invoice not found')
314
- }
315
-
316
- invoice.status = 'paid'
317
- invoice.paidAt = options.paidAt
318
-
319
- emit('invoice.paid', { invoiceId, amount: invoice.total })
320
- return invoice
321
- },
322
-
323
- getInvoice(id): Invoice | undefined {
324
- return invoices.get(id)
325
- },
326
-
327
- getInvoicesByCustomer(customerId): Invoice[] {
328
- return Array.from(invoices.values()).filter((i) => i.customerId === customerId)
329
- },
330
-
331
- recordUsage(subscriptionId, usage): void {
332
- usageRecords.push({ subscriptionId, ...usage })
333
- },
334
-
335
- addPaymentMethod(params): PaymentMethod {
336
- const id = randomUUID()
337
- const existingMethods = Array.from(paymentMethods.values()).filter(
338
- (pm) => pm.customerId === params.customerId
339
- )
340
-
341
- const method: PaymentMethod = {
342
- id,
343
- customerId: params.customerId,
344
- type: params.type,
345
- details: params.details,
346
- isDefault: existingMethods.length === 0,
347
- }
348
-
349
- paymentMethods.set(id, method)
350
- return method
351
- },
352
-
353
- setDefaultPaymentMethod(customerId, paymentMethodId): void {
354
- for (const method of paymentMethods.values()) {
355
- if (method.customerId === customerId) {
356
- method.isDefault = method.id === paymentMethodId
357
- }
358
- }
359
- },
360
-
361
- getDefaultPaymentMethod(customerId): PaymentMethod | undefined {
362
- return Array.from(paymentMethods.values()).find(
363
- (pm) => pm.customerId === customerId && pm.isDefault
364
- )
365
- },
366
-
367
- getPaymentMethods(customerId): PaymentMethod[] {
368
- return Array.from(paymentMethods.values()).filter((pm) => pm.customerId === customerId)
369
- },
370
-
371
- removePaymentMethod(paymentMethodId): void {
372
- paymentMethods.delete(paymentMethodId)
373
- },
374
-
375
- on(event, handler): void {
376
- if (!eventHandlers.has(event)) {
377
- eventHandlers.set(event, new Set())
378
- }
379
- eventHandlers.get(event)!.add(handler)
380
- },
381
-
382
- off(event, handler): void {
383
- eventHandlers.get(event)?.delete(handler)
384
- },
385
- }
386
- }