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.
- package/.turbo/turbo-build.log +4 -5
- package/CHANGELOG.md +17 -0
- package/README.md +2 -0
- package/dist/api.js +7 -7
- package/dist/api.js.map +1 -1
- package/dist/app.js +6 -6
- package/dist/app.js.map +1 -1
- package/dist/client.d.ts +157 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +69 -0
- package/dist/client.js.map +1 -0
- package/dist/content.js +7 -7
- package/dist/content.js.map +1 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +6 -6
- package/dist/data.js.map +1 -1
- package/dist/dataset.js +5 -5
- package/dist/dataset.js.map +1 -1
- package/dist/index.d.ts +92 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +139 -15
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +17 -10
- package/dist/mcp.js.map +1 -1
- package/dist/product.js +2 -2
- package/dist/product.js.map +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +52 -16
- package/dist/sdk.js.map +1 -1
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +12 -8
- package/dist/site.js.map +1 -1
- package/dist/types.d.ts +830 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +495 -2
- package/dist/types.js.map +1 -1
- package/dist/worker.d.ts +205 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +356 -0
- package/dist/worker.js.map +1 -0
- package/package.json +29 -13
- package/src/api.ts +7 -7
- package/src/app.ts +6 -6
- package/src/client.ts +192 -0
- package/src/content.ts +7 -7
- package/src/data.ts +12 -7
- package/src/dataset.ts +5 -5
- package/src/index.ts +151 -15
- package/src/mcp.ts +18 -11
- package/src/product.ts +2 -2
- package/src/sdk.ts +54 -15
- package/src/site.ts +12 -8
- package/src/types.ts +821 -12
- package/src/worker.ts +525 -0
- package/test/product.test.ts +53 -198
- package/test/unified-types.test.ts +589 -0
- package/test/worker.test.ts +912 -0
- package/vitest.config.ts +42 -0
- package/wrangler.jsonc +36 -0
- package/LICENSE +0 -21
- package/dist/features/define.d.ts +0 -63
- package/dist/features/define.d.ts.map +0 -1
- package/dist/features/define.js +0 -72
- package/dist/features/define.js.map +0 -1
- package/dist/features/flags.d.ts +0 -98
- package/dist/features/flags.d.ts.map +0 -1
- package/dist/features/flags.js +0 -145
- package/dist/features/flags.js.map +0 -1
- package/dist/features/toggles.d.ts +0 -75
- package/dist/features/toggles.d.ts.map +0 -1
- package/dist/features/toggles.js +0 -107
- package/dist/features/toggles.js.map +0 -1
- package/dist/tiers/define.d.ts +0 -63
- package/dist/tiers/define.d.ts.map +0 -1
- package/dist/tiers/define.js +0 -78
- package/dist/tiers/define.js.map +0 -1
- package/dist/tiers/entitlements.d.ts +0 -94
- package/dist/tiers/entitlements.d.ts.map +0 -1
- package/dist/tiers/entitlements.js +0 -94
- package/dist/tiers/entitlements.js.map +0 -1
- package/src/api.js +0 -128
- package/src/app.js +0 -106
- package/src/content.js +0 -77
- package/src/data.js +0 -106
- package/src/dataset.js +0 -49
- package/src/entities/ai.js +0 -858
- package/src/entities/content.js +0 -783
- package/src/entities/index.js +0 -88
- package/src/entities/interfaces.js +0 -929
- package/src/entities/lifecycle.js +0 -803
- package/src/entities/products.js +0 -797
- package/src/entities/web.js +0 -657
- package/src/features/define.ts +0 -130
- package/src/features/flags.ts +0 -247
- package/src/features/toggles.ts +0 -189
- package/src/index.js +0 -35
- package/src/mcp.js +0 -139
- package/src/pricing/billing.ts +0 -386
- package/src/pricing/plans.ts +0 -214
- package/src/product.js +0 -53
- package/src/registry.js +0 -31
- package/src/sdk.js +0 -127
- package/src/site.js +0 -112
- package/src/tiers/define.ts +0 -137
- package/src/tiers/entitlements.ts +0 -201
- package/src/types.js +0 -4
- package/test/analytics/events.test.ts +0 -319
- package/test/analytics/experiments.test.ts +0 -327
- package/test/features/define.test.ts +0 -187
- package/test/features/flags.test.ts +0 -259
- package/test/features/toggles.test.ts +0 -178
- package/test/lifecycle/stages.test.ts +0 -233
- package/test/lifecycle/transitions.test.ts +0 -207
- package/test/onboarding/flows.test.ts +0 -307
- package/test/pricing/billing.test.ts +0 -287
- package/test/pricing/plans.test.ts +0 -307
- package/test/roadmap/milestones.test.ts +0 -231
- package/test/roadmap/priorities.test.ts +0 -239
- package/test/tiers/define.test.ts +0 -192
- package/test/tiers/entitlements.test.ts +0 -220
package/src/pricing/plans.ts
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pricing Plans
|
|
3
|
-
* Product pricing and billing plans
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Billing interval
|
|
8
|
-
*/
|
|
9
|
-
export type BillingInterval = 'monthly' | 'yearly' | 'custom'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Currency type
|
|
13
|
-
*/
|
|
14
|
-
export type Currency = 'USD' | 'EUR' | 'GBP' | 'CAD' | 'AUD' | 'JPY' | string
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Plan discount
|
|
18
|
-
*/
|
|
19
|
-
export interface PlanDiscount {
|
|
20
|
-
percentage: number
|
|
21
|
-
monthlyEquivalent: number
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Trial configuration
|
|
26
|
-
*/
|
|
27
|
-
export interface TrialConfig {
|
|
28
|
-
days: number
|
|
29
|
-
requiresPaymentMethod: boolean
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Usage-based pricing
|
|
34
|
-
*/
|
|
35
|
-
export interface UsageBasedPricing {
|
|
36
|
-
metric: string
|
|
37
|
-
unitPrice: number
|
|
38
|
-
includedUnits: number
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Plan addon
|
|
43
|
-
*/
|
|
44
|
-
export interface PlanAddon {
|
|
45
|
-
id: string
|
|
46
|
-
price: number
|
|
47
|
-
name?: string
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Pricing plan definition
|
|
52
|
-
*/
|
|
53
|
-
export interface PricingPlanDefinition {
|
|
54
|
-
/** Unique identifier */
|
|
55
|
-
id: string
|
|
56
|
-
/** Human-readable name */
|
|
57
|
-
name: string
|
|
58
|
-
/** Associated tier ID */
|
|
59
|
-
tierId: string
|
|
60
|
-
/** Price */
|
|
61
|
-
price: number
|
|
62
|
-
/** Currency */
|
|
63
|
-
currency: Currency
|
|
64
|
-
/** Billing interval */
|
|
65
|
-
interval: BillingInterval
|
|
66
|
-
/** Custom interval in months */
|
|
67
|
-
intervalMonths?: number
|
|
68
|
-
/** Discount info */
|
|
69
|
-
discount?: PlanDiscount
|
|
70
|
-
/** Trial configuration */
|
|
71
|
-
trial?: TrialConfig
|
|
72
|
-
/** Usage-based pricing */
|
|
73
|
-
usageBased?: UsageBasedPricing
|
|
74
|
-
/** Available addons */
|
|
75
|
-
addons?: PlanAddon[]
|
|
76
|
-
/** Description */
|
|
77
|
-
description?: string
|
|
78
|
-
/** Metadata */
|
|
79
|
-
metadata?: Record<string, unknown>
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Create a pricing plan
|
|
84
|
-
*/
|
|
85
|
-
export function PricingPlan(config: PricingPlanDefinition): PricingPlanDefinition {
|
|
86
|
-
return {
|
|
87
|
-
id: config.id,
|
|
88
|
-
name: config.name,
|
|
89
|
-
tierId: config.tierId,
|
|
90
|
-
price: config.price,
|
|
91
|
-
currency: config.currency,
|
|
92
|
-
interval: config.interval,
|
|
93
|
-
intervalMonths: config.intervalMonths,
|
|
94
|
-
discount: config.discount,
|
|
95
|
-
trial: config.trial,
|
|
96
|
-
usageBased: config.usageBased,
|
|
97
|
-
addons: config.addons,
|
|
98
|
-
description: config.description,
|
|
99
|
-
metadata: config.metadata,
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Create and validate a pricing plan
|
|
105
|
-
*/
|
|
106
|
-
export function createPricingPlan(config: PricingPlanDefinition): PricingPlanDefinition {
|
|
107
|
-
if (config.price < 0) {
|
|
108
|
-
throw new Error('Price must be non-negative')
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (config.interval === 'custom' && !config.intervalMonths) {
|
|
112
|
-
throw new Error('Custom interval requires intervalMonths')
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return PricingPlan(config)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Savings calculation result
|
|
120
|
-
*/
|
|
121
|
-
export interface SavingsResult {
|
|
122
|
-
percentage: number
|
|
123
|
-
amount: number
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Plan registry interface
|
|
128
|
-
*/
|
|
129
|
-
export interface PlanRegistry {
|
|
130
|
-
/** Register a plan */
|
|
131
|
-
register(plan: PricingPlanDefinition): void
|
|
132
|
-
/** Get a plan by ID */
|
|
133
|
-
get(id: string): PricingPlanDefinition | undefined
|
|
134
|
-
/** List all plans */
|
|
135
|
-
list(): PricingPlanDefinition[]
|
|
136
|
-
/** List plans by tier */
|
|
137
|
-
listByTier(tierId: string): PricingPlanDefinition[]
|
|
138
|
-
/** List plans by interval */
|
|
139
|
-
listByInterval(interval: BillingInterval): PricingPlanDefinition[]
|
|
140
|
-
/** Get monthly equivalent price */
|
|
141
|
-
getMonthlyEquivalent(planId: string): number
|
|
142
|
-
/** Calculate savings between plans */
|
|
143
|
-
calculateSavings(fromPlanId: string, toPlanId: string): SavingsResult
|
|
144
|
-
/** Clear registry */
|
|
145
|
-
clear(): void
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Create a plan registry
|
|
150
|
-
*/
|
|
151
|
-
export function createPlanRegistry(): PlanRegistry {
|
|
152
|
-
const plans = new Map<string, PricingPlanDefinition>()
|
|
153
|
-
|
|
154
|
-
const getMonths = (plan: PricingPlanDefinition): number => {
|
|
155
|
-
if (plan.interval === 'monthly') return 1
|
|
156
|
-
if (plan.interval === 'yearly') return 12
|
|
157
|
-
return plan.intervalMonths ?? 1
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
register(plan: PricingPlanDefinition): void {
|
|
162
|
-
plans.set(plan.id, plan)
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
get(id: string): PricingPlanDefinition | undefined {
|
|
166
|
-
return plans.get(id)
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
list(): PricingPlanDefinition[] {
|
|
170
|
-
return Array.from(plans.values())
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
listByTier(tierId: string): PricingPlanDefinition[] {
|
|
174
|
-
return Array.from(plans.values()).filter((p) => p.tierId === tierId)
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
listByInterval(interval: BillingInterval): PricingPlanDefinition[] {
|
|
178
|
-
return Array.from(plans.values()).filter((p) => p.interval === interval)
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
getMonthlyEquivalent(planId: string): number {
|
|
182
|
-
const plan = plans.get(planId)
|
|
183
|
-
if (!plan) return 0
|
|
184
|
-
|
|
185
|
-
const months = getMonths(plan)
|
|
186
|
-
return plan.price / months
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
calculateSavings(fromPlanId: string, toPlanId: string): SavingsResult {
|
|
190
|
-
const fromPlan = plans.get(fromPlanId)
|
|
191
|
-
const toPlan = plans.get(toPlanId)
|
|
192
|
-
|
|
193
|
-
if (!fromPlan || !toPlan) {
|
|
194
|
-
return { percentage: 0, amount: 0 }
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const fromMonthly = fromPlan.price / getMonths(fromPlan)
|
|
198
|
-
const toMonthly = toPlan.price / getMonths(toPlan)
|
|
199
|
-
|
|
200
|
-
// Annualized comparison
|
|
201
|
-
const fromYearly = fromMonthly * 12
|
|
202
|
-
const toYearly = toMonthly * 12
|
|
203
|
-
|
|
204
|
-
const amount = fromYearly - toYearly
|
|
205
|
-
const percentage = (amount / fromYearly) * 100
|
|
206
|
-
|
|
207
|
-
return { percentage, amount }
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
clear(): void {
|
|
211
|
-
plans.clear()
|
|
212
|
-
},
|
|
213
|
-
}
|
|
214
|
-
}
|
package/src/product.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic Product() constructor
|
|
3
|
-
*/
|
|
4
|
-
import { registry } from './registry.js';
|
|
5
|
-
/**
|
|
6
|
-
* Create a generic digital product definition
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* const product = Product({
|
|
11
|
-
* id: 'my-product',
|
|
12
|
-
* name: 'My Product',
|
|
13
|
-
* description: 'A digital product',
|
|
14
|
-
* version: '1.0.0',
|
|
15
|
-
* })
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
export function Product(config) {
|
|
19
|
-
const product = {
|
|
20
|
-
id: config.id,
|
|
21
|
-
name: config.name,
|
|
22
|
-
description: config.description,
|
|
23
|
-
version: config.version,
|
|
24
|
-
metadata: config.metadata,
|
|
25
|
-
tags: config.tags,
|
|
26
|
-
status: config.status || 'active',
|
|
27
|
-
};
|
|
28
|
-
return product;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Create and register a product in one step
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```ts
|
|
35
|
-
* const product = createProduct({
|
|
36
|
-
* id: 'my-product',
|
|
37
|
-
* name: 'My Product',
|
|
38
|
-
* description: 'A digital product',
|
|
39
|
-
* version: '1.0.0',
|
|
40
|
-
* })
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
export function createProduct(config) {
|
|
44
|
-
const product = Product(config);
|
|
45
|
-
return product;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Create and register any product definition
|
|
49
|
-
*/
|
|
50
|
-
export function registerProduct(product) {
|
|
51
|
-
registry.register(product);
|
|
52
|
-
return product;
|
|
53
|
-
}
|
package/src/registry.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Product registry implementation
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* In-memory product registry
|
|
6
|
-
*/
|
|
7
|
-
class InMemoryProductRegistry {
|
|
8
|
-
products = new Map();
|
|
9
|
-
register(product) {
|
|
10
|
-
this.products.set(product.id, product);
|
|
11
|
-
}
|
|
12
|
-
get(id) {
|
|
13
|
-
return this.products.get(id);
|
|
14
|
-
}
|
|
15
|
-
list() {
|
|
16
|
-
return Array.from(this.products.values());
|
|
17
|
-
}
|
|
18
|
-
listByType(type) {
|
|
19
|
-
return this.list().filter((p) => p.type === type);
|
|
20
|
-
}
|
|
21
|
-
remove(id) {
|
|
22
|
-
return this.products.delete(id);
|
|
23
|
-
}
|
|
24
|
-
clear() {
|
|
25
|
-
this.products.clear();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Global product registry instance
|
|
30
|
-
*/
|
|
31
|
-
export const registry = new InMemoryProductRegistry();
|
package/src/sdk.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SDK() - Define a software development kit
|
|
3
|
-
*/
|
|
4
|
-
import { registerProduct } from './product.js';
|
|
5
|
-
/**
|
|
6
|
-
* Create an SDK definition
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* const mySDK = SDK({
|
|
11
|
-
* id: 'my-sdk',
|
|
12
|
-
* name: 'My SDK',
|
|
13
|
-
* description: 'JavaScript SDK for My API',
|
|
14
|
-
* version: '1.0.0',
|
|
15
|
-
* language: 'typescript',
|
|
16
|
-
* api: 'my-api',
|
|
17
|
-
* exports: [
|
|
18
|
-
* Export('function', 'createClient', 'Create an API client', {
|
|
19
|
-
* parameters: {
|
|
20
|
-
* apiKey: 'API key for authentication',
|
|
21
|
-
* baseUrl: 'Optional base URL',
|
|
22
|
-
* },
|
|
23
|
-
* returns: 'API client instance',
|
|
24
|
-
* }),
|
|
25
|
-
* Export('class', 'APIClient', 'Main API client', {
|
|
26
|
-
* methods: [
|
|
27
|
-
* Export('function', 'get', 'GET request', {
|
|
28
|
-
* parameters: { path: 'Request path' },
|
|
29
|
-
* returns: 'Response data',
|
|
30
|
-
* }),
|
|
31
|
-
* Export('function', 'post', 'POST request', {
|
|
32
|
-
* parameters: { path: 'Request path', data: 'Request body' },
|
|
33
|
-
* returns: 'Response data',
|
|
34
|
-
* }),
|
|
35
|
-
* ],
|
|
36
|
-
* }),
|
|
37
|
-
* ],
|
|
38
|
-
* install: 'npm install my-sdk',
|
|
39
|
-
* examples: [
|
|
40
|
-
* Example(
|
|
41
|
-
* 'Basic Usage',
|
|
42
|
-
* 'Create a client and make a request',
|
|
43
|
-
* `import { createClient } from 'my-sdk'
|
|
44
|
-
*
|
|
45
|
-
* const client = createClient({ apiKey: 'YOUR_API_KEY' })
|
|
46
|
-
* const users = await client.get('/users')
|
|
47
|
-
* console.log(users)`
|
|
48
|
-
* ),
|
|
49
|
-
* ],
|
|
50
|
-
* })
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
export function SDK(config) {
|
|
54
|
-
const sdk = {
|
|
55
|
-
type: 'sdk',
|
|
56
|
-
id: config.id,
|
|
57
|
-
name: config.name,
|
|
58
|
-
description: config.description,
|
|
59
|
-
version: config.version,
|
|
60
|
-
language: config.language,
|
|
61
|
-
api: config.api,
|
|
62
|
-
exports: config.exports,
|
|
63
|
-
install: config.install,
|
|
64
|
-
docs: config.docs,
|
|
65
|
-
examples: config.examples,
|
|
66
|
-
metadata: config.metadata,
|
|
67
|
-
tags: config.tags,
|
|
68
|
-
status: config.status || 'active',
|
|
69
|
-
};
|
|
70
|
-
return registerProduct(sdk);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Helper to create an SDK export
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```ts
|
|
77
|
-
* const fn = Export('function', 'calculateTotal', 'Calculate order total', {
|
|
78
|
-
* parameters: {
|
|
79
|
-
* items: ['Array of order items'],
|
|
80
|
-
* taxRate: 'Tax rate (number)',
|
|
81
|
-
* },
|
|
82
|
-
* returns: 'Total amount (number)',
|
|
83
|
-
* })
|
|
84
|
-
*
|
|
85
|
-
* const cls = Export('class', 'OrderManager', 'Manage orders', {
|
|
86
|
-
* methods: [
|
|
87
|
-
* Export('function', 'create', 'Create order', {
|
|
88
|
-
* parameters: { order: 'Order data' },
|
|
89
|
-
* returns: 'Created order',
|
|
90
|
-
* }),
|
|
91
|
-
* ],
|
|
92
|
-
* })
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
export function Export(type, name, description, options) {
|
|
96
|
-
return {
|
|
97
|
-
type,
|
|
98
|
-
name,
|
|
99
|
-
description,
|
|
100
|
-
parameters: options?.parameters,
|
|
101
|
-
returns: options?.returns,
|
|
102
|
-
methods: options?.methods,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Helper to create an SDK example
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* ```ts
|
|
110
|
-
* const example = Example(
|
|
111
|
-
* 'Authentication',
|
|
112
|
-
* 'How to authenticate with the API',
|
|
113
|
-
* `const client = createClient({
|
|
114
|
-
* apiKey: process.env.API_KEY,
|
|
115
|
-
* })`,
|
|
116
|
-
* '{ authenticated: true }'
|
|
117
|
-
* )
|
|
118
|
-
* ```
|
|
119
|
-
*/
|
|
120
|
-
export function Example(title, description, code, output) {
|
|
121
|
-
return {
|
|
122
|
-
title,
|
|
123
|
-
description,
|
|
124
|
-
code,
|
|
125
|
-
output,
|
|
126
|
-
};
|
|
127
|
-
}
|
package/src/site.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Site() - Define a website
|
|
3
|
-
*/
|
|
4
|
-
import { registerProduct } from './product.js';
|
|
5
|
-
/**
|
|
6
|
-
* Create a site definition
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* const docsSite = Site({
|
|
11
|
-
* id: 'docs',
|
|
12
|
-
* name: 'Documentation Site',
|
|
13
|
-
* description: 'Product documentation',
|
|
14
|
-
* version: '1.0.0',
|
|
15
|
-
* generator: 'fumadocs',
|
|
16
|
-
* structure: {
|
|
17
|
-
* home: '/docs/index.mdx',
|
|
18
|
-
* docs: [
|
|
19
|
-
* '/docs/getting-started.mdx',
|
|
20
|
-
* '/docs/api-reference.mdx',
|
|
21
|
-
* ],
|
|
22
|
-
* },
|
|
23
|
-
* navigation: [
|
|
24
|
-
* Nav('Home', '/'),
|
|
25
|
-
* Nav('Docs', '/docs', {
|
|
26
|
-
* children: [
|
|
27
|
-
* Nav('Getting Started', '/docs/getting-started'),
|
|
28
|
-
* Nav('API Reference', '/docs/api-reference'),
|
|
29
|
-
* ],
|
|
30
|
-
* }),
|
|
31
|
-
* ],
|
|
32
|
-
* seo: {
|
|
33
|
-
* titleTemplate: '%s | My Product',
|
|
34
|
-
* description: 'Official documentation for My Product',
|
|
35
|
-
* keywords: ['docs', 'api', 'reference'],
|
|
36
|
-
* },
|
|
37
|
-
* analytics: {
|
|
38
|
-
* provider: 'plausible',
|
|
39
|
-
* id: 'docs.example.com',
|
|
40
|
-
* },
|
|
41
|
-
* })
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export function Site(config) {
|
|
45
|
-
const site = {
|
|
46
|
-
type: 'site',
|
|
47
|
-
id: config.id,
|
|
48
|
-
name: config.name,
|
|
49
|
-
description: config.description,
|
|
50
|
-
version: config.version,
|
|
51
|
-
generator: config.generator || 'next',
|
|
52
|
-
structure: config.structure,
|
|
53
|
-
navigation: config.navigation,
|
|
54
|
-
seo: config.seo,
|
|
55
|
-
analytics: config.analytics,
|
|
56
|
-
deployment: config.deployment,
|
|
57
|
-
metadata: config.metadata,
|
|
58
|
-
tags: config.tags,
|
|
59
|
-
status: config.status || 'active',
|
|
60
|
-
};
|
|
61
|
-
return registerProduct(site);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Helper to create a navigation item
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* ```ts
|
|
68
|
-
* const nav = Nav('Documentation', '/docs', {
|
|
69
|
-
* icon: 'book',
|
|
70
|
-
* children: [
|
|
71
|
-
* Nav('Getting Started', '/docs/getting-started'),
|
|
72
|
-
* Nav('API Reference', '/docs/api'),
|
|
73
|
-
* ],
|
|
74
|
-
* })
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export function Nav(label, href, options) {
|
|
78
|
-
return {
|
|
79
|
-
label,
|
|
80
|
-
href,
|
|
81
|
-
...options,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Helper to configure SEO
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```ts
|
|
89
|
-
* const seo = SEO({
|
|
90
|
-
* titleTemplate: '%s | My Site',
|
|
91
|
-
* description: 'My awesome site',
|
|
92
|
-
* keywords: ['keyword1', 'keyword2'],
|
|
93
|
-
* ogImage: '/og-image.png',
|
|
94
|
-
* twitterCard: 'summary_large_image',
|
|
95
|
-
* })
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
export function SEO(config) {
|
|
99
|
-
return config;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Helper to configure analytics
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```ts
|
|
106
|
-
* const analytics = Analytics('google', 'G-XXXXXXXXXX')
|
|
107
|
-
* const analytics = Analytics('plausible', 'example.com')
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
export function Analytics(provider, id, config) {
|
|
111
|
-
return { provider, id, config };
|
|
112
|
-
}
|
package/src/tiers/define.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tier Definition
|
|
3
|
-
* Product tier primitives
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Tier level type
|
|
8
|
-
*/
|
|
9
|
-
export type TierLevel = number
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Tier definition
|
|
13
|
-
*/
|
|
14
|
-
export interface TierDefinition {
|
|
15
|
-
/** Unique identifier */
|
|
16
|
-
id: string
|
|
17
|
-
/** Human-readable name */
|
|
18
|
-
name: string
|
|
19
|
-
/** Tier level (higher = more features) */
|
|
20
|
-
level: TierLevel
|
|
21
|
-
/** Description */
|
|
22
|
-
description?: string
|
|
23
|
-
/** Custom pricing flag */
|
|
24
|
-
customPricing?: boolean
|
|
25
|
-
/** Feature limits */
|
|
26
|
-
limits?: Record<string, number | string>
|
|
27
|
-
/** Included features */
|
|
28
|
-
features?: string[]
|
|
29
|
-
/** Metadata */
|
|
30
|
-
metadata?: Record<string, unknown>
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Create a tier definition
|
|
35
|
-
*/
|
|
36
|
-
export function Tier(config: TierDefinition): TierDefinition {
|
|
37
|
-
return {
|
|
38
|
-
id: config.id,
|
|
39
|
-
name: config.name,
|
|
40
|
-
level: config.level,
|
|
41
|
-
description: config.description,
|
|
42
|
-
customPricing: config.customPricing,
|
|
43
|
-
limits: config.limits,
|
|
44
|
-
features: config.features,
|
|
45
|
-
metadata: config.metadata,
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Create and validate a tier definition
|
|
51
|
-
*/
|
|
52
|
-
export function defineTier(config: TierDefinition): TierDefinition {
|
|
53
|
-
if (!config.id || config.id.trim() === '') {
|
|
54
|
-
throw new Error('Tier ID is required')
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (config.level < 0) {
|
|
58
|
-
throw new Error('Tier level must be non-negative')
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return Tier(config)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Tier registry interface
|
|
66
|
-
*/
|
|
67
|
-
export interface TierRegistry {
|
|
68
|
-
/** Register a tier */
|
|
69
|
-
register(tier: TierDefinition): void
|
|
70
|
-
/** Get a tier by ID */
|
|
71
|
-
get(id: string): TierDefinition | undefined
|
|
72
|
-
/** List all tiers */
|
|
73
|
-
list(): TierDefinition[]
|
|
74
|
-
/** List tiers sorted by level */
|
|
75
|
-
listSorted(): TierDefinition[]
|
|
76
|
-
/** Compare two tiers */
|
|
77
|
-
compare(tierA: string, tierB: string): number
|
|
78
|
-
/** Check if tier has access to another tier's features */
|
|
79
|
-
hasAccessTo(currentTier: string, requiredTier: string): boolean
|
|
80
|
-
/** Get upgrade path from current tier */
|
|
81
|
-
getUpgradePath(currentTier: string): string[]
|
|
82
|
-
/** Clear registry */
|
|
83
|
-
clear(): void
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Create a tier registry
|
|
88
|
-
*/
|
|
89
|
-
export function createTierRegistry(): TierRegistry {
|
|
90
|
-
const tiers = new Map<string, TierDefinition>()
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
register(tier: TierDefinition): void {
|
|
94
|
-
tiers.set(tier.id, tier)
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
get(id: string): TierDefinition | undefined {
|
|
98
|
-
return tiers.get(id)
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
list(): TierDefinition[] {
|
|
102
|
-
return Array.from(tiers.values())
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
listSorted(): TierDefinition[] {
|
|
106
|
-
return Array.from(tiers.values()).sort((a, b) => a.level - b.level)
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
compare(tierA: string, tierB: string): number {
|
|
110
|
-
const a = tiers.get(tierA)
|
|
111
|
-
const b = tiers.get(tierB)
|
|
112
|
-
if (!a || !b) return 0
|
|
113
|
-
return a.level - b.level
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
hasAccessTo(currentTier: string, requiredTier: string): boolean {
|
|
117
|
-
const current = tiers.get(currentTier)
|
|
118
|
-
const required = tiers.get(requiredTier)
|
|
119
|
-
if (!current || !required) return false
|
|
120
|
-
return current.level >= required.level
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
getUpgradePath(currentTier: string): string[] {
|
|
124
|
-
const current = tiers.get(currentTier)
|
|
125
|
-
if (!current) return []
|
|
126
|
-
|
|
127
|
-
return Array.from(tiers.values())
|
|
128
|
-
.filter((t) => t.level > current.level)
|
|
129
|
-
.sort((a, b) => a.level - b.level)
|
|
130
|
-
.map((t) => t.id)
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
clear(): void {
|
|
134
|
-
tiers.clear()
|
|
135
|
-
},
|
|
136
|
-
}
|
|
137
|
-
}
|