@beeblock/svelar 0.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/LICENSE +21 -0
- package/README.md +110 -0
- package/dist/actions/index.d.ts +101 -0
- package/dist/actions/index.js +1 -0
- package/dist/api-keys/index.d.ts +58 -0
- package/dist/api-keys/index.js +1 -0
- package/dist/audit/index.d.ts +52 -0
- package/dist/audit/index.js +1 -0
- package/dist/auth/Auth.d.ts +283 -0
- package/dist/auth/Gate.d.ts +166 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +80 -0
- package/dist/broadcasting/client.d.ts +195 -0
- package/dist/broadcasting/client.js +1 -0
- package/dist/broadcasting/index.d.ts +318 -0
- package/dist/broadcasting/index.js +20 -0
- package/dist/cache/index.d.ts +77 -0
- package/dist/cache/index.js +1 -0
- package/dist/cli/Cli.d.ts +23 -0
- package/dist/cli/Command.d.ts +36 -0
- package/dist/cli/bin.d.ts +8 -0
- package/dist/cli/bin.js +5856 -0
- package/dist/cli/commands/KeyGenerateCommand.d.ts +16 -0
- package/dist/cli/commands/MakeActionCommand.d.ts +15 -0
- package/dist/cli/commands/MakeBroadcastingCommand.d.ts +29 -0
- package/dist/cli/commands/MakeChannelCommand.d.ts +18 -0
- package/dist/cli/commands/MakeCommandCommand.d.ts +16 -0
- package/dist/cli/commands/MakeConfigCommand.d.ts +13 -0
- package/dist/cli/commands/MakeControllerCommand.d.ts +28 -0
- package/dist/cli/commands/MakeDashboardCommand.d.ts +34 -0
- package/dist/cli/commands/MakeDockerCommand.d.ts +32 -0
- package/dist/cli/commands/MakeEventCommand.d.ts +11 -0
- package/dist/cli/commands/MakeJobCommand.d.ts +11 -0
- package/dist/cli/commands/MakeListenerCommand.d.ts +16 -0
- package/dist/cli/commands/MakeMiddlewareCommand.d.ts +11 -0
- package/dist/cli/commands/MakeMigrationCommand.d.ts +17 -0
- package/dist/cli/commands/MakeModelCommand.d.ts +25 -0
- package/dist/cli/commands/MakeObserverCommand.d.ts +23 -0
- package/dist/cli/commands/MakePluginCommand.d.ts +11 -0
- package/dist/cli/commands/MakeProviderCommand.d.ts +11 -0
- package/dist/cli/commands/MakeRepositoryCommand.d.ts +22 -0
- package/dist/cli/commands/MakeRequestCommand.d.ts +15 -0
- package/dist/cli/commands/MakeResourceCommand.d.ts +30 -0
- package/dist/cli/commands/MakeRouteCommand.d.ts +42 -0
- package/dist/cli/commands/MakeSchemaCommand.d.ts +20 -0
- package/dist/cli/commands/MakeSeederCommand.d.ts +11 -0
- package/dist/cli/commands/MakeServiceCommand.d.ts +28 -0
- package/dist/cli/commands/MakeTaskCommand.d.ts +12 -0
- package/dist/cli/commands/MigrateCommand.d.ts +26 -0
- package/dist/cli/commands/NewCommand.d.ts +21 -0
- package/dist/cli/commands/NewCommandTemplates.d.ts +123 -0
- package/dist/cli/commands/PluginInstallCommand.d.ts +16 -0
- package/dist/cli/commands/PluginListCommand.d.ts +11 -0
- package/dist/cli/commands/PluginPublishCommand.d.ts +22 -0
- package/dist/cli/commands/QueueFailedCommand.d.ts +9 -0
- package/dist/cli/commands/QueueFlushCommand.d.ts +9 -0
- package/dist/cli/commands/QueueRetryCommand.d.ts +16 -0
- package/dist/cli/commands/QueueWorkCommand.d.ts +25 -0
- package/dist/cli/commands/RoutesListCommand.d.ts +30 -0
- package/dist/cli/commands/ScheduleRunCommand.d.ts +15 -0
- package/dist/cli/commands/SeedCommand.d.ts +14 -0
- package/dist/cli/commands/TinkerCommand.d.ts +10 -0
- package/dist/cli/index.d.ts +36 -0
- package/dist/cli/index.js +1973 -0
- package/dist/cli/ts-resolve-hook.mjs +74 -0
- package/dist/cli/ts-resolver.mjs +8 -0
- package/dist/config/Config.d.ts +65 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +1 -0
- package/dist/container/Application.d.ts +33 -0
- package/dist/container/Container.d.ts +70 -0
- package/dist/container/ServiceProvider.d.ts +21 -0
- package/dist/container/index.d.ts +3 -0
- package/dist/container/index.js +1 -0
- package/dist/dashboard/index.d.ts +123 -0
- package/dist/dashboard/index.js +5 -0
- package/dist/database/Connection.d.ts +80 -0
- package/dist/database/Migration.d.ts +76 -0
- package/dist/database/SchemaBuilder.d.ts +91 -0
- package/dist/database/Seeder.d.ts +9 -0
- package/dist/database/index.d.ts +4 -0
- package/dist/database/index.js +4 -0
- package/dist/email-templates/index.d.ts +51 -0
- package/dist/email-templates/index.js +57 -0
- package/dist/errors/Handler.d.ts +100 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +5 -0
- package/dist/events/EventServiceProvider.d.ts +82 -0
- package/dist/events/Listener.d.ts +28 -0
- package/dist/events/index.d.ts +80 -0
- package/dist/events/index.js +1 -0
- package/dist/excel/index.d.ts +154 -0
- package/dist/excel/index.js +1 -0
- package/dist/feature-flags/index.d.ts +158 -0
- package/dist/feature-flags/index.js +59 -0
- package/dist/forms/index.d.ts +81 -0
- package/dist/forms/index.js +1 -0
- package/dist/hashing/Hash.d.ts +51 -0
- package/dist/hashing/index.d.ts +1 -0
- package/dist/hashing/index.js +1 -0
- package/dist/hooks/index.d.ts +135 -0
- package/dist/hooks/index.js +5 -0
- package/dist/http/index.d.ts +201 -0
- package/dist/http/index.js +2 -0
- package/dist/i18n/index.d.ts +81 -0
- package/dist/i18n/index.js +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +127 -0
- package/dist/logging/LogViewer.d.ts +95 -0
- package/dist/logging/LogViewer.js +1 -0
- package/dist/logging/index.d.ts +83 -0
- package/dist/logging/index.js +3 -0
- package/dist/mail/index.d.ts +149 -0
- package/dist/mail/index.js +1 -0
- package/dist/middleware/Middleware.d.ts +208 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +1 -0
- package/dist/notifications/index.d.ts +85 -0
- package/dist/notifications/index.js +2 -0
- package/dist/orm/Model.d.ts +123 -0
- package/dist/orm/Observer.d.ts +34 -0
- package/dist/orm/QueryBuilder.d.ts +119 -0
- package/dist/orm/Relationship.d.ts +58 -0
- package/dist/orm/index.d.ts +4 -0
- package/dist/orm/index.js +1 -0
- package/dist/pagination/index.d.ts +8 -0
- package/dist/pagination/index.js +0 -0
- package/dist/pdf/GeneratePdfJob.d.ts +99 -0
- package/dist/pdf/GeneratePdfJob.js +41 -0
- package/dist/pdf/index.d.ts +328 -0
- package/dist/pdf/index.js +41 -0
- package/dist/permissions/index.d.ts +161 -0
- package/dist/permissions/index.js +60 -0
- package/dist/plugins/BootstrapPlugins.d.ts +11 -0
- package/dist/plugins/PluginInstaller.d.ts +30 -0
- package/dist/plugins/PluginInstaller.js +1 -0
- package/dist/plugins/PluginPublisher.d.ts +32 -0
- package/dist/plugins/PluginPublisher.js +1 -0
- package/dist/plugins/PluginRegistry.d.ts +55 -0
- package/dist/plugins/PluginRegistry.js +1 -0
- package/dist/plugins/index.d.ts +206 -0
- package/dist/plugins/index.js +1 -0
- package/dist/queue/JobMonitor.d.ts +109 -0
- package/dist/queue/JobMonitor.js +5 -0
- package/dist/queue/index.d.ts +279 -0
- package/dist/queue/index.js +5 -0
- package/dist/repositories/index.d.ts +147 -0
- package/dist/repositories/index.js +1 -0
- package/dist/routing/Controller.d.ts +115 -0
- package/dist/routing/FormRequest.d.ts +94 -0
- package/dist/routing/Resource.d.ts +213 -0
- package/dist/routing/Response.d.ts +138 -0
- package/dist/routing/index.d.ts +4 -0
- package/dist/routing/index.js +5 -0
- package/dist/scheduler/ScheduleMonitor.d.ts +141 -0
- package/dist/scheduler/ScheduleMonitor.js +1 -0
- package/dist/scheduler/SchedulerLock.d.ts +33 -0
- package/dist/scheduler/index.d.ts +208 -0
- package/dist/scheduler/index.js +34 -0
- package/dist/services/index.d.ts +79 -0
- package/dist/services/index.js +1 -0
- package/dist/session/Session.d.ts +166 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.js +16 -0
- package/dist/storage/index.d.ts +154 -0
- package/dist/storage/index.js +1 -0
- package/dist/support/Pipeline.d.ts +65 -0
- package/dist/support/date.d.ts +136 -0
- package/dist/support/date.js +1 -0
- package/dist/support/index.d.ts +8 -0
- package/dist/support/index.js +1 -0
- package/dist/support/singleton.d.ts +10 -0
- package/dist/support/uuid.d.ts +40 -0
- package/dist/teams/index.d.ts +91 -0
- package/dist/teams/index.js +78 -0
- package/dist/uploads/index.d.ts +63 -0
- package/dist/uploads/index.js +2 -0
- package/dist/validation/index.d.ts +46 -0
- package/dist/validation/index.js +1 -0
- package/dist/webhooks/index.d.ts +66 -0
- package/dist/webhooks/index.js +1 -0
- package/package.json +338 -0
- package/src/i18n/LanguageSwitcher.svelte +47 -0
- package/src/i18n/index.ts +113 -0
- package/src/ui/Alert.svelte +22 -0
- package/src/ui/Avatar.svelte +18 -0
- package/src/ui/AvatarFallback.svelte +18 -0
- package/src/ui/AvatarImage.svelte +12 -0
- package/src/ui/Badge.svelte +27 -0
- package/src/ui/Button.svelte +51 -0
- package/src/ui/Card.svelte +15 -0
- package/src/ui/CardContent.svelte +15 -0
- package/src/ui/CardDescription.svelte +15 -0
- package/src/ui/CardFooter.svelte +15 -0
- package/src/ui/CardHeader.svelte +15 -0
- package/src/ui/CardTitle.svelte +15 -0
- package/src/ui/Icon.svelte +81 -0
- package/src/ui/Input.svelte +40 -0
- package/src/ui/Label.svelte +20 -0
- package/src/ui/Separator.svelte +10 -0
- package/src/ui/Tabs.svelte +23 -0
- package/src/ui/TabsContent.svelte +27 -0
- package/src/ui/TabsList.svelte +19 -0
- package/src/ui/TabsTrigger.svelte +28 -0
- package/src/ui/Toaster.svelte +279 -0
- package/src/ui/index.ts +31 -0
- package/src/ui/toast.ts +212 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelar Teams & Workspaces
|
|
3
|
+
* Multi-tenant team support for SaaS applications.
|
|
4
|
+
*
|
|
5
|
+
* Tables (`teams`, `team_members`, `team_invitations`) are auto-created
|
|
6
|
+
* on first use when the database driver is configured — no migration required.
|
|
7
|
+
*/
|
|
8
|
+
export interface Team {
|
|
9
|
+
id: string | number;
|
|
10
|
+
name: string;
|
|
11
|
+
slug: string;
|
|
12
|
+
ownerId: string | number;
|
|
13
|
+
personalTeam: boolean;
|
|
14
|
+
metadata?: Record<string, any>;
|
|
15
|
+
createdAt: number;
|
|
16
|
+
updatedAt: number;
|
|
17
|
+
}
|
|
18
|
+
export interface TeamMember {
|
|
19
|
+
id: string | number;
|
|
20
|
+
teamId: string | number;
|
|
21
|
+
userId: string | number;
|
|
22
|
+
role: string;
|
|
23
|
+
joinedAt: number;
|
|
24
|
+
}
|
|
25
|
+
export interface TeamInvitation {
|
|
26
|
+
id: string;
|
|
27
|
+
teamId: string | number;
|
|
28
|
+
email: string;
|
|
29
|
+
role: string;
|
|
30
|
+
token: string;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
acceptedAt?: number;
|
|
33
|
+
createdAt: number;
|
|
34
|
+
}
|
|
35
|
+
export type TeamRole = 'owner' | 'admin' | 'member' | 'viewer';
|
|
36
|
+
export interface TeamsConfig {
|
|
37
|
+
driver: 'database' | 'memory';
|
|
38
|
+
table?: string;
|
|
39
|
+
membersTable?: string;
|
|
40
|
+
invitationsTable?: string;
|
|
41
|
+
roles?: TeamRole[];
|
|
42
|
+
maxTeamsPerUser?: number;
|
|
43
|
+
invitationExpiryHours?: number;
|
|
44
|
+
}
|
|
45
|
+
declare class TeamManager {
|
|
46
|
+
private config;
|
|
47
|
+
private memTeams;
|
|
48
|
+
private memMembers;
|
|
49
|
+
private memInvitations;
|
|
50
|
+
private currentTeamId;
|
|
51
|
+
private tablesEnsured;
|
|
52
|
+
configure(config: TeamsConfig): void;
|
|
53
|
+
private get teamsTable();
|
|
54
|
+
private get membersTable();
|
|
55
|
+
private get invitationsTable();
|
|
56
|
+
private get useDb();
|
|
57
|
+
private getConnection;
|
|
58
|
+
private getDriver;
|
|
59
|
+
/**
|
|
60
|
+
* Auto-create teams, team_members, and team_invitations tables on first use.
|
|
61
|
+
*/
|
|
62
|
+
ensureTables(): Promise<void>;
|
|
63
|
+
private rowToTeam;
|
|
64
|
+
private rowToMember;
|
|
65
|
+
private rowToInvitation;
|
|
66
|
+
create(data: {
|
|
67
|
+
name: string;
|
|
68
|
+
ownerId: string | number;
|
|
69
|
+
personalTeam?: boolean;
|
|
70
|
+
}): Promise<Team>;
|
|
71
|
+
update(teamId: string | number, data: Partial<Pick<Team, 'name' | 'metadata'>>): Promise<Team | null>;
|
|
72
|
+
delete(teamId: string | number): Promise<boolean>;
|
|
73
|
+
findById(teamId: string | number): Promise<Team | null>;
|
|
74
|
+
findBySlug(slug: string): Promise<Team | null>;
|
|
75
|
+
addMember(teamId: string | number, userId: string | number, role?: string): Promise<TeamMember>;
|
|
76
|
+
removeMember(teamId: string | number, userId: string | number): Promise<boolean>;
|
|
77
|
+
updateMemberRole(teamId: string | number, userId: string | number, role: string): Promise<boolean>;
|
|
78
|
+
getMembers(teamId: string | number): Promise<TeamMember[]>;
|
|
79
|
+
getUserTeams(userId: string | number): Promise<Team[]>;
|
|
80
|
+
isMember(teamId: string | number, userId: string | number): Promise<boolean>;
|
|
81
|
+
hasRole(teamId: string | number, userId: string | number, role: string): Promise<boolean>;
|
|
82
|
+
invite(teamId: string | number, email: string, role?: string): Promise<TeamInvitation>;
|
|
83
|
+
acceptInvitation(token: string, userId: string | number): Promise<boolean>;
|
|
84
|
+
cancelInvitation(invitationId: string): Promise<boolean>;
|
|
85
|
+
getPendingInvitations(teamId: string | number): Promise<TeamInvitation[]>;
|
|
86
|
+
setCurrentTeam(teamId: string | number): void;
|
|
87
|
+
getCurrentTeam(): string | number | null;
|
|
88
|
+
private slugify;
|
|
89
|
+
}
|
|
90
|
+
export declare const Teams: TeamManager;
|
|
91
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
var p=Object.defineProperty;var g=(T,e)=>()=>(T&&(e=T(T=0)),e);var N=(T,e)=>{for(var n in e)p(T,n,{get:e[n],enumerable:!0})};function d(T,e){let n=Symbol.for(T),t=globalThis;return t[n]||(t[n]=e()),t[n]}var u=g(()=>{"use strict"});var E={};N(E,{Connection:()=>A});var w,A,h=g(()=>{"use strict";u();w=class{connections=new Map;config=null;defaultName="default";configure(e){this.config=e,this.defaultName=e.default}async connection(e){let n=e??this.defaultName;if(this.connections.has(n))return this.connections.get(n).drizzle;if(!this.config)throw new Error("Database not configured. Call Connection.configure() first, or register DatabaseServiceProvider.");let t=this.config.connections[n];if(!t)throw new Error(`Database connection "${n}" is not defined in configuration.`);let a=await this.createConnection(t);return this.connections.set(n,a),a.drizzle}async rawClient(e){let n=e??this.defaultName;return await this.connection(n),this.connections.get(n).rawClient}async raw(e,n=[],t){let a=await this.connection(t),i=this.getConfig(t);switch(i.driver){case"sqlite":{let r=await this.rawClient(t),s=n.map(c=>typeof c=="boolean"?c?1:0:c instanceof Date?c.toISOString():c),o=r.prepare(e),m=e.trimStart().toUpperCase();return m.startsWith("SELECT")||m.startsWith("PRAGMA")||m.startsWith("WITH")?o.all(...s):o.run(...s)}case"postgres":return(await this.rawClient(t))(e,...n);case"mysql":{let r=await this.rawClient(t),[s]=await r.execute(e,n);return s}default:throw new Error(`Unsupported driver: ${i.driver}`)}}getDriver(e){return this.getConfig(e).driver}getConfig(e){let n=e??this.defaultName;if(!this.config)throw new Error("Database not configured.");let t=this.config.connections[n];if(!t)throw new Error(`Database connection "${n}" is not defined.`);return t}async disconnect(e){if(e){let n=this.connections.get(e);n&&(await this.closeConnection(n),this.connections.delete(e))}else{for(let[n,t]of this.connections)await this.closeConnection(t);this.connections.clear()}}isConnected(e){return this.connections.has(e??this.defaultName)}async transaction(e,n){let t=this.getConfig(n),a=await this.rawClient(n);switch(t.driver){case"sqlite":{a.exec("BEGIN");try{let i=await e();return a.exec("COMMIT"),i}catch(i){throw a.exec("ROLLBACK"),i}}case"postgres":{await a`BEGIN`;try{let i=await e();return await a`COMMIT`,i}catch(i){throw await a`ROLLBACK`,i}}case"mysql":{let i=await a.getConnection();await i.beginTransaction();try{let r=await e();return await i.commit(),i.release(),r}catch(r){throw await i.rollback(),i.release(),r}}default:throw new Error(`Unsupported driver: ${t.driver}`)}}async createConnection(e){switch(e.driver){case"sqlite":return this.createSQLiteConnection(e);case"postgres":return this.createPostgresConnection(e);case"mysql":return this.createMySQLConnection(e);default:throw new Error(`Unsupported database driver: ${e.driver}`)}}async createSQLiteConnection(e){let n=e.filename??e.database??":memory:";try{let t=(await import("better-sqlite3")).default,{drizzle:a}=await import("drizzle-orm/better-sqlite3"),i=new t(n);return i.pragma("journal_mode = WAL"),i.pragma("foreign_keys = ON"),{drizzle:a(i),config:e,rawClient:i}}catch(t){let a;try{a=(await new Function("mod","return import(mod)")("node:sqlite")).DatabaseSync}catch{throw new Error(`No SQLite driver available. Install better-sqlite3 (npm install better-sqlite3) or use Node.js v22+ which includes built-in SQLite support. Original error: ${t instanceof Error?t.message:String(t)}`)}let i=new a(n);i.exec("PRAGMA journal_mode = WAL"),i.exec("PRAGMA foreign_keys = ON");let r={prepare(o){let m=i.prepare(o);return{all(...c){return m.all(...c)},run(...c){return m.run(...c)},get(...c){return m.get(...c)}}},exec(o){i.exec(o)},pragma(o){return i.prepare(`PRAGMA ${o}`).all()},close(){i.close()}},s;try{let{drizzle:o}=await import("drizzle-orm/better-sqlite3");s=o(r)}catch{s=r}return{drizzle:s,config:e,rawClient:r}}}async createPostgresConnection(e){let n=(await import("postgres")).default,{drizzle:t}=await import("drizzle-orm/postgres-js"),a=e.url??`postgres://${e.user}:${e.password}@${e.host??"localhost"}:${e.port??5432}/${e.database}`,i=n(a);return{drizzle:t(i),config:e,rawClient:i}}async createMySQLConnection(e){let n=await import("mysql2/promise"),{drizzle:t}=await import("drizzle-orm/mysql2"),a=n.createPool({host:e.host??"localhost",port:e.port??3306,database:e.database,user:e.user,password:e.password,uri:e.url});return{drizzle:t(a),config:e,rawClient:a}}async closeConnection(e){try{switch(e.config.driver){case"sqlite":e.rawClient.close();break;case"postgres":await e.rawClient.end();break;case"mysql":await e.rawClient.end();break}}catch{}}},A=d("svelar.connection",()=>new w)});u();import{randomUUID as l}from"crypto";var b=class{config={driver:"memory",invitationExpiryHours:72};memTeams=[];memMembers=[];memInvitations=[];currentTeamId=null;tablesEnsured=!1;configure(e){this.config={...this.config,...e},this.tablesEnsured=!1}get teamsTable(){return this.config.table||"teams"}get membersTable(){return this.config.membersTable||"team_members"}get invitationsTable(){return this.config.invitationsTable||"team_invitations"}get useDb(){return this.config.driver==="database"}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(h(),E));return e}async getDriver(){return(await this.getConnection()).getDriver()}async ensureTables(){if(this.tablesEnsured||!this.useDb)return;let e=await this.getConnection(),n=e.getDriver(),t=this.teamsTable,a=this.membersTable,i=this.invitationsTable;switch(n){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS ${t} (
|
|
2
|
+
id TEXT PRIMARY KEY,
|
|
3
|
+
name TEXT NOT NULL,
|
|
4
|
+
slug TEXT NOT NULL UNIQUE,
|
|
5
|
+
owner_id TEXT NOT NULL,
|
|
6
|
+
personal_team INTEGER NOT NULL DEFAULT 0,
|
|
7
|
+
metadata TEXT,
|
|
8
|
+
created_at TEXT NOT NULL,
|
|
9
|
+
updated_at TEXT NOT NULL
|
|
10
|
+
)`),await e.raw(`CREATE TABLE IF NOT EXISTS ${a} (
|
|
11
|
+
id TEXT PRIMARY KEY,
|
|
12
|
+
team_id TEXT NOT NULL,
|
|
13
|
+
user_id TEXT NOT NULL,
|
|
14
|
+
role TEXT NOT NULL DEFAULT 'member',
|
|
15
|
+
joined_at TEXT NOT NULL,
|
|
16
|
+
UNIQUE(team_id, user_id)
|
|
17
|
+
)`),await e.raw(`CREATE TABLE IF NOT EXISTS ${i} (
|
|
18
|
+
id TEXT PRIMARY KEY,
|
|
19
|
+
team_id TEXT NOT NULL,
|
|
20
|
+
email TEXT NOT NULL,
|
|
21
|
+
role TEXT NOT NULL DEFAULT 'member',
|
|
22
|
+
token TEXT NOT NULL UNIQUE,
|
|
23
|
+
expires_at TEXT NOT NULL,
|
|
24
|
+
accepted_at TEXT,
|
|
25
|
+
created_at TEXT NOT NULL
|
|
26
|
+
)`);break;case"postgres":await e.raw(`CREATE TABLE IF NOT EXISTS ${t} (
|
|
27
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
28
|
+
name VARCHAR(255) NOT NULL,
|
|
29
|
+
slug VARCHAR(255) NOT NULL UNIQUE,
|
|
30
|
+
owner_id VARCHAR(255) NOT NULL,
|
|
31
|
+
personal_team BOOLEAN NOT NULL DEFAULT FALSE,
|
|
32
|
+
metadata JSONB,
|
|
33
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
34
|
+
updated_at TIMESTAMPTZ NOT NULL
|
|
35
|
+
)`),await e.raw(`CREATE TABLE IF NOT EXISTS ${a} (
|
|
36
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
37
|
+
team_id VARCHAR(255) NOT NULL,
|
|
38
|
+
user_id VARCHAR(255) NOT NULL,
|
|
39
|
+
role VARCHAR(50) NOT NULL DEFAULT 'member',
|
|
40
|
+
joined_at TIMESTAMPTZ NOT NULL,
|
|
41
|
+
UNIQUE(team_id, user_id)
|
|
42
|
+
)`),await e.raw(`CREATE TABLE IF NOT EXISTS ${i} (
|
|
43
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
44
|
+
team_id VARCHAR(255) NOT NULL,
|
|
45
|
+
email VARCHAR(255) NOT NULL,
|
|
46
|
+
role VARCHAR(50) NOT NULL DEFAULT 'member',
|
|
47
|
+
token VARCHAR(255) NOT NULL UNIQUE,
|
|
48
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
49
|
+
accepted_at TIMESTAMPTZ,
|
|
50
|
+
created_at TIMESTAMPTZ NOT NULL
|
|
51
|
+
)`);break;case"mysql":await e.raw(`CREATE TABLE IF NOT EXISTS ${t} (
|
|
52
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
53
|
+
name VARCHAR(255) NOT NULL,
|
|
54
|
+
slug VARCHAR(255) NOT NULL UNIQUE,
|
|
55
|
+
owner_id VARCHAR(255) NOT NULL,
|
|
56
|
+
personal_team TINYINT(1) NOT NULL DEFAULT 0,
|
|
57
|
+
metadata JSON,
|
|
58
|
+
created_at DATETIME NOT NULL,
|
|
59
|
+
updated_at DATETIME NOT NULL
|
|
60
|
+
) ENGINE=InnoDB`),await e.raw(`CREATE TABLE IF NOT EXISTS ${a} (
|
|
61
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
62
|
+
team_id VARCHAR(255) NOT NULL,
|
|
63
|
+
user_id VARCHAR(255) NOT NULL,
|
|
64
|
+
role VARCHAR(50) NOT NULL DEFAULT 'member',
|
|
65
|
+
joined_at DATETIME NOT NULL,
|
|
66
|
+
UNIQUE(team_id, user_id)
|
|
67
|
+
) ENGINE=InnoDB`),await e.raw(`CREATE TABLE IF NOT EXISTS ${i} (
|
|
68
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
69
|
+
team_id VARCHAR(255) NOT NULL,
|
|
70
|
+
email VARCHAR(255) NOT NULL,
|
|
71
|
+
role VARCHAR(50) NOT NULL DEFAULT 'member',
|
|
72
|
+
token VARCHAR(255) NOT NULL UNIQUE,
|
|
73
|
+
expires_at DATETIME NOT NULL,
|
|
74
|
+
accepted_at DATETIME,
|
|
75
|
+
created_at DATETIME NOT NULL
|
|
76
|
+
) ENGINE=InnoDB`);break}this.tablesEnsured=!0}rowToTeam(e){return{id:e.id,name:e.name,slug:e.slug,ownerId:e.owner_id,personalTeam:!!e.personal_team,metadata:e.metadata?typeof e.metadata=="string"?JSON.parse(e.metadata):e.metadata:void 0,createdAt:new Date(e.created_at).getTime(),updatedAt:new Date(e.updated_at).getTime()}}rowToMember(e){return{id:e.id,teamId:e.team_id,userId:e.user_id,role:e.role,joinedAt:new Date(e.joined_at).getTime()}}rowToInvitation(e){return{id:e.id,teamId:e.team_id,email:e.email,role:e.role,token:e.token,expiresAt:new Date(e.expires_at).getTime(),acceptedAt:e.accepted_at?new Date(e.accepted_at).getTime():void 0,createdAt:new Date(e.created_at).getTime()}}async create(e){let n=this.slugify(e.name),t=Date.now(),a={id:l(),name:e.name,slug:n,ownerId:e.ownerId,personalTeam:e.personalTeam||!1,createdAt:t,updatedAt:t};if(this.useDb){await this.ensureTables();let i=await this.getConnection(),r=new Date(t).toISOString();await i.raw(`INSERT INTO ${this.teamsTable} (id, name, slug, owner_id, personal_team, metadata, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[a.id,a.name,a.slug,a.ownerId,a.personalTeam?1:0,null,r,r]),await i.raw(`INSERT INTO ${this.membersTable} (id, team_id, user_id, role, joined_at) VALUES (?, ?, ?, ?, ?)`,[l(),a.id,e.ownerId,"owner",r])}else this.memTeams.push(a),this.memMembers.push({id:l(),teamId:a.id,userId:e.ownerId,role:"owner",joinedAt:t});return a}async update(e,n){if(this.useDb){await this.ensureTables();let a=await this.getConnection(),i=await this.findById(e);if(!i)return null;let r=new Date().toISOString(),s=n.name??i.name,o=n.name?this.slugify(n.name):i.slug,m=n.metadata!==void 0?JSON.stringify(n.metadata):i.metadata?JSON.stringify(i.metadata):null;return await a.raw(`UPDATE ${this.teamsTable} SET name = ?, slug = ?, metadata = ?, updated_at = ? WHERE id = ?`,[s,o,m,r,e]),this.findById(e)}let t=this.memTeams.find(a=>a.id===e);return t?(Object.assign(t,n,{updatedAt:Date.now()}),n.name&&(t.slug=this.slugify(n.name)),t):null}async delete(e){if(this.useDb){await this.ensureTables();let t=await this.getConnection();await t.raw(`DELETE FROM ${this.invitationsTable} WHERE team_id = ?`,[e]),await t.raw(`DELETE FROM ${this.membersTable} WHERE team_id = ?`,[e]);let a=await t.raw(`DELETE FROM ${this.teamsTable} WHERE id = ?`,[e]);return!0}let n=this.memTeams.findIndex(t=>t.id===e);return n===-1?!1:(this.memTeams.splice(n,1),this.memMembers=this.memMembers.filter(t=>t.teamId!==e),this.memInvitations=this.memInvitations.filter(t=>t.teamId!==e),!0)}async findById(e){if(this.useDb){await this.ensureTables();let t=await(await this.getConnection()).raw(`SELECT * FROM ${this.teamsTable} WHERE id = ?`,[e]);return t.length>0?this.rowToTeam(t[0]):null}return this.memTeams.find(n=>n.id===e)||null}async findBySlug(e){if(this.useDb){await this.ensureTables();let t=await(await this.getConnection()).raw(`SELECT * FROM ${this.teamsTable} WHERE slug = ?`,[e]);return t.length>0?this.rowToTeam(t[0]):null}return this.memTeams.find(n=>n.slug===e)||null}async addMember(e,n,t="member"){if(this.useDb){await this.ensureTables();let r=await this.getConnection(),s=await r.raw(`SELECT * FROM ${this.membersTable} WHERE team_id = ? AND user_id = ?`,[e,n]);if(s.length>0)return this.rowToMember(s[0]);let o=l(),m=new Date().toISOString();return await r.raw(`INSERT INTO ${this.membersTable} (id, team_id, user_id, role, joined_at) VALUES (?, ?, ?, ?, ?)`,[o,e,n,t,m]),{id:o,teamId:e,userId:n,role:t,joinedAt:Date.now()}}let a=this.memMembers.find(r=>r.teamId===e&&r.userId===n);if(a)return a;let i={id:l(),teamId:e,userId:n,role:t,joinedAt:Date.now()};return this.memMembers.push(i),i}async removeMember(e,n){if(this.useDb)return await this.ensureTables(),await(await this.getConnection()).raw(`DELETE FROM ${this.membersTable} WHERE team_id = ? AND user_id = ?`,[e,n]),!0;let t=this.memMembers.findIndex(a=>a.teamId===e&&a.userId===n);return t===-1?!1:(this.memMembers.splice(t,1),!0)}async updateMemberRole(e,n,t){if(this.useDb)return await this.ensureTables(),await(await this.getConnection()).raw(`UPDATE ${this.membersTable} SET role = ? WHERE team_id = ? AND user_id = ?`,[t,e,n]),!0;let a=this.memMembers.find(i=>i.teamId===e&&i.userId===n);return a?(a.role=t,!0):!1}async getMembers(e){return this.useDb?(await this.ensureTables(),(await(await this.getConnection()).raw(`SELECT * FROM ${this.membersTable} WHERE team_id = ?`,[e])).map(a=>this.rowToMember(a))):this.memMembers.filter(n=>n.teamId===e)}async getUserTeams(e){if(this.useDb)return await this.ensureTables(),(await(await this.getConnection()).raw(`SELECT t.* FROM ${this.teamsTable} t
|
|
77
|
+
INNER JOIN ${this.membersTable} m ON m.team_id = t.id
|
|
78
|
+
WHERE m.user_id = ?`,[e])).map(i=>this.rowToTeam(i));let n=this.memMembers.filter(t=>t.userId===e).map(t=>t.teamId);return this.memTeams.filter(t=>n.includes(t.id))}async isMember(e,n){return this.useDb?(await this.ensureTables(),(await(await this.getConnection()).raw(`SELECT 1 FROM ${this.membersTable} WHERE team_id = ? AND user_id = ?`,[e,n])).length>0):this.memMembers.some(t=>t.teamId===e&&t.userId===n)}async hasRole(e,n,t){return this.useDb?(await this.ensureTables(),(await(await this.getConnection()).raw(`SELECT 1 FROM ${this.membersTable} WHERE team_id = ? AND user_id = ? AND role = ?`,[e,n,t])).length>0):this.memMembers.find(i=>i.teamId===e&&i.userId===n)?.role===t||!1}async invite(e,n,t="member"){let a=this.config.invitationExpiryHours||72,i=Date.now(),r={id:l(),teamId:e,email:n,role:t,token:l(),expiresAt:i+a*60*60*1e3,createdAt:i};if(this.useDb)await this.ensureTables(),await(await this.getConnection()).raw(`INSERT INTO ${this.invitationsTable} (id, team_id, email, role, token, expires_at, accepted_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[r.id,e,n,t,r.token,new Date(r.expiresAt).toISOString(),null,new Date(i).toISOString()]);else{if(!this.memTeams.find(o=>o.id===e))throw new Error(`Team ${e} not found`);this.memInvitations.push(r)}return r}async acceptInvitation(e,n){if(this.useDb){await this.ensureTables();let a=await this.getConnection(),i=new Date().toISOString(),r=await a.raw(`SELECT * FROM ${this.invitationsTable} WHERE token = ? AND accepted_at IS NULL`,[e]);if(r.length===0)return!1;let s=r[0];return new Date(s.expires_at).getTime()<Date.now()?!1:(await this.addMember(s.team_id,n,s.role),await a.raw(`UPDATE ${this.invitationsTable} SET accepted_at = ? WHERE id = ?`,[i,s.id]),!0)}let t=this.memInvitations.find(a=>a.token===e);return!t||t.expiresAt<Date.now()?!1:(await this.addMember(t.teamId,n,t.role),t.acceptedAt=Date.now(),!0)}async cancelInvitation(e){if(this.useDb)return await this.ensureTables(),await(await this.getConnection()).raw(`DELETE FROM ${this.invitationsTable} WHERE id = ?`,[e]),!0;let n=this.memInvitations.findIndex(t=>t.id===e);return n===-1?!1:(this.memInvitations.splice(n,1),!0)}async getPendingInvitations(e){if(this.useDb){await this.ensureTables();let n=await this.getConnection(),t=new Date().toISOString();return(await n.raw(`SELECT * FROM ${this.invitationsTable} WHERE team_id = ? AND accepted_at IS NULL AND expires_at > ?`,[e,t])).map(i=>this.rowToInvitation(i))}return this.memInvitations.filter(n=>n.teamId===e&&!n.acceptedAt&&n.expiresAt>Date.now())}setCurrentTeam(e){this.currentTeamId=e}getCurrentTeam(){return this.currentTeamId}slugify(e){return e.toLowerCase().replace(/[^\w\s-]/g,"").replace(/[\s_]+/g,"-").replace(/^-+|-+$/g,"")}},D=d("svelar.teams",()=>new b);export{D as Teams};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelar File Uploads
|
|
3
|
+
* Track and manage uploaded files with metadata.
|
|
4
|
+
*/
|
|
5
|
+
export interface FileUpload {
|
|
6
|
+
id: string;
|
|
7
|
+
userId?: string | number;
|
|
8
|
+
originalName: string;
|
|
9
|
+
storedName: string;
|
|
10
|
+
path: string;
|
|
11
|
+
disk: string;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
size: number;
|
|
14
|
+
metadata?: Record<string, any>;
|
|
15
|
+
publicUrl?: string;
|
|
16
|
+
createdAt: number;
|
|
17
|
+
}
|
|
18
|
+
export interface UploadOptions {
|
|
19
|
+
disk?: string;
|
|
20
|
+
directory?: string;
|
|
21
|
+
maxSize?: number;
|
|
22
|
+
allowedMimes?: string[];
|
|
23
|
+
generateThumbnail?: boolean;
|
|
24
|
+
public?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface UploadsConfig {
|
|
27
|
+
driver: 'database' | 'memory';
|
|
28
|
+
table?: string;
|
|
29
|
+
maxFileSize?: number;
|
|
30
|
+
allowedMimeTypes?: string[];
|
|
31
|
+
defaultDisk?: string;
|
|
32
|
+
}
|
|
33
|
+
declare class UploadManager {
|
|
34
|
+
private config;
|
|
35
|
+
private uploads;
|
|
36
|
+
configure(config: UploadsConfig): void;
|
|
37
|
+
/** Store an uploaded file */
|
|
38
|
+
store(file: {
|
|
39
|
+
name: string;
|
|
40
|
+
data: Buffer | Uint8Array;
|
|
41
|
+
type: string;
|
|
42
|
+
}, options?: UploadOptions): Promise<FileUpload>;
|
|
43
|
+
/** Store from a SvelteKit request */
|
|
44
|
+
storeFromRequest(formData: FormData, fieldName: string, options?: UploadOptions): Promise<FileUpload | null>;
|
|
45
|
+
/** Get upload by ID */
|
|
46
|
+
get(id: string): Promise<FileUpload | null>;
|
|
47
|
+
/** List uploads for a user */
|
|
48
|
+
listForUser(userId: string | number, limit?: number): Promise<FileUpload[]>;
|
|
49
|
+
/** Delete an upload (removes file and record) */
|
|
50
|
+
delete(id: string): Promise<boolean>;
|
|
51
|
+
/** Get a temporary/signed URL for a file */
|
|
52
|
+
getUrl(id: string, expiresIn?: number): Promise<string | null>;
|
|
53
|
+
/** Get upload statistics */
|
|
54
|
+
getStats(): Promise<{
|
|
55
|
+
totalFiles: number;
|
|
56
|
+
totalSize: number;
|
|
57
|
+
byMimeType: Record<string, number>;
|
|
58
|
+
}>;
|
|
59
|
+
/** Helper: Extract file extension */
|
|
60
|
+
private getExtension;
|
|
61
|
+
}
|
|
62
|
+
export declare const Uploads: UploadManager;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var U=Object.defineProperty;var w=(u,t)=>()=>(u&&(t=u(u=0)),t);var x=(u,t)=>{for(var e in t)U(u,e,{get:t[e],enumerable:!0})};function d(u,t){let e=Symbol.for(u),i=globalThis;return i[e]||(i[e]=t()),i[e]}var p=w(()=>{"use strict"});var $={};x($,{S3Disk:()=>f,Storage:()=>L});import{readFile as D,writeFile as E,unlink as I,mkdir as m,readdir as b,stat as S,copyFile as O,rename as q}from"fs/promises";import{existsSync as N}from"fs";import{join as _,dirname as y}from"path";var k,f,v,L,z=w(()=>{"use strict";p();k=class{constructor(t){this.config=t;if(!t.root)throw new Error('Local disk requires a "root" path.')}resolve(t){return _(this.config.root,t)}async get(t){return D(this.resolve(t))}async getText(t){return D(this.resolve(t),"utf-8")}async put(t,e){let i=this.resolve(t);await m(y(i),{recursive:!0}),await E(i,e)}async append(t,e){let{appendFile:i}=await import("fs/promises"),s=this.resolve(t);await m(y(s),{recursive:!0}),await i(s,e)}async exists(t){return N(this.resolve(t))}async delete(t){try{return await I(this.resolve(t)),!0}catch{return!1}}async copy(t,e){let i=this.resolve(e);await m(y(i),{recursive:!0}),await O(this.resolve(t),i)}async move(t,e){let i=this.resolve(e);await m(y(i),{recursive:!0}),await q(this.resolve(t),i)}async files(t=""){let e=this.resolve(t);try{return(await b(e,{withFileTypes:!0})).filter(s=>s.isFile()).map(s=>t?`${t}/${s.name}`:s.name)}catch{return[]}}async allFiles(t=""){let e=[],i=this.resolve(t);try{let s=await b(i,{withFileTypes:!0});for(let r of s){let n=t?`${t}/${r.name}`:r.name;r.isFile()?e.push(n):r.isDirectory()&&e.push(...await this.allFiles(n))}}catch{}return e}async directories(t=""){let e=this.resolve(t);try{return(await b(e,{withFileTypes:!0})).filter(s=>s.isDirectory()).map(s=>t?`${t}/${s.name}`:s.name)}catch{return[]}}async makeDirectory(t){await m(this.resolve(t),{recursive:!0})}async deleteDirectory(t){let{rm:e}=await import("fs/promises");await e(this.resolve(t),{recursive:!0,force:!0})}async size(t){return(await S(this.resolve(t))).size}async lastModified(t){return(await S(this.resolve(t))).mtime}url(t){return`${this.config.urlPrefix??""}/${t}`}},f=class{config;_client=null;_s3Module=null;constructor(t){if(!t.bucket)throw new Error('S3 disk requires a "bucket" name.');this.config=t}async getS3(){if(this._s3Module)return this._s3Module;try{return this._s3Module=await Function('return import("@aws-sdk/client-s3")')(),this._s3Module}catch{throw new Error("S3 storage driver requires @aws-sdk/client-s3. Install it with: npm install @aws-sdk/client-s3")}}async getClient(){if(this._client)return this._client;let t=await this.getS3();return this._client=new t.S3Client({region:this.config.region??"us-east-1",endpoint:this.config.endpoint,forcePathStyle:this.config.forcePathStyle??!0,credentials:{accessKeyId:this.config.accessKeyId??"",secretAccessKey:this.config.secretAccessKey??""}}),this._client}key(t){let e=this.config.prefix;return e?`${e}/${t}`:t}async get(t){let e=await this.getS3(),r=await(await(await this.getClient()).send(new e.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(t)}))).Body.transformToByteArray();return Buffer.from(r)}async getText(t){return(await this.get(t)).toString("utf-8")}async put(t,e){let i=await this.getS3(),s=await this.getClient(),r=typeof e=="string"?Buffer.from(e,"utf-8"):e;await s.send(new i.PutObjectCommand({Bucket:this.config.bucket,Key:this.key(t),Body:r}))}async append(t,e){let i=null;try{i=await this.get(t)}catch{}let s=typeof e=="string"?Buffer.from(e,"utf-8"):e,r=i?Buffer.concat([i,s]):s;await this.put(t,r)}async exists(t){let e=await this.getS3(),i=await this.getClient();try{return await i.send(new e.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(t)})),!0}catch{return!1}}async delete(t){let e=await this.getS3(),i=await this.getClient();try{return await i.send(new e.DeleteObjectCommand({Bucket:this.config.bucket,Key:this.key(t)})),!0}catch{return!1}}async copy(t,e){let i=await this.getS3();await(await this.getClient()).send(new i.CopyObjectCommand({Bucket:this.config.bucket,CopySource:`${this.config.bucket}/${this.key(t)}`,Key:this.key(e)}))}async move(t,e){await this.copy(t,e),await this.delete(t)}async files(t=""){let e=await this.getS3(),i=await this.getClient(),s=this.key(t?`${t}/`:"");try{return((await i.send(new e.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:s,Delimiter:"/"}))).Contents??[]).map(n=>n.Key).filter(n=>n!==s).map(n=>{let o=this.config.prefix;return o?n.slice(o.length+1):n})}catch{return[]}}async allFiles(t=""){let e=await this.getS3(),i=await this.getClient(),s=this.key(t?`${t}/`:""),r=[],n;do{let o=await i.send(new e.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:s,ContinuationToken:n}));for(let a of o.Contents??[]){let l=this.config.prefix,c=l?a.Key.slice(l.length+1):a.Key;c&&r.push(c)}n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return r}async directories(t=""){let e=await this.getS3(),i=await this.getClient(),s=this.key(t?`${t}/`:"");try{return((await i.send(new e.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:s,Delimiter:"/"}))).CommonPrefixes??[]).map(n=>{let o=this.config.prefix;return(o?n.Prefix.slice(o.length+1):n.Prefix).replace(/\/$/,"")}).filter(n=>n.length>0)}catch{return[]}}async makeDirectory(t){}async deleteDirectory(t){let e=await this.allFiles(t);for(let i of e)await this.delete(i)}async size(t){let e=await this.getS3();return(await(await this.getClient()).send(new e.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(t)}))).ContentLength??0}async lastModified(t){let e=await this.getS3();return(await(await this.getClient()).send(new e.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(t)}))).LastModified??new Date}url(t){let e=this.config.urlPrefix;if(e)return`${e}/${t}`;let i=this.config.endpoint??`https://s3.${this.config.region??"us-east-1"}.amazonaws.com`;return this.config.forcePathStyle!==!1?`${i}/${this.config.bucket}/${this.key(t)}`:`${i.replace("://",`://${this.config.bucket}.`)}/${this.key(t)}`}async temporaryUrl(t,e=3600){try{let i=await Function('return import("@aws-sdk/s3-request-presigner")')(),s=await this.getS3(),r=await this.getClient(),n=new s.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(t)});return await i.getSignedUrl(r,n,{expiresIn:e})}catch{throw new Error("Pre-signed URLs require @aws-sdk/s3-request-presigner. Install it with: npm install @aws-sdk/s3-request-presigner")}}async ensureBucket(){let t=await this.getS3(),e=await this.getClient();try{await e.send(new t.HeadBucketCommand({Bucket:this.config.bucket}))}catch{await e.send(new t.CreateBucketCommand({Bucket:this.config.bucket}))}}},v=class{config=null;disks=new Map;configure(t){this.config=t}disk(t){let e=t??this.config?.default??"local";if(this.disks.has(e))return this.disks.get(e);if(!this.config)throw new Error("Storage not configured. Call Storage.configure() first.");let i=this.config.disks[e];if(!i)throw new Error(`Storage disk "${e}" is not defined.`);let s=this.createDisk(i);return this.disks.set(e,s),s}async get(t){return this.disk().get(t)}async getText(t){return this.disk().getText(t)}async put(t,e){return this.disk().put(t,e)}async append(t,e){return this.disk().append(t,e)}async exists(t){return this.disk().exists(t)}async delete(t){return this.disk().delete(t)}async copy(t,e){return this.disk().copy(t,e)}async move(t,e){return this.disk().move(t,e)}async files(t){return this.disk().files(t)}async allFiles(t){return this.disk().allFiles(t)}async directories(t){return this.disk().directories(t)}async makeDirectory(t){return this.disk().makeDirectory(t)}async deleteDirectory(t){return this.disk().deleteDirectory(t)}async size(t){return this.disk().size(t)}async lastModified(t){return this.disk().lastModified(t)}url(t){return this.disk().url(t)}createDisk(t){switch(t.driver){case"local":return new k(t);case"s3":return new f(t);default:throw new Error(`Unknown storage driver: ${t.driver}`)}}s3Disk(t){let e=this.disk(t);if(!(e instanceof f))throw new Error(`Disk "${t??this.config?.default}" is not an S3 disk.`);return e}},L=d("svelar.storage",()=>new v)});var B={};x(B,{Connection:()=>K});var C,K,F=w(()=>{"use strict";p();C=class{connections=new Map;config=null;defaultName="default";configure(t){this.config=t,this.defaultName=t.default}async connection(t){let e=t??this.defaultName;if(this.connections.has(e))return this.connections.get(e).drizzle;if(!this.config)throw new Error("Database not configured. Call Connection.configure() first, or register DatabaseServiceProvider.");let i=this.config.connections[e];if(!i)throw new Error(`Database connection "${e}" is not defined in configuration.`);let s=await this.createConnection(i);return this.connections.set(e,s),s.drizzle}async rawClient(t){let e=t??this.defaultName;return await this.connection(e),this.connections.get(e).rawClient}async raw(t,e=[],i){let s=await this.connection(i),r=this.getConfig(i);switch(r.driver){case"sqlite":{let n=await this.rawClient(i),o=e.map(c=>typeof c=="boolean"?c?1:0:c instanceof Date?c.toISOString():c),a=n.prepare(t),l=t.trimStart().toUpperCase();return l.startsWith("SELECT")||l.startsWith("PRAGMA")||l.startsWith("WITH")?a.all(...o):a.run(...o)}case"postgres":return(await this.rawClient(i))(t,...e);case"mysql":{let n=await this.rawClient(i),[o]=await n.execute(t,e);return o}default:throw new Error(`Unsupported driver: ${r.driver}`)}}getDriver(t){return this.getConfig(t).driver}getConfig(t){let e=t??this.defaultName;if(!this.config)throw new Error("Database not configured.");let i=this.config.connections[e];if(!i)throw new Error(`Database connection "${e}" is not defined.`);return i}async disconnect(t){if(t){let e=this.connections.get(t);e&&(await this.closeConnection(e),this.connections.delete(t))}else{for(let[e,i]of this.connections)await this.closeConnection(i);this.connections.clear()}}isConnected(t){return this.connections.has(t??this.defaultName)}async transaction(t,e){let i=this.getConfig(e),s=await this.rawClient(e);switch(i.driver){case"sqlite":{s.exec("BEGIN");try{let r=await t();return s.exec("COMMIT"),r}catch(r){throw s.exec("ROLLBACK"),r}}case"postgres":{await s`BEGIN`;try{let r=await t();return await s`COMMIT`,r}catch(r){throw await s`ROLLBACK`,r}}case"mysql":{let r=await s.getConnection();await r.beginTransaction();try{let n=await t();return await r.commit(),r.release(),n}catch(n){throw await r.rollback(),r.release(),n}}default:throw new Error(`Unsupported driver: ${i.driver}`)}}async createConnection(t){switch(t.driver){case"sqlite":return this.createSQLiteConnection(t);case"postgres":return this.createPostgresConnection(t);case"mysql":return this.createMySQLConnection(t);default:throw new Error(`Unsupported database driver: ${t.driver}`)}}async createSQLiteConnection(t){let e=t.filename??t.database??":memory:";try{let i=(await import("better-sqlite3")).default,{drizzle:s}=await import("drizzle-orm/better-sqlite3"),r=new i(e);return r.pragma("journal_mode = WAL"),r.pragma("foreign_keys = ON"),{drizzle:s(r),config:t,rawClient:r}}catch(i){let s;try{s=(await new Function("mod","return import(mod)")("node:sqlite")).DatabaseSync}catch{throw new Error(`No SQLite driver available. Install better-sqlite3 (npm install better-sqlite3) or use Node.js v22+ which includes built-in SQLite support. Original error: ${i instanceof Error?i.message:String(i)}`)}let r=new s(e);r.exec("PRAGMA journal_mode = WAL"),r.exec("PRAGMA foreign_keys = ON");let n={prepare(a){let l=r.prepare(a);return{all(...c){return l.all(...c)},run(...c){return l.run(...c)},get(...c){return l.get(...c)}}},exec(a){r.exec(a)},pragma(a){return r.prepare(`PRAGMA ${a}`).all()},close(){r.close()}},o;try{let{drizzle:a}=await import("drizzle-orm/better-sqlite3");o=a(n)}catch{o=n}return{drizzle:o,config:t,rawClient:n}}}async createPostgresConnection(t){let e=(await import("postgres")).default,{drizzle:i}=await import("drizzle-orm/postgres-js"),s=t.url??`postgres://${t.user}:${t.password}@${t.host??"localhost"}:${t.port??5432}/${t.database}`,r=e(s);return{drizzle:i(r),config:t,rawClient:r}}async createMySQLConnection(t){let e=await import("mysql2/promise"),{drizzle:i}=await import("drizzle-orm/mysql2"),s=e.createPool({host:t.host??"localhost",port:t.port??3306,database:t.database,user:t.user,password:t.password,uri:t.url});return{drizzle:i(s),config:t,rawClient:s}}async closeConnection(t){try{switch(t.config.driver){case"sqlite":t.rawClient.close();break;case"postgres":await t.rawClient.end();break;case"mysql":await t.rawClient.end();break}}catch{}}},K=d("svelar.connection",()=>new C)});p();import{randomUUID as T}from"crypto";var P=class{config={driver:"memory",maxFileSize:10*1024*1024};uploads=[];configure(t){this.config={...this.config,...t}}async store(t,e){let i=e?.allowedMimes||this.config.allowedMimeTypes;if(i&&!i.includes(t.type))throw new Error(`File type ${t.type} not allowed. Allowed: ${i.join(", ")}`);let s=e?.maxSize||this.config.maxFileSize||10*1024*1024,r=Buffer.isBuffer(t.data)?t.data:Buffer.from(t.data);if(r.length>s)throw new Error(`File size exceeds maximum of ${s/1024/1024}MB`);let n=this.getExtension(t.name),o=`${T()}${n?`.${n}`:""}`,a=e?.directory||"",l=e?.disk||this.config.defaultDisk||"local",c=a?`${a}/${o}`:o,g={id:T(),originalName:t.name,storedName:o,path:c,disk:l,mimeType:t.type,size:r.length,metadata:e?.public?{public:!0}:void 0,createdAt:Date.now()};try{let{Storage:h}=await Promise.resolve().then(()=>(z(),$));await h.disk(l).put(c,r),g.publicUrl=h.disk(l).url(c)}catch{}if(this.config.driver==="memory")this.uploads.push(g);else if(this.config.driver==="database")try{let{Connection:h}=await Promise.resolve().then(()=>(F(),B)),M=await h.connection(),A=this.config.table??"svelar_uploads";await M.raw(`INSERT INTO ${A} (id, user_id, original_name, stored_name, path, disk, mime_type, size, public_url, metadata, created_at)
|
|
2
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[g.id,g.userId??null,g.originalName,g.storedName,g.path,g.disk,g.mimeType,g.size,g.publicUrl??null,JSON.stringify(g.metadata??{}),Math.floor(g.createdAt/1e3)])}catch{this.uploads.push(g)}return g}async storeFromRequest(t,e,i){let s=t.get(e);if(!(s instanceof File))return null;let r=await s.arrayBuffer();return this.store({name:s.name,data:Buffer.from(r),type:s.type},i)}async get(t){return this.uploads.find(e=>e.id===t)||null}async listForUser(t,e){return this.uploads.filter(i=>i.userId===t).sort((i,s)=>s.createdAt-i.createdAt).slice(0,e||100)}async delete(t){let e=this.uploads.findIndex(i=>i.id===t);return e===-1?!1:(this.uploads.splice(e,1),!0)}async getUrl(t,e){let i=await this.get(t);return i?`/files/${i.id}/${i.storedName}`:null}async getStats(){let t={},e=0;for(let i of this.uploads)t[i.mimeType]=(t[i.mimeType]||0)+1,e+=i.size;return{totalFiles:this.uploads.length,totalSize:e,byMimeType:t}}getExtension(t){let e=t.split(".");return e.length>1?e[e.length-1].toLowerCase():""}},tt=d("svelar.uploads",()=>new P);export{tt as Uploads};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelar Validation
|
|
3
|
+
*
|
|
4
|
+
* Re-exports Zod with some convenience helpers for common validation patterns.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
export { z };
|
|
8
|
+
export declare const rules: {
|
|
9
|
+
required: () => z.ZodString;
|
|
10
|
+
email: () => z.ZodString;
|
|
11
|
+
string: (min?: number, max?: number) => z.ZodString;
|
|
12
|
+
number: (min?: number, max?: number) => z.ZodNumber;
|
|
13
|
+
integer: () => z.ZodNumber;
|
|
14
|
+
boolean: () => z.ZodBoolean;
|
|
15
|
+
date: () => z.ZodDate;
|
|
16
|
+
url: () => z.ZodString;
|
|
17
|
+
uuid: () => z.ZodString;
|
|
18
|
+
enum: <T extends [string, ...string[]]>(values: T) => z.ZodEnum<z.Writeable<T>>;
|
|
19
|
+
array: <T extends z.ZodTypeAny>(schema: T) => z.ZodArray<T, "many">;
|
|
20
|
+
nullable: <T extends z.ZodTypeAny>(schema: T) => z.ZodNullable<T>;
|
|
21
|
+
optional: <T extends z.ZodTypeAny>(schema: T) => z.ZodOptional<T>;
|
|
22
|
+
confirmed: (field?: string) => z.ZodEffects<z.ZodObject<{
|
|
23
|
+
[x: string]: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
[x: string]: string;
|
|
26
|
+
}, {
|
|
27
|
+
[x: string]: string;
|
|
28
|
+
}>, {
|
|
29
|
+
[x: string]: string;
|
|
30
|
+
}, {
|
|
31
|
+
[x: string]: string;
|
|
32
|
+
}>;
|
|
33
|
+
min: (value: number) => z.ZodNumber;
|
|
34
|
+
max: (value: number) => z.ZodNumber;
|
|
35
|
+
between: (min: number, max: number) => z.ZodNumber;
|
|
36
|
+
regex: (pattern: RegExp, message?: string) => z.ZodString;
|
|
37
|
+
ip: () => z.ZodEffects<z.ZodString, string, string>;
|
|
38
|
+
json: () => z.ZodEffects<z.ZodString, string, string>;
|
|
39
|
+
};
|
|
40
|
+
export declare function validate<T extends z.ZodTypeAny>(schema: T, data: unknown): {
|
|
41
|
+
success: true;
|
|
42
|
+
data: z.infer<T>;
|
|
43
|
+
} | {
|
|
44
|
+
success: false;
|
|
45
|
+
errors: Record<string, any>;
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as n}from"zod";var l={required:()=>n.string().min(1,"This field is required"),email:()=>n.string().email("Must be a valid email address"),string:(e,r)=>{let s=n.string();return e!==void 0&&(s=s.min(e)),r!==void 0&&(s=s.max(r)),s},number:(e,r)=>{let s=n.number();return e!==void 0&&(s=s.min(e)),r!==void 0&&(s=s.max(r)),s},integer:()=>n.number().int(),boolean:()=>n.boolean(),date:()=>n.coerce.date(),url:()=>n.string().url(),uuid:()=>n.string().uuid(),enum:e=>n.enum(e),array:e=>n.array(e),nullable:e=>e.nullable(),optional:e=>e.optional(),confirmed:(e="password")=>n.object({[e]:n.string(),[`${e}_confirmation`]:n.string()}).refine(r=>r[e]===r[`${e}_confirmation`],{message:"Confirmation does not match",path:[`${e}_confirmation`]}),min:e=>n.number().min(e),max:e=>n.number().max(e),between:(e,r)=>n.number().min(e).max(r),regex:(e,r)=>n.string().regex(e,r),ip:()=>n.string().refine(e=>{let r=e.split(".");return r.length!==4?!1:r.every(s=>{let i=Number(s);return Number.isInteger(i)&&i>=0&&i<=255})},{message:"Must be a valid IP address"}),json:()=>n.string().refine(e=>{try{return JSON.parse(e),!0}catch{return!1}},{message:"Must be valid JSON"})};function g(e,r){let s=e.safeParse(r);if(s.success)return{success:!0,data:s.data};let i={};for(let u of s.error.issues){let a=u.path.length>0?u.path:["_root"],t=i;for(let m=0;m<a.length-1;m++){let c=a[m];c in t||(t[c]={}),t=t[c]}let o=a[a.length-1];t[o]||(t[o]=[]),t[o].push(u.message)}return{success:!1,errors:i}}export{l as rules,g as validate,n as z};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelar Outgoing Webhooks
|
|
3
|
+
* Send event notifications to external URLs with retry logic.
|
|
4
|
+
*/
|
|
5
|
+
export interface WebhookEndpoint {
|
|
6
|
+
id: string;
|
|
7
|
+
userId?: string | number;
|
|
8
|
+
url: string;
|
|
9
|
+
events: string[];
|
|
10
|
+
secret: string;
|
|
11
|
+
active: boolean;
|
|
12
|
+
metadata?: Record<string, any>;
|
|
13
|
+
createdAt: number;
|
|
14
|
+
}
|
|
15
|
+
export interface WebhookDelivery {
|
|
16
|
+
id: string;
|
|
17
|
+
webhookId: string;
|
|
18
|
+
event: string;
|
|
19
|
+
payload: Record<string, any>;
|
|
20
|
+
status: 'pending' | 'success' | 'failed';
|
|
21
|
+
statusCode?: number;
|
|
22
|
+
response?: string;
|
|
23
|
+
attempts: number;
|
|
24
|
+
maxAttempts: number;
|
|
25
|
+
nextRetryAt?: number;
|
|
26
|
+
deliveredAt?: number;
|
|
27
|
+
createdAt: number;
|
|
28
|
+
}
|
|
29
|
+
export interface WebhookConfig {
|
|
30
|
+
driver: 'database' | 'memory';
|
|
31
|
+
table?: string;
|
|
32
|
+
deliveryTable?: string;
|
|
33
|
+
maxAttempts?: number;
|
|
34
|
+
retryDelays?: number[];
|
|
35
|
+
signatureHeader?: string;
|
|
36
|
+
timeout?: number;
|
|
37
|
+
}
|
|
38
|
+
declare class WebhookManager {
|
|
39
|
+
private config;
|
|
40
|
+
private endpoints;
|
|
41
|
+
private deliveries;
|
|
42
|
+
configure(config: WebhookConfig): void;
|
|
43
|
+
/** Register a webhook endpoint */
|
|
44
|
+
register(endpoint: Omit<WebhookEndpoint, 'id' | 'secret' | 'createdAt'>): Promise<WebhookEndpoint>;
|
|
45
|
+
/** Dispatch an event to all matching endpoints */
|
|
46
|
+
dispatch(event: string, payload: Record<string, any>): Promise<void>;
|
|
47
|
+
/** Deliver a single webhook (with retry) */
|
|
48
|
+
deliver(deliveryId: string): Promise<boolean>;
|
|
49
|
+
/** Sign a payload */
|
|
50
|
+
sign(payload: string, secret: string): string;
|
|
51
|
+
/** List endpoints */
|
|
52
|
+
listEndpoints(userId?: string | number): Promise<WebhookEndpoint[]>;
|
|
53
|
+
/** List deliveries with filtering */
|
|
54
|
+
listDeliveries(filter?: {
|
|
55
|
+
webhookId?: string;
|
|
56
|
+
event?: string;
|
|
57
|
+
status?: string;
|
|
58
|
+
limit?: number;
|
|
59
|
+
}): Promise<WebhookDelivery[]>;
|
|
60
|
+
/** Retry a failed delivery */
|
|
61
|
+
retryDelivery(deliveryId: string): Promise<boolean>;
|
|
62
|
+
/** Delete an endpoint */
|
|
63
|
+
deleteEndpoint(id: string): Promise<boolean>;
|
|
64
|
+
}
|
|
65
|
+
export declare const Webhooks: WebhookManager;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var y=Object.defineProperty;var f=(d,t)=>()=>(d&&(t=d(d=0)),t);var v=(d,t)=>{for(var e in t)y(d,e,{get:t[e],enumerable:!0})};function u(d,t){let e=Symbol.for(d),n=globalThis;return n[e]||(n[e]=t()),n[e]}var p=f(()=>{"use strict"});var w={};v(w,{Connection:()=>C});var h,C,b=f(()=>{"use strict";p();h=class{connections=new Map;config=null;defaultName="default";configure(t){this.config=t,this.defaultName=t.default}async connection(t){let e=t??this.defaultName;if(this.connections.has(e))return this.connections.get(e).drizzle;if(!this.config)throw new Error("Database not configured. Call Connection.configure() first, or register DatabaseServiceProvider.");let n=this.config.connections[e];if(!n)throw new Error(`Database connection "${e}" is not defined in configuration.`);let i=await this.createConnection(n);return this.connections.set(e,i),i.drizzle}async rawClient(t){let e=t??this.defaultName;return await this.connection(e),this.connections.get(e).rawClient}async raw(t,e=[],n){let i=await this.connection(n),r=this.getConfig(n);switch(r.driver){case"sqlite":{let s=await this.rawClient(n),o=e.map(c=>typeof c=="boolean"?c?1:0:c instanceof Date?c.toISOString():c),a=s.prepare(t),l=t.trimStart().toUpperCase();return l.startsWith("SELECT")||l.startsWith("PRAGMA")||l.startsWith("WITH")?a.all(...o):a.run(...o)}case"postgres":return(await this.rawClient(n))(t,...e);case"mysql":{let s=await this.rawClient(n),[o]=await s.execute(t,e);return o}default:throw new Error(`Unsupported driver: ${r.driver}`)}}getDriver(t){return this.getConfig(t).driver}getConfig(t){let e=t??this.defaultName;if(!this.config)throw new Error("Database not configured.");let n=this.config.connections[e];if(!n)throw new Error(`Database connection "${e}" is not defined.`);return n}async disconnect(t){if(t){let e=this.connections.get(t);e&&(await this.closeConnection(e),this.connections.delete(t))}else{for(let[e,n]of this.connections)await this.closeConnection(n);this.connections.clear()}}isConnected(t){return this.connections.has(t??this.defaultName)}async transaction(t,e){let n=this.getConfig(e),i=await this.rawClient(e);switch(n.driver){case"sqlite":{i.exec("BEGIN");try{let r=await t();return i.exec("COMMIT"),r}catch(r){throw i.exec("ROLLBACK"),r}}case"postgres":{await i`BEGIN`;try{let r=await t();return await i`COMMIT`,r}catch(r){throw await i`ROLLBACK`,r}}case"mysql":{let r=await i.getConnection();await r.beginTransaction();try{let s=await t();return await r.commit(),r.release(),s}catch(s){throw await r.rollback(),r.release(),s}}default:throw new Error(`Unsupported driver: ${n.driver}`)}}async createConnection(t){switch(t.driver){case"sqlite":return this.createSQLiteConnection(t);case"postgres":return this.createPostgresConnection(t);case"mysql":return this.createMySQLConnection(t);default:throw new Error(`Unsupported database driver: ${t.driver}`)}}async createSQLiteConnection(t){let e=t.filename??t.database??":memory:";try{let n=(await import("better-sqlite3")).default,{drizzle:i}=await import("drizzle-orm/better-sqlite3"),r=new n(e);return r.pragma("journal_mode = WAL"),r.pragma("foreign_keys = ON"),{drizzle:i(r),config:t,rawClient:r}}catch(n){let i;try{i=(await new Function("mod","return import(mod)")("node:sqlite")).DatabaseSync}catch{throw new Error(`No SQLite driver available. Install better-sqlite3 (npm install better-sqlite3) or use Node.js v22+ which includes built-in SQLite support. Original error: ${n instanceof Error?n.message:String(n)}`)}let r=new i(e);r.exec("PRAGMA journal_mode = WAL"),r.exec("PRAGMA foreign_keys = ON");let s={prepare(a){let l=r.prepare(a);return{all(...c){return l.all(...c)},run(...c){return l.run(...c)},get(...c){return l.get(...c)}}},exec(a){r.exec(a)},pragma(a){return r.prepare(`PRAGMA ${a}`).all()},close(){r.close()}},o;try{let{drizzle:a}=await import("drizzle-orm/better-sqlite3");o=a(s)}catch{o=s}return{drizzle:o,config:t,rawClient:s}}}async createPostgresConnection(t){let e=(await import("postgres")).default,{drizzle:n}=await import("drizzle-orm/postgres-js"),i=t.url??`postgres://${t.user}:${t.password}@${t.host??"localhost"}:${t.port??5432}/${t.database}`,r=e(i);return{drizzle:n(r),config:t,rawClient:r}}async createMySQLConnection(t){let e=await import("mysql2/promise"),{drizzle:n}=await import("drizzle-orm/mysql2"),i=e.createPool({host:t.host??"localhost",port:t.port??3306,database:t.database,user:t.user,password:t.password,uri:t.url});return{drizzle:n(i),config:t,rawClient:i}}async closeConnection(t){try{switch(t.config.driver){case"sqlite":t.rawClient.close();break;case"postgres":await t.rawClient.end();break;case"mysql":await t.rawClient.end();break}}catch{}}},C=u("svelar.connection",()=>new h)});p();import{randomUUID as g}from"crypto";import{createHmac as D}from"crypto";var m=class{config={driver:"memory",maxAttempts:5,retryDelays:[1,10,60,300,3600],signatureHeader:"X-Webhook-Signature",timeout:1e4};endpoints=[];deliveries=[];configure(t){this.config={...this.config,...t}}async register(t){let e=g(),n={...t,id:g(),secret:e,createdAt:Date.now()};if(this.config.driver==="memory")this.endpoints.push(n);else if(this.config.driver==="database")try{let{Connection:i}=await Promise.resolve().then(()=>(b(),w));await i.connection()}catch{this.endpoints.push(n)}return n}async dispatch(t,e){for(let n of this.endpoints){if(!n.active||!(n.events.includes("*")||n.events.includes(t)))continue;let r={id:g(),webhookId:n.id,event:t,payload:e,status:"pending",attempts:0,maxAttempts:this.config.maxAttempts||5,createdAt:Date.now()};this.deliveries.push(r),await this.deliver(r.id)}}async deliver(t){let e=this.deliveries.find(i=>i.id===t);if(!e)return!1;let n=this.endpoints.find(i=>i.id===e.webhookId);if(!n)return!1;e.attempts++;try{let i=this.sign(JSON.stringify(e.payload),n.secret),r=new AbortController,s=setTimeout(()=>r.abort(),this.config.timeout||1e4),o=await fetch(n.url,{method:"POST",headers:{"Content-Type":"application/json",[this.config.signatureHeader||"X-Webhook-Signature"]:i,"X-Webhook-Event":e.event,"X-Webhook-Delivery":t},body:JSON.stringify(e.payload),signal:r.signal});if(clearTimeout(s),e.statusCode=o.status,e.response=await o.text(),o.ok)return e.status="success",e.deliveredAt=Date.now(),!0;throw new Error(`HTTP ${o.status}: ${e.response.slice(0,100)}`)}catch(i){let r=i instanceof Error?i.message:"Unknown error";if(e.attempts<e.maxAttempts){let s=this.config.retryDelays?.[e.attempts-1]||60;e.nextRetryAt=Date.now()+s*1e3,e.status="pending"}else e.status="failed";return!1}}sign(t,e){return D("sha256",e).update(t).digest("hex")}async listEndpoints(t){let e=this.endpoints;return t!==void 0&&(e=e.filter(n=>n.userId===t)),e.map(n=>({...n}))}async listDeliveries(t){let e=[...this.deliveries];return t?.webhookId&&(e=e.filter(n=>n.webhookId===t.webhookId)),t?.event&&(e=e.filter(n=>n.event===t.event)),t?.status&&(e=e.filter(n=>n.status===t.status)),e.sort((n,i)=>i.createdAt-n.createdAt),e.slice(0,t?.limit||100)}async retryDelivery(t){let e=this.deliveries.find(n=>n.id===t);return e?(e.attempts=0,e.status="pending",e.nextRetryAt=void 0,this.deliver(t)):!1}async deleteEndpoint(t){let e=this.endpoints.findIndex(n=>n.id===t);return e===-1?!1:(this.endpoints.splice(e,1),!0)}},S=u("svelar.webhooks",()=>new m);export{S as Webhooks};
|