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
@@ -1,130 +0,0 @@
1
- /**
2
- * Feature Definition
3
- * Primitives for defining product features
4
- */
5
-
6
- /**
7
- * Feature status options
8
- */
9
- export type FeatureStatus = 'active' | 'beta' | 'deprecated' | 'disabled'
10
-
11
- /**
12
- * Feature definition
13
- */
14
- export interface FeatureDefinition {
15
- /** Unique identifier */
16
- id: string
17
- /** Human-readable name */
18
- name: string
19
- /** Description of the feature */
20
- description: string
21
- /** Feature category */
22
- category?: string
23
- /** Dependencies on other features */
24
- dependencies?: string[]
25
- /** Metadata */
26
- metadata?: Record<string, unknown>
27
- /** Feature status */
28
- status?: FeatureStatus
29
- /** Version */
30
- version?: string
31
- }
32
-
33
- /**
34
- * Create a feature definition
35
- */
36
- export function Feature(config: Omit<FeatureDefinition, 'status'> & { status?: FeatureStatus }): FeatureDefinition {
37
- return {
38
- id: config.id,
39
- name: config.name,
40
- description: config.description,
41
- category: config.category,
42
- dependencies: config.dependencies,
43
- metadata: config.metadata,
44
- status: config.status ?? 'active',
45
- version: config.version,
46
- }
47
- }
48
-
49
- /**
50
- * Create and validate a feature definition
51
- */
52
- export function defineFeature(
53
- config: Omit<FeatureDefinition, 'status'> & { status?: FeatureStatus }
54
- ): FeatureDefinition {
55
- if (!config.id || config.id.trim() === '') {
56
- throw new Error('Feature ID is required')
57
- }
58
-
59
- return Feature(config)
60
- }
61
-
62
- /**
63
- * Feature registry interface
64
- */
65
- export interface FeatureRegistry {
66
- /** Register a feature */
67
- register(feature: FeatureDefinition): void
68
- /** Get a feature by ID */
69
- get(id: string): FeatureDefinition | undefined
70
- /** List all features */
71
- list(): FeatureDefinition[]
72
- /** List features by category */
73
- listByCategory(category: string): FeatureDefinition[]
74
- /** Get dependency graph for a feature */
75
- getDependencyGraph(featureId: string): string[]
76
- /** Clear registry */
77
- clear(): void
78
- }
79
-
80
- /**
81
- * Create a feature registry
82
- */
83
- export function createFeatureRegistry(): FeatureRegistry {
84
- const features = new Map<string, FeatureDefinition>()
85
-
86
- return {
87
- register(feature: FeatureDefinition): void {
88
- features.set(feature.id, feature)
89
- },
90
-
91
- get(id: string): FeatureDefinition | undefined {
92
- return features.get(id)
93
- },
94
-
95
- list(): FeatureDefinition[] {
96
- return Array.from(features.values())
97
- },
98
-
99
- listByCategory(category: string): FeatureDefinition[] {
100
- return Array.from(features.values()).filter((f) => f.category === category)
101
- },
102
-
103
- getDependencyGraph(featureId: string): string[] {
104
- const result: string[] = []
105
- const visited = new Set<string>()
106
-
107
- const traverse = (id: string) => {
108
- if (visited.has(id)) return
109
- visited.add(id)
110
-
111
- const feature = features.get(id)
112
- if (feature?.dependencies) {
113
- for (const depId of feature.dependencies) {
114
- traverse(depId)
115
- if (!result.includes(depId)) {
116
- result.push(depId)
117
- }
118
- }
119
- }
120
- }
121
-
122
- traverse(featureId)
123
- return result
124
- },
125
-
126
- clear(): void {
127
- features.clear()
128
- },
129
- }
130
- }
@@ -1,247 +0,0 @@
1
- /**
2
- * Feature Flags
3
- * Runtime feature flag system
4
- */
5
-
6
- import { createHash } from 'crypto'
7
-
8
- /**
9
- * Flag value types
10
- */
11
- export type FlagType = 'boolean' | 'string' | 'number' | 'json'
12
-
13
- /**
14
- * Targeting condition
15
- */
16
- export interface TargetingCondition {
17
- attribute: string
18
- operator: 'equals' | 'not_equals' | 'in' | 'not_in' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains'
19
- value: unknown
20
- }
21
-
22
- /**
23
- * Targeting rule
24
- */
25
- export interface TargetingRule {
26
- condition: TargetingCondition
27
- value: unknown
28
- }
29
-
30
- /**
31
- * Feature flag definition
32
- */
33
- export interface FeatureFlagDefinition {
34
- /** Unique key */
35
- key: string
36
- /** Human-readable name */
37
- name: string
38
- /** Flag type */
39
- type: FlagType
40
- /** Default value */
41
- defaultValue: unknown
42
- /** Allowed variants (for string type) */
43
- variants?: string[]
44
- /** Min value (for number type) */
45
- min?: number
46
- /** Max value (for number type) */
47
- max?: number
48
- /** Targeting rules */
49
- rules?: TargetingRule[]
50
- /** Rollout percentage (0-100) */
51
- rolloutPercentage?: number
52
- /** Description */
53
- description?: string
54
- }
55
-
56
- /**
57
- * Create a feature flag
58
- */
59
- export function FeatureFlag(config: FeatureFlagDefinition): FeatureFlagDefinition {
60
- return {
61
- key: config.key,
62
- name: config.name,
63
- type: config.type,
64
- defaultValue: config.defaultValue,
65
- variants: config.variants,
66
- min: config.min,
67
- max: config.max,
68
- rules: config.rules,
69
- rolloutPercentage: config.rolloutPercentage,
70
- description: config.description,
71
- }
72
- }
73
-
74
- /**
75
- * Create a feature flag (alias)
76
- */
77
- export const createFeatureFlag = FeatureFlag
78
-
79
- /**
80
- * Evaluation context for flag evaluation
81
- */
82
- export interface FlagEvaluationContext {
83
- userId?: string
84
- sessionId?: string
85
- attributes?: Record<string, unknown>
86
- }
87
-
88
- /**
89
- * Evaluation stats
90
- */
91
- export interface EvaluationStats {
92
- totalEvaluations: number
93
- trueCount: number
94
- falseCount: number
95
- }
96
-
97
- /**
98
- * Feature flag manager interface
99
- */
100
- export interface FeatureFlagManager {
101
- /** Register a flag */
102
- register(flag: FeatureFlagDefinition): void
103
- /** Get a flag by key */
104
- get(key: string): FeatureFlagDefinition | undefined
105
- /** Evaluate a flag */
106
- evaluate(key: string, context: FlagEvaluationContext): unknown
107
- /** Get evaluation stats */
108
- getEvaluationStats(key: string): EvaluationStats
109
- /** Set override for testing */
110
- setOverride(key: string, value: unknown): void
111
- /** Clear override */
112
- clearOverride(key: string): void
113
- /** List all flags */
114
- list(): FeatureFlagDefinition[]
115
- /** Remove a flag */
116
- remove(key: string): void
117
- }
118
-
119
- /**
120
- * Create a feature flag manager
121
- */
122
- export function createFeatureFlagManager(): FeatureFlagManager {
123
- const flags = new Map<string, FeatureFlagDefinition>()
124
- const overrides = new Map<string, unknown>()
125
- const stats = new Map<string, EvaluationStats>()
126
-
127
- const initStats = (key: string) => {
128
- if (!stats.has(key)) {
129
- stats.set(key, { totalEvaluations: 0, trueCount: 0, falseCount: 0 })
130
- }
131
- }
132
-
133
- const evaluateCondition = (condition: TargetingCondition, context: FlagEvaluationContext): boolean => {
134
- const attributeValue = context.attributes?.[condition.attribute]
135
-
136
- switch (condition.operator) {
137
- case 'equals':
138
- return attributeValue === condition.value
139
- case 'not_equals':
140
- return attributeValue !== condition.value
141
- case 'in':
142
- return Array.isArray(condition.value) && condition.value.includes(attributeValue)
143
- case 'not_in':
144
- return Array.isArray(condition.value) && !condition.value.includes(attributeValue)
145
- case 'gt':
146
- return typeof attributeValue === 'number' && attributeValue > (condition.value as number)
147
- case 'lt':
148
- return typeof attributeValue === 'number' && attributeValue < (condition.value as number)
149
- case 'gte':
150
- return typeof attributeValue === 'number' && attributeValue >= (condition.value as number)
151
- case 'lte':
152
- return typeof attributeValue === 'number' && attributeValue <= (condition.value as number)
153
- case 'contains':
154
- return typeof attributeValue === 'string' && attributeValue.includes(condition.value as string)
155
- default:
156
- return false
157
- }
158
- }
159
-
160
- const hashUserToPercentage = (userId: string, key: string): number => {
161
- const hash = createHash('md5').update(`${userId}-${key}`).digest('hex')
162
- const num = parseInt(hash.substring(0, 8), 16)
163
- return (num % 100) + 1
164
- }
165
-
166
- return {
167
- register(flag: FeatureFlagDefinition): void {
168
- flags.set(flag.key, flag)
169
- initStats(flag.key)
170
- },
171
-
172
- get(key: string): FeatureFlagDefinition | undefined {
173
- return flags.get(key)
174
- },
175
-
176
- evaluate(key: string, context: FlagEvaluationContext): unknown {
177
- initStats(key)
178
- const flagStats = stats.get(key)!
179
- flagStats.totalEvaluations++
180
-
181
- // Check for override first
182
- if (overrides.has(key)) {
183
- const value = overrides.get(key)
184
- if (value === true) flagStats.trueCount++
185
- else if (value === false) flagStats.falseCount++
186
- return value
187
- }
188
-
189
- const flag = flags.get(key)
190
- if (!flag) {
191
- return undefined
192
- }
193
-
194
- // Check targeting rules
195
- if (flag.rules) {
196
- for (const rule of flag.rules) {
197
- if (evaluateCondition(rule.condition, context)) {
198
- const value = rule.value
199
- if (value === true) flagStats.trueCount++
200
- else if (value === false) flagStats.falseCount++
201
- return value
202
- }
203
- }
204
- }
205
-
206
- // Check rollout percentage
207
- if (flag.rolloutPercentage !== undefined && context.userId) {
208
- const userPercentage = hashUserToPercentage(context.userId, key)
209
- if (userPercentage <= flag.rolloutPercentage) {
210
- if (flag.type === 'boolean') {
211
- flagStats.trueCount++
212
- return true
213
- }
214
- }
215
- }
216
-
217
- // Return default value
218
- const value = flag.defaultValue
219
- if (value === true) flagStats.trueCount++
220
- else if (value === false) flagStats.falseCount++
221
- return value
222
- },
223
-
224
- getEvaluationStats(key: string): EvaluationStats {
225
- initStats(key)
226
- return stats.get(key)!
227
- },
228
-
229
- setOverride(key: string, value: unknown): void {
230
- overrides.set(key, value)
231
- },
232
-
233
- clearOverride(key: string): void {
234
- overrides.delete(key)
235
- },
236
-
237
- list(): FeatureFlagDefinition[] {
238
- return Array.from(flags.values())
239
- },
240
-
241
- remove(key: string): void {
242
- flags.delete(key)
243
- overrides.delete(key)
244
- stats.delete(key)
245
- },
246
- }
247
- }
@@ -1,189 +0,0 @@
1
- /**
2
- * Feature Toggles
3
- * Operational feature toggles for release management
4
- */
5
-
6
- /**
7
- * Toggle categories following Martin Fowler's feature toggle taxonomy
8
- */
9
- export type ToggleCategory = 'ops' | 'release' | 'experiment' | 'permission'
10
-
11
- /**
12
- * Feature toggle definition
13
- */
14
- export interface FeatureToggleDefinition {
15
- /** Toggle name */
16
- name: string
17
- /** Category */
18
- category: ToggleCategory
19
- /** Whether toggle is enabled */
20
- enabled: boolean
21
- /** Description */
22
- description?: string
23
- /** Release date (for release toggles) */
24
- releaseDate?: Date
25
- /** Experiment ID (for experiment toggles) */
26
- experimentId?: string
27
- /** Required roles (for permission toggles) */
28
- requiredRoles?: string[]
29
- /** Expiration date */
30
- expiresAt?: Date
31
- }
32
-
33
- /**
34
- * Create a feature toggle
35
- */
36
- export function FeatureToggle(config: FeatureToggleDefinition): FeatureToggleDefinition {
37
- return {
38
- name: config.name,
39
- category: config.category,
40
- enabled: config.enabled,
41
- description: config.description,
42
- releaseDate: config.releaseDate,
43
- experimentId: config.experimentId,
44
- requiredRoles: config.requiredRoles,
45
- expiresAt: config.expiresAt,
46
- }
47
- }
48
-
49
- /**
50
- * Create a toggle (alias)
51
- */
52
- export const createToggle = FeatureToggle
53
-
54
- /**
55
- * Toggle evaluation context
56
- */
57
- export interface ToggleContext {
58
- roles?: string[]
59
- userId?: string
60
- attributes?: Record<string, unknown>
61
- }
62
-
63
- /**
64
- * Toggle service interface
65
- */
66
- export interface ToggleService {
67
- /** Register a toggle */
68
- register(toggle: FeatureToggleDefinition): void
69
- /** Check if toggle is enabled */
70
- isEnabled(name: string, context?: ToggleContext): boolean
71
- /** Enable a toggle */
72
- enable(name: string): void
73
- /** Disable a toggle */
74
- disable(name: string): void
75
- /** List toggles by category */
76
- listByCategory(category: ToggleCategory): FeatureToggleDefinition[]
77
- /** Bulk enable toggles */
78
- bulkEnable(names: string[]): void
79
- /** Bulk disable toggles */
80
- bulkDisable(names: string[]): void
81
- /** Export toggle state */
82
- export(): FeatureToggleDefinition[]
83
- /** Import toggle state */
84
- import(toggles: FeatureToggleDefinition[]): void
85
- /** Get toggle by name */
86
- get(name: string): FeatureToggleDefinition | undefined
87
- }
88
-
89
- /**
90
- * Create a toggle service
91
- */
92
- export function createToggleService(): ToggleService {
93
- const toggles = new Map<string, FeatureToggleDefinition>()
94
-
95
- const checkPermission = (toggle: FeatureToggleDefinition, context?: ToggleContext): boolean => {
96
- if (toggle.category !== 'permission' || !toggle.requiredRoles) {
97
- return true
98
- }
99
-
100
- if (!context?.roles) {
101
- return false
102
- }
103
-
104
- return toggle.requiredRoles.some((role) => context.roles!.includes(role))
105
- }
106
-
107
- const checkExpiration = (toggle: FeatureToggleDefinition): boolean => {
108
- if (!toggle.expiresAt) {
109
- return true
110
- }
111
-
112
- return new Date() < toggle.expiresAt
113
- }
114
-
115
- return {
116
- register(toggle: FeatureToggleDefinition): void {
117
- toggles.set(toggle.name, toggle)
118
- },
119
-
120
- isEnabled(name: string, context?: ToggleContext): boolean {
121
- const toggle = toggles.get(name)
122
- if (!toggle) {
123
- return false
124
- }
125
-
126
- // Check expiration
127
- if (!checkExpiration(toggle)) {
128
- return false
129
- }
130
-
131
- // Check permission for permission toggles
132
- if (!checkPermission(toggle, context)) {
133
- return false
134
- }
135
-
136
- return toggle.enabled
137
- },
138
-
139
- enable(name: string): void {
140
- const toggle = toggles.get(name)
141
- if (toggle) {
142
- toggle.enabled = true
143
- }
144
- },
145
-
146
- disable(name: string): void {
147
- const toggle = toggles.get(name)
148
- if (toggle) {
149
- toggle.enabled = false
150
- }
151
- },
152
-
153
- listByCategory(category: ToggleCategory): FeatureToggleDefinition[] {
154
- return Array.from(toggles.values()).filter((t) => t.category === category)
155
- },
156
-
157
- bulkEnable(names: string[]): void {
158
- for (const name of names) {
159
- const toggle = toggles.get(name)
160
- if (toggle) {
161
- toggle.enabled = true
162
- }
163
- }
164
- },
165
-
166
- bulkDisable(names: string[]): void {
167
- for (const name of names) {
168
- const toggle = toggles.get(name)
169
- if (toggle) {
170
- toggle.enabled = false
171
- }
172
- }
173
- },
174
-
175
- export(): FeatureToggleDefinition[] {
176
- return Array.from(toggles.values())
177
- },
178
-
179
- import(importedToggles: FeatureToggleDefinition[]): void {
180
- for (const toggle of importedToggles) {
181
- toggles.set(toggle.name, toggle)
182
- }
183
- },
184
-
185
- get(name: string): FeatureToggleDefinition | undefined {
186
- return toggles.get(name)
187
- },
188
- }
189
- }
package/src/index.js DELETED
@@ -1,35 +0,0 @@
1
- /**
2
- * digital-products - Primitives for defining and building digital products
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
13
- *
14
- * @packageDocumentation
15
- */
16
- // Export all types
17
- export * from './types.js';
18
- // Export entity definitions (Nouns) as namespace to avoid conflicts with types
19
- export * as Nouns from './entities/index.js';
20
- // Also export individual entity collections for convenience
21
- export { AllDigitalProductEntities, DigitalProductEntityCategories, Entities,
22
- // Category exports
23
- ProductEntities, ProductCategories, InterfaceEntities, InterfaceCategories, ContentEntities, ContentCategories, WebEntities, WebCategories, AIEntities, AICategories, LifecycleEntities, LifecycleCategories, } from './entities/index.js';
24
- // Export registry
25
- export { registry } from './registry.js';
26
- // Export product constructors
27
- export { Product, createProduct, registerProduct } from './product.js';
28
- export { App, Route, State, Auth } from './app.js';
29
- export { API, Endpoint, APIAuth, RateLimit } from './api.js';
30
- export { Content, Workflow } from './content.js';
31
- export { Data, Index, Relationship, Validate } from './data.js';
32
- export { Dataset } from './dataset.js';
33
- export { Site, Nav, SEO, Analytics } from './site.js';
34
- export { MCP, Tool, Resource, Prompt, MCPConfig } from './mcp.js';
35
- export { SDK, Export, Example } from './sdk.js';