@beeblock/svelar 0.5.0 → 0.6.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/README.md +25 -7
- package/dist/cli/bin.js +230 -702
- package/dist/cli/commands/NewCommandTemplates.d.ts +2 -10
- package/dist/cli/commands/UpdateCommand.d.ts +3 -0
- package/dist/cli/index.js +48 -48
- package/dist/plugins/PluginInstaller.js +1 -1
- package/dist/plugins/PluginRegistry.js +1 -1
- package/package.json +5 -13
- package/dist/stripe/Invoice.d.ts +0 -44
- package/dist/stripe/StripeService.d.ts +0 -52
- package/dist/stripe/StripeWebhookHandler.d.ts +0 -14
- package/dist/stripe/Subscription.d.ts +0 -40
- package/dist/stripe/SubscriptionManager.d.ts +0 -39
- package/dist/stripe/SubscriptionPlan.d.ts +0 -41
- package/dist/stripe/SyncStripeCustomerJob.d.ts +0 -11
- package/dist/stripe/index.d.ts +0 -22
- package/dist/stripe/index.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var w=(u=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(s,e)=>(typeof require<"u"?require:s)[e]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+u+'" is not supported')});function d(u,s){let e=Symbol.for(u),n=globalThis;return n[e]||(n[e]=s()),n[e]}var P=class{plugins=new Map;enabledPlugins=new Set;async discover(){let{join:s}=await import("path"),{existsSync:e,readdirSync:n}=await import("fs"),{readFile:c}=await import("fs/promises"),o=[],i=s(process.cwd(),"node_modules");if(!e(i))return o;let g=async(r,m="")=>{if(e(r))try{let p=n(r,{withFileTypes:!0});for(let a of p){if(!a.isDirectory()||a.name.startsWith("."))continue;if(a.name.startsWith("@")){let h=s(r,a.name);await g(h,a.name+"/");continue}let t=m+a.name,l=a.name.startsWith("svelar-");if(!l)continue;let b=s(r,a.name,"package.json");if(e(b))try{let h=await c(b,"utf-8"),f=JSON.parse(h),k=f.keywords?.includes("svelar-plugin");if(!l&&!k)continue;let y={name:f.name||t,version:f.version||"0.0.0",description:f.description||"",packageName:t,installed:!0,enabled:!1,hasConfig:!!f.svelar?.config,hasMigrations:!!f.svelar?.migrations};o.push(y),this.plugins.set(y.name,y)}catch{}}}catch{}};return await g(i),o}enable(s){let e=this.plugins.get(s);if(!e)throw new Error(`Plugin "${s}" not found in registry.`);this.enabledPlugins.add(s),e.enabled=!0}disable(s){this.enabledPlugins.delete(s);let e=this.plugins.get(s);e&&(e.enabled=!1)}isEnabled(s){return this.enabledPlugins.has(s)}list(){return[...this.plugins.values()]}listEnabled(){return[...this.plugins.values()].filter(s=>this.enabledPlugins.has(s.name))}get(s){return this.plugins.get(s)}register(s){this.plugins.set(s.name,s)}},v=d("svelar.pluginRegistry",()=>new P);var M=class{async publish(s,e){let{mkdir:n,copyFile:c}=await import("fs/promises"),{join:o,dirname:i}=await import("path"),{existsSync:g}=await import("fs"),r={configs:[],migrations:[],assets:[]},m=s.publishables?.()||{};for(let[p,a]of Object.entries(m))for(let t of a){if(e?.only&&t.type!==e.only)continue;let l=o(process.cwd(),t.dest),b=i(l);if(!(g(l)&&!e?.force))try{await n(b,{recursive:!0}),await c(t.source,l),t.type==="config"?r.configs.push(l):t.type==="migration"?r.migrations.push(l):t.type==="asset"&&r.assets.push(l)}catch(h){console.warn(`Failed to publish ${t.source} to ${l}:`,h)}}return r}async preview(s){let e={configs:[],migrations:[],assets:[]},n=s.publishables?.()||{};for(let[c,o]of Object.entries(n))for(let i of o){let g=w("path").join(process.cwd(),i.dest);i.type==="config"?e.configs.push(g):i.type==="migration"?e.migrations.push(g):i.type==="asset"&&e.assets.push(g)}return e}},R=d("svelar.pluginPublisher",()=>new M);var x=class{async install(s,e){let{spawn:n}=await import("child_process"),{promisify:c}=await import("util"),{join:o}=await import("path"),{readFile:i}=await import("fs/promises"),{existsSync:g}=await import("fs");try{await this.runNpmInstall(s);let r=v,m=await r.discover(),p;for(let t of m)if(t.packageName===s||t.name===s){p=t;break}if(!p)return{success:!1,pluginName:s,version:"0.0.0",published:null,error:`Plugin not found after installation. Make sure ${s} is a valid Svelar plugin.`};r.enable(p.name);let a=null;if(e?.publish!==!1)try{let t=await this.loadPluginClass(p.packageName);t&&(a=await R.publish(new t))}catch(t){console.warn("Failed to publish plugin assets:",t)}return{success:!0,pluginName:p.name,version:p.version,published:a}}catch(r){return{success:!1,pluginName:s,version:"0.0.0",published:null,error:r?.message??String(r)}}}async uninstall(s){try{let e=v,n=e.get(s);return n?(e.disable(s),await this.runNpmUninstall(n.packageName),!0):!1}catch(e){return console.error("Failed to uninstall plugin:",e),!1}}async runNpmInstall(s){return new Promise((e,n)=>{let{spawn:c}=w("child_process"),o=c("npm",["install",s],{cwd:process.cwd(),stdio:"inherit"});o.on("close",i=>{i===0?e():n(new Error(`npm install exited with code ${i}`))}),o.on("error",n)})}async runNpmUninstall(s){return new Promise((e,n)=>{let{spawn:c}=w("child_process"),o=c("npm",["uninstall",s],{cwd:process.cwd(),stdio:"inherit"});o.on("close",i=>{i===0?e():n(new Error(`npm uninstall exited with code ${i}`))}),o.on("error",n)})}async loadPluginClass(s){try{let e=await import(`${s}/plugin`);return e.default||Object.values(e)[0]}catch{try{let e=await import(s);return e.default||Object.values(e)[0]}catch{return null}}}},C=d("svelar.pluginInstaller",()=>new x);export{C as PluginInstaller};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function m(c,n){let e=Symbol.for(c),s=globalThis;return s[e]||(s[e]=n()),s[e]}var g=class{plugins=new Map;enabledPlugins=new Set;async discover(){let{join:n}=await import("path"),{existsSync:e,readdirSync:s}=await import("fs"),{readFile:b}=await import("fs/promises"),o=[],u=n(process.cwd(),"node_modules");if(!e(u))return o;let d=async(a,P="")=>{if(e(a))try{let v=s(a,{withFileTypes:!0});for(let t of v){if(!t.isDirectory()||t.name.startsWith("."))continue;if(t.name.startsWith("@")){let r=n(a,t.name);await d(r,t.name+"/");continue}let p=P+t.name,h=t.name.startsWith("svelar-");if(!h)continue;let f=n(a,t.name,"package.json");if(e(f))try{let r=await b(f,"utf-8"),i=JSON.parse(r),y=i.keywords?.includes("svelar-plugin");if(!h&&!y)continue;let l={name:i.name||p,version:i.version||"0.0.0",description:i.description||"",packageName:p,installed:!0,enabled:!1,hasConfig:!!i.svelar?.config,hasMigrations:!!i.svelar?.migrations};o.push(l),this.plugins.set(l.name,l)}catch{}}}catch{}};return await d(u),o}enable(n){let e=this.plugins.get(n);if(!e)throw new Error(`Plugin "${n}" not found in registry.`);this.enabledPlugins.add(n),e.enabled=!0}disable(n){this.enabledPlugins.delete(n);let e=this.plugins.get(n);e&&(e.enabled=!1)}isEnabled(n){return this.enabledPlugins.has(n)}list(){return[...this.plugins.values()]}listEnabled(){return[...this.plugins.values()].filter(n=>this.enabledPlugins.has(n.name))}get(n){return this.plugins.get(n)}register(n){this.plugins.set(n.name,n)}},k=m("svelar.pluginRegistry",()=>new g);export{k as PluginRegistry};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beeblock/svelar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Laravel-inspired framework on top of SvelteKit 2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -242,10 +242,6 @@
|
|
|
242
242
|
"types": "./dist/excel/index.d.ts",
|
|
243
243
|
"import": "./dist/excel/index.js"
|
|
244
244
|
},
|
|
245
|
-
"./stripe": {
|
|
246
|
-
"types": "./dist/stripe/index.d.ts",
|
|
247
|
-
"import": "./dist/stripe/index.js"
|
|
248
|
-
},
|
|
249
245
|
"./testing": {
|
|
250
246
|
"types": "./dist/testing/index.d.ts",
|
|
251
247
|
"import": "./dist/testing/index.js"
|
|
@@ -273,7 +269,7 @@
|
|
|
273
269
|
"@vitest/coverage-v8": "^2.1.9",
|
|
274
270
|
"better-sqlite3": "^11.0.0",
|
|
275
271
|
"exceljs": "^4.4.0",
|
|
276
|
-
|
|
272
|
+
|
|
277
273
|
"sveltekit-superforms": "^2.30.1",
|
|
278
274
|
"tsup": "^8.3.0",
|
|
279
275
|
"typescript": "^5.7.0",
|
|
@@ -292,7 +288,7 @@
|
|
|
292
288
|
"pdfkit": ">=0.18.0",
|
|
293
289
|
"postgres": "*",
|
|
294
290
|
"pusher-js": ">=8.0.0",
|
|
295
|
-
|
|
291
|
+
|
|
296
292
|
"sveltekit-superforms": ">=2.0.0",
|
|
297
293
|
"vitest": ">=1.0.0"
|
|
298
294
|
},
|
|
@@ -333,9 +329,7 @@
|
|
|
333
329
|
"meilisearch": {
|
|
334
330
|
"optional": true
|
|
335
331
|
},
|
|
336
|
-
|
|
337
|
-
"optional": true
|
|
338
|
-
},
|
|
332
|
+
|
|
339
333
|
"vitest": {
|
|
340
334
|
"optional": true
|
|
341
335
|
}
|
|
@@ -353,9 +347,7 @@
|
|
|
353
347
|
"cache",
|
|
354
348
|
"queue",
|
|
355
349
|
"mail",
|
|
356
|
-
"
|
|
357
|
-
"billing",
|
|
358
|
-
"subscriptions"
|
|
350
|
+
"billing"
|
|
359
351
|
],
|
|
360
352
|
"license": "MIT",
|
|
361
353
|
"author": "Raoni <alephtus@gmail.com>",
|
package/dist/stripe/Invoice.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
export type InvoiceStatus = 'draft' | 'open' | 'paid' | 'void' | 'uncollectible';
|
|
2
|
-
export interface InvoiceAttributes {
|
|
3
|
-
id: number;
|
|
4
|
-
userId: number;
|
|
5
|
-
subscriptionId: number | null;
|
|
6
|
-
stripeInvoiceId: string;
|
|
7
|
-
amountDue: number;
|
|
8
|
-
amountPaid: number;
|
|
9
|
-
currency: string;
|
|
10
|
-
status: InvoiceStatus;
|
|
11
|
-
paidAt: Date | null;
|
|
12
|
-
dueDate: Date | null;
|
|
13
|
-
invoicePdf: string | null;
|
|
14
|
-
createdAt: Date;
|
|
15
|
-
updatedAt?: Date;
|
|
16
|
-
}
|
|
17
|
-
export declare class Invoice implements InvoiceAttributes {
|
|
18
|
-
id: number;
|
|
19
|
-
userId: number;
|
|
20
|
-
subscriptionId: number | null;
|
|
21
|
-
stripeInvoiceId: string;
|
|
22
|
-
amountDue: number;
|
|
23
|
-
amountPaid: number;
|
|
24
|
-
currency: string;
|
|
25
|
-
status: InvoiceStatus;
|
|
26
|
-
paidAt: Date | null;
|
|
27
|
-
dueDate: Date | null;
|
|
28
|
-
invoicePdf: string | null;
|
|
29
|
-
createdAt: Date;
|
|
30
|
-
updatedAt?: Date;
|
|
31
|
-
constructor(attributes: InvoiceAttributes);
|
|
32
|
-
isPaid(): boolean;
|
|
33
|
-
isOpen(): boolean;
|
|
34
|
-
isDraft(): boolean;
|
|
35
|
-
isVoid(): boolean;
|
|
36
|
-
isUncollectible(): boolean;
|
|
37
|
-
isOverdue(): boolean;
|
|
38
|
-
outstandingAmount(): number;
|
|
39
|
-
formattedAmountDue(): string;
|
|
40
|
-
formattedAmountPaid(): string;
|
|
41
|
-
formattedOutstanding(): string;
|
|
42
|
-
daysUntilDue(): number | null;
|
|
43
|
-
private formatCurrency;
|
|
44
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type Stripe from 'stripe';
|
|
2
|
-
export interface StripeConfig {
|
|
3
|
-
secretKey: string;
|
|
4
|
-
publishableKey: string;
|
|
5
|
-
webhookSecret: string;
|
|
6
|
-
currency?: string;
|
|
7
|
-
trialDays?: number;
|
|
8
|
-
portalReturnUrl?: string;
|
|
9
|
-
checkoutSuccessUrl?: string;
|
|
10
|
-
checkoutCancelUrl?: string;
|
|
11
|
-
}
|
|
12
|
-
export declare class StripeService {
|
|
13
|
-
private stripe;
|
|
14
|
-
private config;
|
|
15
|
-
configure(config: StripeConfig): void;
|
|
16
|
-
getConfig(): StripeConfig;
|
|
17
|
-
getClient(): Promise<Stripe>;
|
|
18
|
-
createCustomer(user: {
|
|
19
|
-
id: number | string;
|
|
20
|
-
name?: string;
|
|
21
|
-
email?: string;
|
|
22
|
-
}): Promise<Stripe.Customer>;
|
|
23
|
-
updateCustomer(customerId: string, data: Stripe.CustomerUpdateParams): Promise<Stripe.Customer>;
|
|
24
|
-
deleteCustomer(customerId: string): Promise<void>;
|
|
25
|
-
getCustomer(customerId: string): Promise<Stripe.Customer>;
|
|
26
|
-
createSubscription(customerId: string, priceId: string, opts?: {
|
|
27
|
-
trialDays?: number;
|
|
28
|
-
metadata?: Record<string, string>;
|
|
29
|
-
collectionMethod?: 'send_invoice' | 'charge_automatically';
|
|
30
|
-
daysUntilDue?: number;
|
|
31
|
-
}): Promise<Stripe.Subscription>;
|
|
32
|
-
getSubscription(subscriptionId: string): Promise<Stripe.Subscription>;
|
|
33
|
-
cancelSubscription(subscriptionId: string, immediately?: boolean): Promise<Stripe.Subscription>;
|
|
34
|
-
resumeSubscription(subscriptionId: string): Promise<Stripe.Subscription>;
|
|
35
|
-
updateSubscription(subscriptionId: string, newPriceId: string, opts?: {
|
|
36
|
-
proration?: 'create_prorations' | 'none';
|
|
37
|
-
metadata?: Record<string, string>;
|
|
38
|
-
}): Promise<Stripe.Subscription>;
|
|
39
|
-
getInvoices(customerId: string, limit?: number): Promise<Stripe.Invoice[]>;
|
|
40
|
-
getInvoice(invoiceId: string): Promise<Stripe.Invoice>;
|
|
41
|
-
createCheckoutSession(customerId: string, priceId: string, successUrl: string, cancelUrl: string, opts?: {
|
|
42
|
-
trialDays?: number;
|
|
43
|
-
metadata?: Record<string, string>;
|
|
44
|
-
}): Promise<Stripe.Checkout.Session>;
|
|
45
|
-
createPortalSession(customerId: string, returnUrl: string): Promise<Stripe.BillingPortal.Session>;
|
|
46
|
-
constructWebhookEvent(body: string | Buffer, signature: string): Promise<Stripe.Event>;
|
|
47
|
-
listPrices(productId?: string, limit?: number): Promise<Stripe.Price[]>;
|
|
48
|
-
listProducts(limit?: number): Promise<Stripe.Product[]>;
|
|
49
|
-
refundInvoice(invoiceId: string): Promise<Stripe.Refund>;
|
|
50
|
-
getRefund(refundId: string): Promise<Stripe.Refund>;
|
|
51
|
-
listRefunds(chargeId: string): Promise<Stripe.Refund[]>;
|
|
52
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type Stripe from 'stripe';
|
|
2
|
-
export type WebhookEventType = 'customer.subscription.created' | 'customer.subscription.updated' | 'customer.subscription.deleted' | 'invoice.payment_succeeded' | 'invoice.payment_failed' | 'customer.created' | 'customer.updated' | 'customer.deleted' | 'checkout.session.completed' | 'invoice.created' | 'invoice.finalized' | 'charge.refunded' | string;
|
|
3
|
-
export type WebhookHandler = (event: Stripe.Event) => Promise<void>;
|
|
4
|
-
export declare class StripeWebhookHandler {
|
|
5
|
-
private handlers;
|
|
6
|
-
on(eventType: WebhookEventType, handler: WebhookHandler): this;
|
|
7
|
-
once(eventType: WebhookEventType, handler: WebhookHandler): this;
|
|
8
|
-
off(eventType: WebhookEventType, handler: WebhookHandler): void;
|
|
9
|
-
removeAllListeners(eventType?: WebhookEventType): void;
|
|
10
|
-
handle(event: Stripe.Event): Promise<void>;
|
|
11
|
-
getHandlers(eventType: WebhookEventType): WebhookHandler[];
|
|
12
|
-
getEventTypes(): WebhookEventType[];
|
|
13
|
-
hasHandlers(eventType: WebhookEventType): boolean;
|
|
14
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export type SubscriptionStatus = 'active' | 'past_due' | 'canceled' | 'trialing' | 'incomplete' | 'paused';
|
|
2
|
-
export interface SubscriptionAttributes {
|
|
3
|
-
id: number;
|
|
4
|
-
userId: number;
|
|
5
|
-
stripeSubscriptionId: string;
|
|
6
|
-
stripeCustomerId: string;
|
|
7
|
-
planId: number;
|
|
8
|
-
status: SubscriptionStatus;
|
|
9
|
-
currentPeriodStart: Date;
|
|
10
|
-
currentPeriodEnd: Date;
|
|
11
|
-
cancelAtPeriodEnd: boolean;
|
|
12
|
-
trialEndsAt: Date | null;
|
|
13
|
-
canceledAt: Date | null;
|
|
14
|
-
createdAt: Date;
|
|
15
|
-
updatedAt: Date;
|
|
16
|
-
}
|
|
17
|
-
export declare class Subscription implements SubscriptionAttributes {
|
|
18
|
-
id: number;
|
|
19
|
-
userId: number;
|
|
20
|
-
stripeSubscriptionId: string;
|
|
21
|
-
stripeCustomerId: string;
|
|
22
|
-
planId: number;
|
|
23
|
-
status: SubscriptionStatus;
|
|
24
|
-
currentPeriodStart: Date;
|
|
25
|
-
currentPeriodEnd: Date;
|
|
26
|
-
cancelAtPeriodEnd: boolean;
|
|
27
|
-
trialEndsAt: Date | null;
|
|
28
|
-
canceledAt: Date | null;
|
|
29
|
-
createdAt: Date;
|
|
30
|
-
updatedAt: Date;
|
|
31
|
-
constructor(attributes: SubscriptionAttributes);
|
|
32
|
-
isActive(): boolean;
|
|
33
|
-
isPastDue(): boolean;
|
|
34
|
-
isCanceled(): boolean;
|
|
35
|
-
isOnTrial(): boolean;
|
|
36
|
-
isOnGracePeriod(): boolean;
|
|
37
|
-
isIncomplete(): boolean;
|
|
38
|
-
isPaused(): boolean;
|
|
39
|
-
daysUntilEnd(): number;
|
|
40
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { StripeService } from './StripeService.js';
|
|
2
|
-
import type { Subscription } from './Subscription.js';
|
|
3
|
-
import type { SubscriptionPlan } from './SubscriptionPlan.js';
|
|
4
|
-
export interface SubscriptionManagerDependencies {
|
|
5
|
-
stripeService: StripeService;
|
|
6
|
-
subscriptionRepository?: {
|
|
7
|
-
findByUserId(userId: number): Promise<Subscription | null>;
|
|
8
|
-
findByStripeSubscriptionId(id: string): Promise<Subscription | null>;
|
|
9
|
-
create(data: any): Promise<Subscription>;
|
|
10
|
-
update(id: number, data: any): Promise<Subscription>;
|
|
11
|
-
delete(id: number): Promise<void>;
|
|
12
|
-
};
|
|
13
|
-
planRepository?: {
|
|
14
|
-
findById(id: number): Promise<SubscriptionPlan | null>;
|
|
15
|
-
findByStripePriceId(id: string): Promise<SubscriptionPlan | null>;
|
|
16
|
-
all(): Promise<SubscriptionPlan[]>;
|
|
17
|
-
};
|
|
18
|
-
userRepository?: {
|
|
19
|
-
findById(id: number): Promise<any>;
|
|
20
|
-
update(id: number, data: any): Promise<any>;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
export declare class SubscriptionManager {
|
|
24
|
-
private stripeService;
|
|
25
|
-
private deps;
|
|
26
|
-
constructor(deps: SubscriptionManagerDependencies);
|
|
27
|
-
subscribe(userId: number, planId: number, opts?: {
|
|
28
|
-
trialDays?: number;
|
|
29
|
-
metadata?: Record<string, string>;
|
|
30
|
-
}): Promise<Subscription>;
|
|
31
|
-
upgrade(userId: number, newPlanId: number): Promise<Subscription>;
|
|
32
|
-
downgrade(userId: number, newPlanId: number): Promise<Subscription>;
|
|
33
|
-
cancel(userId: number, immediately?: boolean): Promise<void>;
|
|
34
|
-
resume(userId: number): Promise<Subscription>;
|
|
35
|
-
isSubscribed(userId: number, planId?: number): Promise<boolean>;
|
|
36
|
-
onTrial(userId: number): Promise<boolean>;
|
|
37
|
-
hasFeature(userId: number, feature: string): Promise<boolean>;
|
|
38
|
-
syncFromStripe(userId: number): Promise<Subscription>;
|
|
39
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export type PlanInterval = 'month' | 'year';
|
|
2
|
-
export interface SubscriptionPlanAttributes {
|
|
3
|
-
id: number;
|
|
4
|
-
name: string;
|
|
5
|
-
stripePriceId: string;
|
|
6
|
-
stripeProductId: string;
|
|
7
|
-
price: number;
|
|
8
|
-
currency: string;
|
|
9
|
-
interval: PlanInterval;
|
|
10
|
-
intervalCount: number;
|
|
11
|
-
trialDays: number;
|
|
12
|
-
features: string[];
|
|
13
|
-
sortOrder: number;
|
|
14
|
-
active: boolean;
|
|
15
|
-
createdAt: Date;
|
|
16
|
-
updatedAt: Date;
|
|
17
|
-
}
|
|
18
|
-
export declare class SubscriptionPlan implements SubscriptionPlanAttributes {
|
|
19
|
-
id: number;
|
|
20
|
-
name: string;
|
|
21
|
-
stripePriceId: string;
|
|
22
|
-
stripeProductId: string;
|
|
23
|
-
price: number;
|
|
24
|
-
currency: string;
|
|
25
|
-
interval: PlanInterval;
|
|
26
|
-
intervalCount: number;
|
|
27
|
-
trialDays: number;
|
|
28
|
-
features: string[];
|
|
29
|
-
sortOrder: number;
|
|
30
|
-
active: boolean;
|
|
31
|
-
createdAt: Date;
|
|
32
|
-
updatedAt: Date;
|
|
33
|
-
constructor(attributes: SubscriptionPlanAttributes);
|
|
34
|
-
isActive(): boolean;
|
|
35
|
-
monthlyPrice(): number;
|
|
36
|
-
yearlyPrice(): number;
|
|
37
|
-
hasFeature(feature: string): boolean;
|
|
38
|
-
formattedPrice(): string;
|
|
39
|
-
intervalLabel(): string;
|
|
40
|
-
trialLabel(): string;
|
|
41
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { StripeService } from './StripeService.js';
|
|
2
|
-
export declare class SyncStripeCustomerJob {
|
|
3
|
-
userId: number;
|
|
4
|
-
email: string;
|
|
5
|
-
userName: string;
|
|
6
|
-
readonly name = "sync-stripe-customer";
|
|
7
|
-
constructor(userId: number, email: string, userName: string);
|
|
8
|
-
handle(stripeService: StripeService): Promise<void>;
|
|
9
|
-
serialize(): string;
|
|
10
|
-
static restore(data: any): SyncStripeCustomerJob;
|
|
11
|
-
}
|
package/dist/stripe/index.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { StripeService, type StripeConfig } from './StripeService.js';
|
|
2
|
-
import { StripeWebhookHandler } from './StripeWebhookHandler.js';
|
|
3
|
-
import { SubscriptionManager, type SubscriptionManagerDependencies } from './SubscriptionManager.js';
|
|
4
|
-
declare class StripeManager {
|
|
5
|
-
private stripeService;
|
|
6
|
-
private webhookHandler;
|
|
7
|
-
private subscriptionManager;
|
|
8
|
-
configure(config: StripeConfig): void;
|
|
9
|
-
service(): StripeService;
|
|
10
|
-
webhooks(): StripeWebhookHandler;
|
|
11
|
-
subscriptions(deps?: SubscriptionManagerDependencies): SubscriptionManager;
|
|
12
|
-
initSubscriptions(deps: Omit<SubscriptionManagerDependencies, 'stripeService'>): SubscriptionManager;
|
|
13
|
-
}
|
|
14
|
-
export declare const Stripe: StripeManager;
|
|
15
|
-
export { StripeManager };
|
|
16
|
-
export { StripeService, type StripeConfig } from './StripeService.js';
|
|
17
|
-
export { StripeWebhookHandler, type WebhookEventType, type WebhookHandler } from './StripeWebhookHandler.js';
|
|
18
|
-
export { SubscriptionManager, type SubscriptionManagerDependencies } from './SubscriptionManager.js';
|
|
19
|
-
export { Subscription, type SubscriptionAttributes, type SubscriptionStatus } from './Subscription.js';
|
|
20
|
-
export { SubscriptionPlan, type SubscriptionPlanAttributes, type PlanInterval } from './SubscriptionPlan.js';
|
|
21
|
-
export { Invoice, type InvoiceAttributes, type InvoiceStatus } from './Invoice.js';
|
|
22
|
-
export { SyncStripeCustomerJob } from './SyncStripeCustomerJob.js';
|
package/dist/stripe/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{randomBytes as D}from"crypto";function h(n,t){let e=Symbol.for(n),i=globalThis;return i[e]||(i[e]=t()),i[e]}var p=class{stripe=null;config=null;configure(t){this.config=t,this.stripe=null}getConfig(){if(!this.config)throw new Error("StripeService not configured. Call Stripe.configure() in app.ts first.");return this.config}async getClient(){if(!this.stripe){if(!this.config)throw new Error("StripeService not configured. Call Stripe.configure() in app.ts first.");let{default:t}=await import("stripe");this.stripe=new t(this.config.secretKey,{apiVersion:"2024-04-10"})}return this.stripe}async createCustomer(t){return(await this.getClient()).customers.create({email:t.email,name:t.name||void 0,metadata:{userId:String(t.id)}})}async updateCustomer(t,e){return(await this.getClient()).customers.update(t,e)}async deleteCustomer(t){await(await this.getClient()).customers.del(t)}async getCustomer(t){return await(await this.getClient()).customers.retrieve(t)}async createSubscription(t,e,i){let r=await this.getClient(),s={customer:t,items:[{price:e}],metadata:i?.metadata,collection_method:i?.collectionMethod||"charge_automatically"};return i?.trialDays&&(s.trial_period_days=i.trialDays),i?.daysUntilDue&&(s.days_until_due=i.daysUntilDue),r.subscriptions.create(s)}async getSubscription(t){return(await this.getClient()).subscriptions.retrieve(t)}async cancelSubscription(t,e=!1){let i=await this.getClient();return e?i.subscriptions.cancel(t):i.subscriptions.update(t,{cancel_at_period_end:!0})}async resumeSubscription(t){return(await this.getClient()).subscriptions.update(t,{cancel_at_period_end:!1})}async updateSubscription(t,e,i){let r=await this.getClient(),s=await r.subscriptions.retrieve(t);if(!s.items.data[0])throw new Error("Subscription has no items");return r.subscriptions.update(t,{items:[{id:s.items.data[0].id,price:e}],proration_behavior:i?.proration||"create_prorations",metadata:i?.metadata})}async getInvoices(t,e=10){return(await(await this.getClient()).invoices.list({customer:t,limit:e})).data}async getInvoice(t){return(await this.getClient()).invoices.retrieve(t)}async createCheckoutSession(t,e,i,r,s){let o=await this.getClient(),a={customer:t,payment_method_types:["card"],line_items:[{price:e,quantity:1}],mode:"subscription",success_url:i,cancel_url:r,metadata:s?.metadata};return s?.trialDays&&(a.subscription_data={trial_period_days:s.trialDays}),o.checkout.sessions.create(a)}async createPortalSession(t,e){return(await this.getClient()).billingPortal.sessions.create({customer:t,return_url:e})}async constructWebhookEvent(t,e){if(!this.config)throw new Error("StripeService not configured");return(await this.getClient()).webhooks.constructEvent(t,e,this.config.webhookSecret)}async listPrices(t,e=100){let i=await this.getClient(),r={limit:e,expand:["data.product"]};return t&&(r.product=t),(await i.prices.list(r)).data}async listProducts(t=100){return(await(await this.getClient()).products.list({limit:t})).data}async refundInvoice(t){let e=await this.getClient(),i=await e.invoices.retrieve(t),r=i.charge??i.payment_intent;if(!r)throw new Error("Invoice has no associated charge or payment intent");return e.refunds.create({charge:String(r)})}async getRefund(t){return(await this.getClient()).refunds.retrieve(t)}async listRefunds(t){return(await(await this.getClient()).refunds.list({charge:t})).data}};var d=class{handlers=new Map;on(t,e){return this.handlers.has(t)||this.handlers.set(t,[]),this.handlers.get(t).push(e),this}once(t,e){let i=async r=>{await e(r),this.off(t,i)};return this.on(t,i)}off(t,e){let i=this.handlers.get(t);if(i){let r=i.indexOf(e);r>-1&&i.splice(r,1)}}removeAllListeners(t){t?this.handlers.delete(t):this.handlers.clear()}async handle(t){let e=this.handlers.get(t.type)||[];for(let i of e)try{await i(t)}catch(r){throw console.error(`Error handling webhook event ${t.type}:`,r),r}}getHandlers(t){return this.handlers.get(t)||[]}getEventTypes(){return Array.from(this.handlers.keys())}hasHandlers(t){let e=this.handlers.get(t);return!!e&&e.length>0}};function m(n){let t=n.current_period_start;return typeof t=="number"?new Date(t*1e3):new Date(t)}function b(n){let t=n.current_period_end;return typeof t=="number"?new Date(t*1e3):new Date(t)}function w(n){let t=n.trial_end;return t?typeof t=="number"?new Date(t*1e3):new Date(t):null}function P(n){let t=n.canceled_at;return t?typeof t=="number"?new Date(t*1e3):new Date(t):null}var u=class{stripeService;deps;constructor(t){this.stripeService=t.stripeService,this.deps=t}async subscribe(t,e,i){let r=await this.deps.userRepository?.findById(t);if(!r)throw new Error(`User ${t} not found`);let s=await this.deps.planRepository?.findById(e);if(!s)throw new Error(`Plan ${e} not found`);let o=r.stripe_customer_id;o||(o=(await this.stripeService.createCustomer({id:t,name:r.name,email:r.email})).id,await this.deps.userRepository?.update(t,{stripe_customer_id:o}));let a=await this.stripeService.createSubscription(o,s.stripePriceId,{trialDays:i?.trialDays||s.trialDays,metadata:{userId:String(t),planId:String(e),...i?.metadata}}),c=await this.deps.subscriptionRepository?.create({user_id:t,stripe_subscription_id:a.id,stripe_customer_id:o,plan_id:e,status:a.status,current_period_start:m(a),current_period_end:b(a),trial_ends_at:w(a),cancel_at_period_end:a.cancel_at_period_end,canceled_at:P(a)});if(!c)throw new Error("Failed to create subscription record");return c}async upgrade(t,e){let i=await this.deps.subscriptionRepository?.findByUserId(t);if(!i)throw new Error(`User ${t} has no active subscription`);let r=await this.deps.planRepository?.findById(e);if(!r)throw new Error(`Plan ${e} not found`);let s=await this.stripeService.updateSubscription(i.stripeSubscriptionId,r.stripePriceId,{proration:"create_prorations"}),o=await this.deps.subscriptionRepository?.update(i.id,{plan_id:e,status:s.status,current_period_start:m(s),current_period_end:b(s)});if(!o)throw new Error("Failed to update subscription record");return o}async downgrade(t,e){let i=await this.deps.subscriptionRepository?.findByUserId(t);if(!i)throw new Error(`User ${t} has no active subscription`);let r=await this.deps.planRepository?.findById(e);if(!r)throw new Error(`Plan ${e} not found`);let s=await this.stripeService.updateSubscription(i.stripeSubscriptionId,r.stripePriceId,{proration:"none"}),o=await this.deps.subscriptionRepository?.update(i.id,{plan_id:e,status:s.status});if(!o)throw new Error("Failed to update subscription record");return o}async cancel(t,e=!1){let i=await this.deps.subscriptionRepository?.findByUserId(t);if(!i)throw new Error(`User ${t} has no active subscription`);await this.stripeService.cancelSubscription(i.stripeSubscriptionId,e),e?await this.deps.subscriptionRepository?.update(i.id,{status:"canceled",canceled_at:new Date}):await this.deps.subscriptionRepository?.update(i.id,{cancel_at_period_end:!0})}async resume(t){let e=await this.deps.subscriptionRepository?.findByUserId(t);if(!e)throw new Error(`User ${t} has no subscription`);let i=await this.stripeService.resumeSubscription(e.stripeSubscriptionId),r=await this.deps.subscriptionRepository?.update(e.id,{cancel_at_period_end:!1,canceled_at:null,status:i.status});if(!r)throw new Error("Failed to update subscription record");return r}async isSubscribed(t,e){let i=await this.deps.subscriptionRepository?.findByUserId(t);return!(!i||!i.isActive()||e&&i.planId!==e)}async onTrial(t){let e=await this.deps.subscriptionRepository?.findByUserId(t);return e?e.isOnTrial():!1}async hasFeature(t,e){let i=await this.deps.subscriptionRepository?.findByUserId(t);if(!i)return!1;let r=await this.deps.planRepository?.findById(i.planId);return r?r.hasFeature(e):!1}async syncFromStripe(t){let e=await this.deps.userRepository?.findById(t);if(!e||!e.stripe_customer_id)throw new Error(`User ${t} not found or has no Stripe customer`);let r=await(await this.stripeService.getClient()).subscriptions.list({customer:e.stripe_customer_id,status:"active",limit:1});if(r.data.length===0)throw new Error(`User ${t} has no active Stripe subscription`);let s=r.data[0],o=s.items.data[0]?.price?.id,a=await this.deps.planRepository?.findByStripePriceId(o);if(!a)throw new Error(`No plan found for Stripe price ${o}`);let c=await this.deps.subscriptionRepository?.findByStripeSubscriptionId(s.id),l={user_id:t,stripe_subscription_id:s.id,stripe_customer_id:e.stripe_customer_id,plan_id:a.id,status:s.status,current_period_start:m(s),current_period_end:b(s),trial_ends_at:w(s),cancel_at_period_end:s.cancel_at_period_end,canceled_at:P(s)};if(c?c=await this.deps.subscriptionRepository?.update(c.id,l):c=await this.deps.subscriptionRepository?.create(l),!c)throw new Error("Failed to sync subscription");return c}};var y=class{id;userId;stripeSubscriptionId;stripeCustomerId;planId;status;currentPeriodStart;currentPeriodEnd;cancelAtPeriodEnd;trialEndsAt;canceledAt;createdAt;updatedAt;constructor(t){this.id=t.id,this.userId=t.userId,this.stripeSubscriptionId=t.stripeSubscriptionId,this.stripeCustomerId=t.stripeCustomerId,this.planId=t.planId,this.status=t.status,this.currentPeriodStart=t.currentPeriodStart,this.currentPeriodEnd=t.currentPeriodEnd,this.cancelAtPeriodEnd=t.cancelAtPeriodEnd,this.trialEndsAt=t.trialEndsAt,this.canceledAt=t.canceledAt,this.createdAt=t.createdAt,this.updatedAt=t.updatedAt}isActive(){return this.status==="active"}isPastDue(){return this.status==="past_due"}isCanceled(){return this.status==="canceled"}isOnTrial(){return this.status==="trialing"||this.trialEndsAt!==null&&new Date<this.trialEndsAt}isOnGracePeriod(){return this.cancelAtPeriodEnd&&this.status!=="canceled"}isIncomplete(){return this.status==="incomplete"}isPaused(){return this.status==="paused"}daysUntilEnd(){let t=this.currentPeriodEnd.getTime()-Date.now();return Math.ceil(t/(1e3*60*60*24))}};var f=class{id;name;stripePriceId;stripeProductId;price;currency;interval;intervalCount;trialDays;features;sortOrder;active;createdAt;updatedAt;constructor(t){this.id=t.id,this.name=t.name,this.stripePriceId=t.stripePriceId,this.stripeProductId=t.stripeProductId,this.price=t.price,this.currency=t.currency,this.interval=t.interval,this.intervalCount=t.intervalCount,this.trialDays=t.trialDays,this.features=t.features,this.sortOrder=t.sortOrder,this.active=t.active,this.createdAt=t.createdAt,this.updatedAt=t.updatedAt}isActive(){return this.active}monthlyPrice(){let t=this.price/100;return this.interval==="month"?t:t/12}yearlyPrice(){let t=this.price/100;return this.interval==="year"?t:t*12}hasFeature(t){return this.features.includes(t)}formattedPrice(){let t=(this.price/100).toFixed(2),e=this.intervalCount>1?`${this.intervalCount} ${this.interval}s`:this.interval;return`${this.currency.toUpperCase()} ${t}/${e}`}intervalLabel(){return this.intervalCount>1?`Every ${this.intervalCount} ${this.interval}s`:`Every ${this.interval}`}trialLabel(){return this.trialDays===0?"No trial":`${this.trialDays} day${this.trialDays!==1?"s":""} free trial`}};var g=class{id;userId;subscriptionId;stripeInvoiceId;amountDue;amountPaid;currency;status;paidAt;dueDate;invoicePdf;createdAt;updatedAt;constructor(t){this.id=t.id,this.userId=t.userId,this.subscriptionId=t.subscriptionId,this.stripeInvoiceId=t.stripeInvoiceId,this.amountDue=t.amountDue,this.amountPaid=t.amountPaid,this.currency=t.currency,this.status=t.status,this.paidAt=t.paidAt,this.dueDate=t.dueDate,this.invoicePdf=t.invoicePdf,this.createdAt=t.createdAt,this.updatedAt=t.updatedAt}isPaid(){return this.status==="paid"}isOpen(){return this.status==="open"}isDraft(){return this.status==="draft"}isVoid(){return this.status==="void"}isUncollectible(){return this.status==="uncollectible"}isOverdue(){return!this.dueDate||this.status==="paid"||this.status==="void"?!1:new Date>this.dueDate}outstandingAmount(){return this.amountDue-this.amountPaid}formattedAmountDue(){return this.formatCurrency(this.amountDue)}formattedAmountPaid(){return this.formatCurrency(this.amountPaid)}formattedOutstanding(){return this.formatCurrency(this.outstandingAmount())}daysUntilDue(){return this.dueDate?Math.ceil((this.dueDate.getTime()-Date.now())/(1e3*60*60*24)):null}formatCurrency(t){return`${{usd:"$",eur:"\u20AC",gbp:"\xA3",jpy:"\xA5",cad:"C$",aud:"A$",chf:"CHF"}[this.currency.toLowerCase()]||this.currency.toUpperCase()}${(t/100).toFixed(2)}`}};var S=class n{constructor(t,e,i){this.userId=t;this.email=e;this.userName=i}name="sync-stripe-customer";async handle(t){let e=await t.createCustomer({id:this.userId,name:this.userName,email:this.email});console.log(`Synced user ${this.userId} to Stripe customer ${e.id}`)}serialize(){return JSON.stringify({userId:this.userId,email:this.email,name:this.userName})}static restore(t){return new n(t.userId,t.email,t.name)}};var v=class{stripeService=new p;webhookHandler=new d;subscriptionManager=null;configure(t){this.stripeService.configure(t)}service(){return this.stripeService}webhooks(){return this.webhookHandler}subscriptions(t){if(!this.subscriptionManager){if(!t)throw new Error("SubscriptionManager not initialized. Call Stripe.subscriptions({ stripeService, ... }) with dependencies first.");this.subscriptionManager=new u(t)}return this.subscriptionManager}initSubscriptions(t){return this.subscriptionManager=new u({stripeService:this.stripeService,...t}),this.subscriptionManager}},q=h("svelar.stripe",()=>new v);export{g as Invoice,q as Stripe,v as StripeManager,p as StripeService,d as StripeWebhookHandler,y as Subscription,u as SubscriptionManager,f as SubscriptionPlan,S as SyncStripeCustomerJob};
|