@autumnsgrove/groveengine 0.4.12 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/components/OnboardingChecklist.svelte +118 -0
- package/dist/components/OnboardingChecklist.svelte.d.ts +14 -0
- package/dist/components/quota/QuotaWarning.svelte +125 -0
- package/dist/components/quota/QuotaWarning.svelte.d.ts +16 -0
- package/dist/components/quota/QuotaWidget.svelte +120 -0
- package/dist/components/quota/QuotaWidget.svelte.d.ts +15 -0
- package/dist/components/quota/UpgradePrompt.svelte +288 -0
- package/dist/components/quota/UpgradePrompt.svelte.d.ts +13 -0
- package/dist/components/quota/index.d.ts +8 -0
- package/dist/components/quota/index.js +8 -0
- package/dist/groveauth/client.d.ts +143 -0
- package/dist/groveauth/client.js +502 -0
- package/dist/groveauth/colors.d.ts +35 -0
- package/dist/groveauth/colors.js +91 -0
- package/dist/groveauth/index.d.ts +34 -0
- package/dist/groveauth/index.js +35 -0
- package/dist/groveauth/limits.d.ts +70 -0
- package/dist/groveauth/limits.js +202 -0
- package/dist/groveauth/rate-limit.d.ts +95 -0
- package/dist/groveauth/rate-limit.js +172 -0
- package/dist/groveauth/types.d.ts +139 -0
- package/dist/groveauth/types.js +61 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/payments/types.d.ts +7 -2
- package/dist/server/services/__mocks__/cloudflare.d.ts +54 -0
- package/dist/server/services/__mocks__/cloudflare.js +470 -0
- package/dist/server/services/cache.d.ts +170 -0
- package/dist/server/services/cache.js +335 -0
- package/dist/server/services/database.d.ts +236 -0
- package/dist/server/services/database.js +450 -0
- package/dist/server/services/index.d.ts +34 -0
- package/dist/server/services/index.js +77 -0
- package/dist/server/services/storage.d.ts +221 -0
- package/dist/server/services/storage.js +485 -0
- package/package.json +11 -1
- package/static/fonts/Calistoga-Regular.ttf +1438 -0
- package/static/fonts/Caveat-Regular.ttf +0 -0
- package/static/fonts/EBGaramond-Regular.ttf +0 -0
- package/static/fonts/Fraunces-Regular.ttf +0 -0
- package/static/fonts/InstrumentSans-Regular.ttf +0 -0
- package/static/fonts/Lora-Regular.ttf +0 -0
- package/static/fonts/Luciole-Regular.ttf +1438 -0
- package/static/fonts/Manrope-Regular.ttf +0 -0
- package/static/fonts/Merriweather-Regular.ttf +1439 -0
- package/static/fonts/Nunito-Regular.ttf +0 -0
- package/static/fonts/PlusJakartaSans-Regular.ttf +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GroveAuth Client Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for integrating with GroveAuth service.
|
|
5
|
+
*/
|
|
6
|
+
export interface GroveAuthConfig {
|
|
7
|
+
/** Client ID registered with GroveAuth */
|
|
8
|
+
clientId: string;
|
|
9
|
+
/** Client secret for token exchange (keep secure!) */
|
|
10
|
+
clientSecret: string;
|
|
11
|
+
/** OAuth callback URL for this application */
|
|
12
|
+
redirectUri: string;
|
|
13
|
+
/** GroveAuth base URL (defaults to https://auth.grove.place) */
|
|
14
|
+
authBaseUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface TokenResponse {
|
|
17
|
+
access_token: string;
|
|
18
|
+
token_type: "Bearer";
|
|
19
|
+
expires_in: number;
|
|
20
|
+
refresh_token: string;
|
|
21
|
+
scope: string;
|
|
22
|
+
}
|
|
23
|
+
export interface TokenInfo {
|
|
24
|
+
active: boolean;
|
|
25
|
+
sub?: string;
|
|
26
|
+
email?: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
exp?: number;
|
|
29
|
+
iat?: number;
|
|
30
|
+
client_id?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface UserInfo {
|
|
33
|
+
sub: string;
|
|
34
|
+
email: string;
|
|
35
|
+
name: string | null;
|
|
36
|
+
picture: string | null;
|
|
37
|
+
provider: "google" | "github" | "magic_code";
|
|
38
|
+
}
|
|
39
|
+
export interface LoginUrlResult {
|
|
40
|
+
url: string;
|
|
41
|
+
state: string;
|
|
42
|
+
codeVerifier: string;
|
|
43
|
+
}
|
|
44
|
+
export type SubscriptionTier = "seedling" | "sapling" | "oak" | "evergreen";
|
|
45
|
+
export interface UserSubscription {
|
|
46
|
+
id: string;
|
|
47
|
+
user_id: string;
|
|
48
|
+
tier: SubscriptionTier;
|
|
49
|
+
post_limit: number | null;
|
|
50
|
+
post_count: number;
|
|
51
|
+
grace_period_start: string | null;
|
|
52
|
+
grace_period_days: number;
|
|
53
|
+
stripe_customer_id: string | null;
|
|
54
|
+
stripe_subscription_id: string | null;
|
|
55
|
+
billing_period_start: string | null;
|
|
56
|
+
billing_period_end: string | null;
|
|
57
|
+
custom_domain: string | null;
|
|
58
|
+
custom_domain_verified: number;
|
|
59
|
+
created_at: string;
|
|
60
|
+
updated_at: string;
|
|
61
|
+
}
|
|
62
|
+
export interface SubscriptionStatus {
|
|
63
|
+
tier: SubscriptionTier;
|
|
64
|
+
post_count: number;
|
|
65
|
+
post_limit: number | null;
|
|
66
|
+
posts_remaining: number | null;
|
|
67
|
+
percentage_used: number | null;
|
|
68
|
+
is_at_limit: boolean;
|
|
69
|
+
is_in_grace_period: boolean;
|
|
70
|
+
grace_period_days_remaining: number | null;
|
|
71
|
+
can_create_post: boolean;
|
|
72
|
+
upgrade_required: boolean;
|
|
73
|
+
}
|
|
74
|
+
export interface SubscriptionResponse {
|
|
75
|
+
subscription: UserSubscription;
|
|
76
|
+
status: SubscriptionStatus;
|
|
77
|
+
}
|
|
78
|
+
export interface CanPostResponse {
|
|
79
|
+
allowed: boolean;
|
|
80
|
+
status: SubscriptionStatus;
|
|
81
|
+
subscription: UserSubscription;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Post limits per subscription tier.
|
|
85
|
+
*
|
|
86
|
+
* Business rationale:
|
|
87
|
+
* - Seedling (50 posts): Entry-level tier for curious newcomers testing the
|
|
88
|
+
* platform. Low commitment, creates upgrade path.
|
|
89
|
+
* - Sapling (250 posts): For hobbyists and regular bloggers who know they'll
|
|
90
|
+
* stick around. ~1 post/day for 8 months.
|
|
91
|
+
* - Oak (unlimited): For serious bloggers whose blog is part of their
|
|
92
|
+
* identity. Includes BYOD (bring your own domain) and full email.
|
|
93
|
+
* - Evergreen (unlimited): Full-service tier for professionals. Includes domain
|
|
94
|
+
* search, registration, and priority support.
|
|
95
|
+
*
|
|
96
|
+
* Grace period: When users hit their limit, they have 14 days to upgrade or
|
|
97
|
+
* delete posts before their account becomes read-only.
|
|
98
|
+
*
|
|
99
|
+
* @see docs/implementing-post-limits.md for full specification
|
|
100
|
+
*/
|
|
101
|
+
export declare const TIER_POST_LIMITS: Record<SubscriptionTier, number | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Human-readable tier names for UI display.
|
|
104
|
+
*/
|
|
105
|
+
export declare const TIER_NAMES: Record<SubscriptionTier, string>;
|
|
106
|
+
/**
|
|
107
|
+
* OAuth/API error response structure from GroveAuth.
|
|
108
|
+
* Used to parse error responses from the authentication API.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const response = await fetch('/token');
|
|
113
|
+
* if (!response.ok) {
|
|
114
|
+
* const error: AuthError = await response.json();
|
|
115
|
+
* console.error(error.error, error.error_description);
|
|
116
|
+
* }
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export interface AuthError {
|
|
120
|
+
/** OAuth error code (e.g., 'invalid_grant', 'access_denied') */
|
|
121
|
+
error: string;
|
|
122
|
+
/** Human-readable error description (OAuth standard) */
|
|
123
|
+
error_description?: string;
|
|
124
|
+
/** Alternative message field used by some endpoints */
|
|
125
|
+
message?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Client-side error class for GroveAuth operations.
|
|
129
|
+
* Thrown when authentication or subscription operations fail.
|
|
130
|
+
*/
|
|
131
|
+
export declare class GroveAuthError extends Error {
|
|
132
|
+
/** Error code (e.g., 'invalid_user_id', 'subscription_error') */
|
|
133
|
+
readonly code: string;
|
|
134
|
+
/** HTTP status code from the response */
|
|
135
|
+
readonly statusCode: number;
|
|
136
|
+
constructor(code: string, message: string, statusCode?: number);
|
|
137
|
+
/** Alias for statusCode for compatibility */
|
|
138
|
+
get status(): number;
|
|
139
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GroveAuth Client Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for integrating with GroveAuth service.
|
|
5
|
+
*/
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// POST LIMIT CONSTANTS
|
|
8
|
+
// =============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Post limits per subscription tier.
|
|
11
|
+
*
|
|
12
|
+
* Business rationale:
|
|
13
|
+
* - Seedling (50 posts): Entry-level tier for curious newcomers testing the
|
|
14
|
+
* platform. Low commitment, creates upgrade path.
|
|
15
|
+
* - Sapling (250 posts): For hobbyists and regular bloggers who know they'll
|
|
16
|
+
* stick around. ~1 post/day for 8 months.
|
|
17
|
+
* - Oak (unlimited): For serious bloggers whose blog is part of their
|
|
18
|
+
* identity. Includes BYOD (bring your own domain) and full email.
|
|
19
|
+
* - Evergreen (unlimited): Full-service tier for professionals. Includes domain
|
|
20
|
+
* search, registration, and priority support.
|
|
21
|
+
*
|
|
22
|
+
* Grace period: When users hit their limit, they have 14 days to upgrade or
|
|
23
|
+
* delete posts before their account becomes read-only.
|
|
24
|
+
*
|
|
25
|
+
* @see docs/implementing-post-limits.md for full specification
|
|
26
|
+
*/
|
|
27
|
+
export const TIER_POST_LIMITS = {
|
|
28
|
+
seedling: 50, // For curious newcomers trying blogging
|
|
29
|
+
sapling: 250, // For hobbyists and regular bloggers
|
|
30
|
+
oak: null, // Unlimited for serious bloggers
|
|
31
|
+
evergreen: null, // Unlimited for professionals
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Human-readable tier names for UI display.
|
|
35
|
+
*/
|
|
36
|
+
export const TIER_NAMES = {
|
|
37
|
+
seedling: "Seedling",
|
|
38
|
+
sapling: "Sapling",
|
|
39
|
+
oak: "Oak",
|
|
40
|
+
evergreen: "Evergreen",
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Client-side error class for GroveAuth operations.
|
|
44
|
+
* Thrown when authentication or subscription operations fail.
|
|
45
|
+
*/
|
|
46
|
+
export class GroveAuthError extends Error {
|
|
47
|
+
/** Error code (e.g., 'invalid_user_id', 'subscription_error') */
|
|
48
|
+
code;
|
|
49
|
+
/** HTTP status code from the response */
|
|
50
|
+
statusCode;
|
|
51
|
+
constructor(code, message, statusCode = 400) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = "GroveAuthError";
|
|
54
|
+
this.code = code;
|
|
55
|
+
this.statusCode = statusCode;
|
|
56
|
+
}
|
|
57
|
+
/** Alias for statusCode for compatibility */
|
|
58
|
+
get status() {
|
|
59
|
+
return this.statusCode;
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ export { default as MobileTOC } from './components/custom/MobileTOC.svelte';
|
|
|
6
6
|
export { default as CollapsibleSection } from './components/custom/CollapsibleSection.svelte';
|
|
7
7
|
export { default as MarkdownEditor } from './components/admin/MarkdownEditor.svelte';
|
|
8
8
|
export { default as GutterManager } from './components/admin/GutterManager.svelte';
|
|
9
|
+
export { QuotaWidget, QuotaWarning, UpgradePrompt } from './components/quota/index';
|
|
9
10
|
export { default as ImageGallery } from './ui/components/gallery/ImageGallery.svelte';
|
|
10
11
|
export { default as Lightbox } from './ui/components/gallery/Lightbox.svelte';
|
|
11
12
|
export { default as LightboxCaption } from './ui/components/gallery/LightboxCaption.svelte';
|
|
12
13
|
export { default as ZoomableImage } from './ui/components/gallery/ZoomableImage.svelte';
|
|
13
14
|
export * from './ui/index';
|
|
14
15
|
export { cn } from './utils/cn';
|
|
16
|
+
export * from './groveauth/index';
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export { default as CollapsibleSection } from './components/custom/CollapsibleSe
|
|
|
9
9
|
// Admin components
|
|
10
10
|
export { default as MarkdownEditor } from './components/admin/MarkdownEditor.svelte';
|
|
11
11
|
export { default as GutterManager } from './components/admin/GutterManager.svelte';
|
|
12
|
+
// Quota components
|
|
13
|
+
export { QuotaWidget, QuotaWarning, UpgradePrompt } from './components/quota/index';
|
|
12
14
|
// Gallery components (from UI module)
|
|
13
15
|
export { default as ImageGallery } from './ui/components/gallery/ImageGallery.svelte';
|
|
14
16
|
export { default as Lightbox } from './ui/components/gallery/Lightbox.svelte';
|
|
@@ -18,3 +20,5 @@ export { default as ZoomableImage } from './ui/components/gallery/ZoomableImage.
|
|
|
18
20
|
export * from './ui/index';
|
|
19
21
|
// Utilities
|
|
20
22
|
export { cn } from './utils/cn';
|
|
23
|
+
// GroveAuth client (re-export for convenience)
|
|
24
|
+
export * from './groveauth/index';
|
package/dist/payments/types.d.ts
CHANGED
|
@@ -227,21 +227,26 @@ export interface ConnectOnboardingResult {
|
|
|
227
227
|
onboardingUrl: string;
|
|
228
228
|
expiresAt?: Date;
|
|
229
229
|
}
|
|
230
|
-
export type PlanTier = '
|
|
230
|
+
export type PlanTier = 'seedling' | 'sapling' | 'oak' | 'evergreen';
|
|
231
231
|
export interface PlatformPlan {
|
|
232
232
|
tier: PlanTier;
|
|
233
233
|
name: string;
|
|
234
234
|
price: Money;
|
|
235
|
+
yearlyPrice?: Money;
|
|
235
236
|
interval: BillingInterval;
|
|
236
237
|
features: string[];
|
|
237
238
|
limits: {
|
|
238
239
|
posts?: number;
|
|
239
240
|
storage?: number;
|
|
240
241
|
customDomain?: boolean;
|
|
241
|
-
|
|
242
|
+
byod?: boolean;
|
|
243
|
+
email?: 'none' | 'forward' | 'full';
|
|
244
|
+
analytics?: 'basic' | 'full';
|
|
245
|
+
supportHours?: number;
|
|
242
246
|
shop?: boolean;
|
|
243
247
|
};
|
|
244
248
|
providerPriceId?: string;
|
|
249
|
+
yearlyPriceId?: string;
|
|
245
250
|
}
|
|
246
251
|
export interface TenantBilling {
|
|
247
252
|
tenantId: string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementations for Cloudflare services (D1, KV, R2)
|
|
3
|
+
* Used for testing the service abstraction layer
|
|
4
|
+
*/
|
|
5
|
+
interface MockRow {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a mock D1 database with in-memory storage
|
|
10
|
+
*/
|
|
11
|
+
export declare function createMockD1(): D1Database & {
|
|
12
|
+
_tables: Map<string, MockRow[]>;
|
|
13
|
+
};
|
|
14
|
+
interface KVEntry {
|
|
15
|
+
value: string;
|
|
16
|
+
expiresAt?: number;
|
|
17
|
+
metadata?: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a mock KV namespace with in-memory storage
|
|
21
|
+
*/
|
|
22
|
+
export declare function createMockKV(): KVNamespace & {
|
|
23
|
+
_store: Map<string, KVEntry>;
|
|
24
|
+
};
|
|
25
|
+
interface R2Entry {
|
|
26
|
+
body: ArrayBuffer;
|
|
27
|
+
httpMetadata?: {
|
|
28
|
+
contentType?: string;
|
|
29
|
+
cacheControl?: string;
|
|
30
|
+
};
|
|
31
|
+
customMetadata?: Record<string, string>;
|
|
32
|
+
etag: string;
|
|
33
|
+
uploaded: Date;
|
|
34
|
+
size: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates a mock R2 bucket with in-memory storage
|
|
38
|
+
*/
|
|
39
|
+
export declare function createMockR2(): R2Bucket & {
|
|
40
|
+
_objects: Map<string, R2Entry>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Seed a mock D1 database with initial data
|
|
44
|
+
*/
|
|
45
|
+
export declare function seedMockD1(db: ReturnType<typeof createMockD1>, tableName: string, rows: MockRow[]): void;
|
|
46
|
+
/**
|
|
47
|
+
* Clear all data from a mock D1 database
|
|
48
|
+
*/
|
|
49
|
+
export declare function clearMockD1(db: ReturnType<typeof createMockD1>): void;
|
|
50
|
+
/**
|
|
51
|
+
* Advance time for KV expiration testing
|
|
52
|
+
*/
|
|
53
|
+
export declare function advanceKVTime(kv: ReturnType<typeof createMockKV>, ms: number): void;
|
|
54
|
+
export {};
|