@spfn/auth 0.1.0-alpha.0 → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -12
  3. package/dist/api-BcQM4WKb.d.ts +45 -0
  4. package/dist/client.d.ts +2 -0
  5. package/dist/client.js +1 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/index.d.ts +57 -0
  8. package/dist/index.js +8966 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/lib/contracts/auth.d.ts +262 -0
  11. package/dist/lib/contracts/auth.js +2923 -0
  12. package/dist/lib/contracts/auth.js.map +1 -0
  13. package/dist/lib/contracts/index.d.ts +3 -0
  14. package/dist/lib/contracts/index.js +3162 -0
  15. package/dist/lib/contracts/index.js.map +1 -0
  16. package/dist/lib/contracts/invitation.d.ts +243 -0
  17. package/dist/lib/contracts/invitation.js +2883 -0
  18. package/dist/lib/contracts/invitation.js.map +1 -0
  19. package/dist/plugin.d.ts +12 -0
  20. package/dist/plugin.js +8949 -0
  21. package/dist/plugin.js.map +1 -0
  22. package/dist/server/entities/index.d.ts +10 -0
  23. package/dist/server/entities/index.js +399 -0
  24. package/dist/server/entities/index.js.map +1 -0
  25. package/dist/server/entities/invitations.d.ts +241 -0
  26. package/dist/server/entities/invitations.js +181 -0
  27. package/dist/server/entities/invitations.js.map +1 -0
  28. package/dist/server/entities/permissions.d.ts +196 -0
  29. package/dist/server/entities/permissions.js +44 -0
  30. package/dist/server/entities/permissions.js.map +1 -0
  31. package/dist/server/entities/role-permissions.d.ts +107 -0
  32. package/dist/server/entities/role-permissions.js +112 -0
  33. package/dist/server/entities/role-permissions.js.map +1 -0
  34. package/dist/server/entities/roles.d.ts +196 -0
  35. package/dist/server/entities/roles.js +45 -0
  36. package/dist/server/entities/roles.js.map +1 -0
  37. package/dist/server/entities/user-permissions.d.ts +163 -0
  38. package/dist/server/entities/user-permissions.js +191 -0
  39. package/dist/server/entities/user-permissions.js.map +1 -0
  40. package/dist/server/entities/user-public-keys.d.ts +227 -0
  41. package/dist/server/entities/user-public-keys.js +153 -0
  42. package/dist/server/entities/user-public-keys.js.map +1 -0
  43. package/dist/server/entities/user-social-accounts.d.ts +189 -0
  44. package/dist/server/entities/user-social-accounts.js +146 -0
  45. package/dist/server/entities/user-social-accounts.js.map +1 -0
  46. package/dist/server/entities/users.d.ts +235 -0
  47. package/dist/server/entities/users.js +113 -0
  48. package/dist/server/entities/users.js.map +1 -0
  49. package/dist/server/entities/verification-codes.d.ts +191 -0
  50. package/dist/server/entities/verification-codes.js +44 -0
  51. package/dist/server/entities/verification-codes.js.map +1 -0
  52. package/dist/server/routes/auth/index.d.ts +10 -0
  53. package/dist/server/routes/auth/index.js +4475 -0
  54. package/dist/server/routes/auth/index.js.map +1 -0
  55. package/dist/server/routes/index.d.ts +6 -0
  56. package/dist/server/routes/index.js +6352 -0
  57. package/dist/server/routes/index.js.map +1 -0
  58. package/dist/server/routes/invitations/index.d.ts +10 -0
  59. package/dist/server/routes/invitations/index.js +4209 -0
  60. package/dist/server/routes/invitations/index.js.map +1 -0
  61. package/dist/server.d.ts +1243 -0
  62. package/dist/server.js +2281 -0
  63. package/dist/server.js.map +1 -0
  64. package/migrations/0000_tired_gambit.sql +165 -0
  65. package/migrations/meta/0000_snapshot.json +1395 -0
  66. package/migrations/meta/_journal.json +13 -0
  67. package/package.json +32 -24
@@ -0,0 +1,235 @@
1
+ import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
+
3
+ /**
4
+ * @spfn/auth - Users Entity
5
+ *
6
+ * Main user table supporting multiple authentication methods
7
+ *
8
+ * Features:
9
+ * - Email or phone-based registration
10
+ * - Password authentication (bcrypt)
11
+ * - OAuth support (nullable passwordHash)
12
+ * - Role-based access control (RBAC)
13
+ * - Account status management
14
+ * - Email/phone verification
15
+ */
16
+ declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
17
+ name: "users";
18
+ schema: string;
19
+ columns: {
20
+ createdAt: drizzle_orm_pg_core.PgColumn<{
21
+ name: "created_at";
22
+ tableName: "users";
23
+ dataType: "date";
24
+ columnType: "PgTimestamp";
25
+ data: Date;
26
+ driverParam: string;
27
+ notNull: true;
28
+ hasDefault: true;
29
+ isPrimaryKey: false;
30
+ isAutoincrement: false;
31
+ hasRuntimeDefault: false;
32
+ enumValues: undefined;
33
+ baseColumn: never;
34
+ identity: undefined;
35
+ generated: undefined;
36
+ }, {}, {}>;
37
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
38
+ name: "updated_at";
39
+ tableName: "users";
40
+ dataType: "date";
41
+ columnType: "PgTimestamp";
42
+ data: Date;
43
+ driverParam: string;
44
+ notNull: true;
45
+ hasDefault: true;
46
+ isPrimaryKey: false;
47
+ isAutoincrement: false;
48
+ hasRuntimeDefault: false;
49
+ enumValues: undefined;
50
+ baseColumn: never;
51
+ identity: undefined;
52
+ generated: undefined;
53
+ }, {}, {}>;
54
+ id: drizzle_orm_pg_core.PgColumn<{
55
+ name: "id";
56
+ tableName: "users";
57
+ dataType: "number";
58
+ columnType: "PgBigSerial53";
59
+ data: number;
60
+ driverParam: number;
61
+ notNull: true;
62
+ hasDefault: true;
63
+ isPrimaryKey: true;
64
+ isAutoincrement: false;
65
+ hasRuntimeDefault: false;
66
+ enumValues: undefined;
67
+ baseColumn: never;
68
+ identity: undefined;
69
+ generated: undefined;
70
+ }, {}, {}>;
71
+ email: drizzle_orm_pg_core.PgColumn<{
72
+ name: "email";
73
+ tableName: "users";
74
+ dataType: "string";
75
+ columnType: "PgText";
76
+ data: string;
77
+ driverParam: string;
78
+ notNull: false;
79
+ hasDefault: false;
80
+ isPrimaryKey: false;
81
+ isAutoincrement: false;
82
+ hasRuntimeDefault: false;
83
+ enumValues: [string, ...string[]];
84
+ baseColumn: never;
85
+ identity: undefined;
86
+ generated: undefined;
87
+ }, {}, {}>;
88
+ phone: drizzle_orm_pg_core.PgColumn<{
89
+ name: "phone";
90
+ tableName: "users";
91
+ dataType: "string";
92
+ columnType: "PgText";
93
+ data: string;
94
+ driverParam: string;
95
+ notNull: false;
96
+ hasDefault: false;
97
+ isPrimaryKey: false;
98
+ isAutoincrement: false;
99
+ hasRuntimeDefault: false;
100
+ enumValues: [string, ...string[]];
101
+ baseColumn: never;
102
+ identity: undefined;
103
+ generated: undefined;
104
+ }, {}, {}>;
105
+ passwordHash: drizzle_orm_pg_core.PgColumn<{
106
+ name: "password_hash";
107
+ tableName: "users";
108
+ dataType: "string";
109
+ columnType: "PgText";
110
+ data: string;
111
+ driverParam: string;
112
+ notNull: false;
113
+ hasDefault: false;
114
+ isPrimaryKey: false;
115
+ isAutoincrement: false;
116
+ hasRuntimeDefault: false;
117
+ enumValues: [string, ...string[]];
118
+ baseColumn: never;
119
+ identity: undefined;
120
+ generated: undefined;
121
+ }, {}, {}>;
122
+ passwordChangeRequired: drizzle_orm_pg_core.PgColumn<{
123
+ name: "password_change_required";
124
+ tableName: "users";
125
+ dataType: "boolean";
126
+ columnType: "PgBoolean";
127
+ data: boolean;
128
+ driverParam: boolean;
129
+ notNull: true;
130
+ hasDefault: true;
131
+ isPrimaryKey: false;
132
+ isAutoincrement: false;
133
+ hasRuntimeDefault: false;
134
+ enumValues: undefined;
135
+ baseColumn: never;
136
+ identity: undefined;
137
+ generated: undefined;
138
+ }, {}, {}>;
139
+ roleId: drizzle_orm_pg_core.PgColumn<{
140
+ name: "role_id";
141
+ tableName: "users";
142
+ dataType: "number";
143
+ columnType: "PgBigInt53";
144
+ data: number;
145
+ driverParam: string | number;
146
+ notNull: true;
147
+ hasDefault: false;
148
+ isPrimaryKey: false;
149
+ isAutoincrement: false;
150
+ hasRuntimeDefault: false;
151
+ enumValues: undefined;
152
+ baseColumn: never;
153
+ identity: undefined;
154
+ generated: undefined;
155
+ }, {}, {}>;
156
+ status: drizzle_orm_pg_core.PgColumn<{
157
+ name: "status";
158
+ tableName: "users";
159
+ dataType: "string";
160
+ columnType: "PgText";
161
+ data: "active" | "inactive" | "suspended";
162
+ driverParam: string;
163
+ notNull: true;
164
+ hasDefault: true;
165
+ isPrimaryKey: false;
166
+ isAutoincrement: false;
167
+ hasRuntimeDefault: false;
168
+ enumValues: ["active", "inactive", "suspended"];
169
+ baseColumn: never;
170
+ identity: undefined;
171
+ generated: undefined;
172
+ }, {}, {}>;
173
+ emailVerifiedAt: drizzle_orm_pg_core.PgColumn<{
174
+ name: "email_verified_at";
175
+ tableName: "users";
176
+ dataType: "date";
177
+ columnType: "PgTimestamp";
178
+ data: Date;
179
+ driverParam: string;
180
+ notNull: false;
181
+ hasDefault: false;
182
+ isPrimaryKey: false;
183
+ isAutoincrement: false;
184
+ hasRuntimeDefault: false;
185
+ enumValues: undefined;
186
+ baseColumn: never;
187
+ identity: undefined;
188
+ generated: undefined;
189
+ }, {}, {}>;
190
+ phoneVerifiedAt: drizzle_orm_pg_core.PgColumn<{
191
+ name: "phone_verified_at";
192
+ tableName: "users";
193
+ dataType: "date";
194
+ columnType: "PgTimestamp";
195
+ data: Date;
196
+ driverParam: string;
197
+ notNull: false;
198
+ hasDefault: false;
199
+ isPrimaryKey: false;
200
+ isAutoincrement: false;
201
+ hasRuntimeDefault: false;
202
+ enumValues: undefined;
203
+ baseColumn: never;
204
+ identity: undefined;
205
+ generated: undefined;
206
+ }, {}, {}>;
207
+ lastLoginAt: drizzle_orm_pg_core.PgColumn<{
208
+ name: "last_login_at";
209
+ tableName: "users";
210
+ dataType: "date";
211
+ columnType: "PgTimestamp";
212
+ data: Date;
213
+ driverParam: string;
214
+ notNull: false;
215
+ hasDefault: false;
216
+ isPrimaryKey: false;
217
+ isAutoincrement: false;
218
+ hasRuntimeDefault: false;
219
+ enumValues: undefined;
220
+ baseColumn: never;
221
+ identity: undefined;
222
+ generated: undefined;
223
+ }, {}, {}>;
224
+ };
225
+ dialect: "pg";
226
+ }>;
227
+ type User = typeof users.$inferSelect;
228
+ type NewUser = typeof users.$inferInsert;
229
+ type UserStatus = 'active' | 'inactive' | 'suspended';
230
+ type UserWithVerification = User & {
231
+ isEmailVerified: boolean;
232
+ isPhoneVerified: boolean;
233
+ };
234
+
235
+ export { type NewUser, type User, type UserStatus, type UserWithVerification, users };
@@ -0,0 +1,113 @@
1
+ // src/server/entities/users.ts
2
+ import { text as text2, timestamp, check, boolean as boolean2, bigint, index as index2 } from "drizzle-orm/pg-core";
3
+ import { id as id2, timestamps as timestamps2, createFunctionSchema as createFunctionSchema2 } from "@spfn/core/db";
4
+ import { sql } from "drizzle-orm";
5
+
6
+ // src/server/entities/roles.ts
7
+ import { text, boolean, integer, index } from "drizzle-orm/pg-core";
8
+ import { id, timestamps, createFunctionSchema } from "@spfn/core/db";
9
+ var schema = createFunctionSchema("@spfn/auth");
10
+ var roles = schema.table(
11
+ "roles",
12
+ {
13
+ // Primary key
14
+ id: id(),
15
+ // Role identifier (used in code, e.g., 'admin', 'editor')
16
+ // Must be unique, lowercase, kebab-case recommended
17
+ name: text("name").notNull().unique(),
18
+ // Display name for UI (e.g., 'Administrator', 'Content Editor')
19
+ displayName: text("display_name").notNull(),
20
+ // Role description
21
+ description: text("description"),
22
+ // Built-in role flag
23
+ // true: Core package roles (user, admin, superadmin) - cannot be deleted
24
+ // false: Custom or preset roles - can be deleted
25
+ isBuiltin: boolean("is_builtin").notNull().default(false),
26
+ // System role flag
27
+ // true: Defined in code (builtin or preset) - deletion restricted
28
+ // false: Runtime created custom role - fully manageable
29
+ isSystem: boolean("is_system").notNull().default(false),
30
+ // Active status
31
+ // false: Deactivated role (users cannot be assigned)
32
+ isActive: boolean("is_active").notNull().default(true),
33
+ // Priority level (higher = more privileged)
34
+ // superadmin: 100, admin: 80, user: 10
35
+ // Used for role hierarchy and conflict resolution
36
+ priority: integer("priority").notNull().default(10),
37
+ ...timestamps()
38
+ },
39
+ (table) => [
40
+ index("roles_name_idx").on(table.name),
41
+ index("roles_is_system_idx").on(table.isSystem),
42
+ index("roles_is_active_idx").on(table.isActive),
43
+ index("roles_is_builtin_idx").on(table.isBuiltin),
44
+ index("roles_priority_idx").on(table.priority)
45
+ ]
46
+ );
47
+
48
+ // src/server/entities/users.ts
49
+ var schema2 = createFunctionSchema2("@spfn/auth");
50
+ var users = schema2.table(
51
+ "users",
52
+ {
53
+ // Identity
54
+ id: id2(),
55
+ // Email address (unique identifier)
56
+ // Used for: login, password reset, notifications
57
+ email: text2("email").unique(),
58
+ // Phone number in E.164 international format
59
+ // Format: +[country code][number] (e.g., +821012345678)
60
+ // Used for: SMS login, 2FA, notifications
61
+ phone: text2("phone").unique(),
62
+ // Authentication
63
+ // Bcrypt password hash ($2b$10$[salt][hash], 60 chars)
64
+ // Nullable to support OAuth-only accounts
65
+ passwordHash: text2("password_hash"),
66
+ // Force password change on next login
67
+ // Use cases: initial setup, security breach, policy violation
68
+ passwordChangeRequired: boolean2("password_change_required").notNull().default(false),
69
+ // Authorization (Role-Based Access Control)
70
+ // Foreign key to roles table
71
+ // References built-in roles: user (default), admin, superadmin
72
+ // Can also reference custom roles created at runtime
73
+ roleId: bigint("role_id", { mode: "number" }).references(() => roles.id).notNull(),
74
+ // Account status
75
+ // - active: Normal operation (default)
76
+ // - inactive: Deactivated (user request, dormant)
77
+ // - suspended: Locked (security incident, ToS violation)
78
+ status: text2(
79
+ "status",
80
+ {
81
+ enum: ["active", "inactive", "suspended"]
82
+ }
83
+ ).notNull().default("active"),
84
+ // Verification timestamps
85
+ // null = unverified, timestamp = verified at this time
86
+ // Email verification (via verification code or magic link)
87
+ emailVerifiedAt: timestamp("email_verified_at", { withTimezone: true }),
88
+ // Phone verification (via SMS OTP)
89
+ phoneVerifiedAt: timestamp("phone_verified_at", { withTimezone: true }),
90
+ // Metadata
91
+ // Last successful login timestamp
92
+ // Used for: security auditing, dormant account detection
93
+ lastLoginAt: timestamp("last_login_at", { withTimezone: true }),
94
+ ...timestamps2()
95
+ },
96
+ (table) => [
97
+ // Database constraints
98
+ // Ensure at least one identifier exists (email OR phone)
99
+ check(
100
+ "email_or_phone_check",
101
+ sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`
102
+ ),
103
+ // Indexes for query optimization
104
+ index2("users_email_idx").on(table.email),
105
+ index2("users_phone_idx").on(table.phone),
106
+ index2("users_status_idx").on(table.status),
107
+ index2("users_role_id_idx").on(table.roleId)
108
+ ]
109
+ );
110
+ export {
111
+ users
112
+ };
113
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/entities/users.ts","../../../src/server/entities/roles.ts"],"sourcesContent":["/**\n * @spfn/auth - Users Entity\n *\n * Main user table supporting multiple authentication methods\n *\n * Features:\n * - Email or phone-based registration\n * - Password authentication (bcrypt)\n * - OAuth support (nullable passwordHash)\n * - Role-based access control (RBAC)\n * - Account status management\n * - Email/phone verification\n */\n\nimport { text, timestamp, check, boolean, bigint, index } from 'drizzle-orm/pg-core';\nimport { id, timestamps, createFunctionSchema } from '@spfn/core/db';\nimport { sql } from 'drizzle-orm';\nimport { roles } from './roles';\n\nconst schema = createFunctionSchema('@spfn/auth');\n\nexport const users = schema.table('users',\n {\n // Identity\n id: id(),\n\n // Email address (unique identifier)\n // Used for: login, password reset, notifications\n email: text('email').unique(),\n\n // Phone number in E.164 international format\n // Format: +[country code][number] (e.g., +821012345678)\n // Used for: SMS login, 2FA, notifications\n phone: text('phone').unique(),\n\n // Authentication\n // Bcrypt password hash ($2b$10$[salt][hash], 60 chars)\n // Nullable to support OAuth-only accounts\n passwordHash: text('password_hash'),\n\n // Force password change on next login\n // Use cases: initial setup, security breach, policy violation\n passwordChangeRequired: boolean('password_change_required').notNull().default(false),\n\n // Authorization (Role-Based Access Control)\n // Foreign key to roles table\n // References built-in roles: user (default), admin, superadmin\n // Can also reference custom roles created at runtime\n roleId: bigint('role_id', { mode: 'number' })\n .references(() => roles.id)\n .notNull(),\n\n // Account status\n // - active: Normal operation (default)\n // - inactive: Deactivated (user request, dormant)\n // - suspended: Locked (security incident, ToS violation)\n status: text(\n 'status',\n {\n enum: ['active', 'inactive', 'suspended']\n }\n ).notNull().default('active'),\n\n // Verification timestamps\n // null = unverified, timestamp = verified at this time\n // Email verification (via verification code or magic link)\n emailVerifiedAt: timestamp('email_verified_at', { withTimezone: true }),\n\n // Phone verification (via SMS OTP)\n phoneVerifiedAt: timestamp('phone_verified_at', { withTimezone: true }),\n\n // Metadata\n // Last successful login timestamp\n // Used for: security auditing, dormant account detection\n lastLoginAt: timestamp('last_login_at', { withTimezone: true }),\n\n ...timestamps(),\n },\n (table) => [\n // Database constraints\n // Ensure at least one identifier exists (email OR phone)\n check(\n 'email_or_phone_check',\n sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`\n ),\n\n // Indexes for query optimization\n index('users_email_idx').on(table.email),\n index('users_phone_idx').on(table.phone),\n index('users_status_idx').on(table.status),\n index('users_role_id_idx').on(table.roleId),\n ]\n);\n\n// Type exports\nexport type User = typeof users.$inferSelect;\nexport type NewUser = typeof users.$inferInsert;\nexport type UserStatus = 'active' | 'inactive' | 'suspended';\n\n// Helper type with computed verification status\nexport type UserWithVerification = User &\n{\n isEmailVerified: boolean;\n isPhoneVerified: boolean;\n};","/**\n * @spfn/auth - Roles Entity\n *\n * Role-based access control (RBAC) roles table\n *\n * Features:\n * - Built-in roles (user, admin, superadmin) - cannot be deleted\n * - System roles (preset roles) - can be deactivated\n * - Custom roles (runtime created) - fully manageable\n * - Priority-based hierarchy\n */\n\nimport { text, boolean, integer, index } from 'drizzle-orm/pg-core';\nimport { id, timestamps, createFunctionSchema } from '@spfn/core/db';\n\nconst schema = createFunctionSchema('@spfn/auth');\n\nexport const roles = schema.table('roles',\n {\n // Primary key\n id: id(),\n\n // Role identifier (used in code, e.g., 'admin', 'editor')\n // Must be unique, lowercase, kebab-case recommended\n name: text('name').notNull().unique(),\n\n // Display name for UI (e.g., 'Administrator', 'Content Editor')\n displayName: text('display_name').notNull(),\n\n // Role description\n description: text('description'),\n\n // Built-in role flag\n // true: Core package roles (user, admin, superadmin) - cannot be deleted\n // false: Custom or preset roles - can be deleted\n isBuiltin: boolean('is_builtin').notNull().default(false),\n\n // System role flag\n // true: Defined in code (builtin or preset) - deletion restricted\n // false: Runtime created custom role - fully manageable\n isSystem: boolean('is_system').notNull().default(false),\n\n // Active status\n // false: Deactivated role (users cannot be assigned)\n isActive: boolean('is_active').notNull().default(true),\n\n // Priority level (higher = more privileged)\n // superadmin: 100, admin: 80, user: 10\n // Used for role hierarchy and conflict resolution\n priority: integer('priority').notNull().default(10),\n\n ...timestamps(),\n },\n (table) => [\n index('roles_name_idx').on(table.name),\n index('roles_is_system_idx').on(table.isSystem),\n index('roles_is_active_idx').on(table.isActive),\n index('roles_is_builtin_idx').on(table.isBuiltin),\n index('roles_priority_idx').on(table.priority),\n ]\n);\n\n// Type exports\nexport type RoleEntity = typeof roles.$inferSelect;\nexport type NewRoleEntity = typeof roles.$inferInsert;\n\n// Legacy alias for backward compatibility\nexport type Role = RoleEntity;\nexport type NewRole = NewRoleEntity;"],"mappings":"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","names":["text","boolean","index","id","timestamps","createFunctionSchema","schema","createFunctionSchema","id","text","boolean","timestamps","index"]}
@@ -0,0 +1,191 @@
1
+ import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
+
3
+ /**
4
+ * @spfn/auth - Verification Codes Entity
5
+ *
6
+ * Stores verification codes for email and phone verification
7
+ * Codes expire after a configurable time period
8
+ */
9
+ declare const verificationCodes: drizzle_orm_pg_core.PgTableWithColumns<{
10
+ name: "verification_codes";
11
+ schema: string;
12
+ columns: {
13
+ createdAt: drizzle_orm_pg_core.PgColumn<{
14
+ name: "created_at";
15
+ tableName: "verification_codes";
16
+ dataType: "date";
17
+ columnType: "PgTimestamp";
18
+ data: Date;
19
+ driverParam: string;
20
+ notNull: true;
21
+ hasDefault: true;
22
+ isPrimaryKey: false;
23
+ isAutoincrement: false;
24
+ hasRuntimeDefault: false;
25
+ enumValues: undefined;
26
+ baseColumn: never;
27
+ identity: undefined;
28
+ generated: undefined;
29
+ }, {}, {}>;
30
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
31
+ name: "updated_at";
32
+ tableName: "verification_codes";
33
+ dataType: "date";
34
+ columnType: "PgTimestamp";
35
+ data: Date;
36
+ driverParam: string;
37
+ notNull: true;
38
+ hasDefault: true;
39
+ isPrimaryKey: false;
40
+ isAutoincrement: false;
41
+ hasRuntimeDefault: false;
42
+ enumValues: undefined;
43
+ baseColumn: never;
44
+ identity: undefined;
45
+ generated: undefined;
46
+ }, {}, {}>;
47
+ id: drizzle_orm_pg_core.PgColumn<{
48
+ name: "id";
49
+ tableName: "verification_codes";
50
+ dataType: "number";
51
+ columnType: "PgBigSerial53";
52
+ data: number;
53
+ driverParam: number;
54
+ notNull: true;
55
+ hasDefault: true;
56
+ isPrimaryKey: true;
57
+ isAutoincrement: false;
58
+ hasRuntimeDefault: false;
59
+ enumValues: undefined;
60
+ baseColumn: never;
61
+ identity: undefined;
62
+ generated: undefined;
63
+ }, {}, {}>;
64
+ target: drizzle_orm_pg_core.PgColumn<{
65
+ name: "target";
66
+ tableName: "verification_codes";
67
+ dataType: "string";
68
+ columnType: "PgText";
69
+ data: string;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: [string, ...string[]];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {}>;
81
+ targetType: drizzle_orm_pg_core.PgColumn<{
82
+ name: "target_type";
83
+ tableName: "verification_codes";
84
+ dataType: "string";
85
+ columnType: "PgText";
86
+ data: "email" | "phone";
87
+ driverParam: string;
88
+ notNull: true;
89
+ hasDefault: false;
90
+ isPrimaryKey: false;
91
+ isAutoincrement: false;
92
+ hasRuntimeDefault: false;
93
+ enumValues: ["email", "phone"];
94
+ baseColumn: never;
95
+ identity: undefined;
96
+ generated: undefined;
97
+ }, {}, {}>;
98
+ code: drizzle_orm_pg_core.PgColumn<{
99
+ name: "code";
100
+ tableName: "verification_codes";
101
+ dataType: "string";
102
+ columnType: "PgText";
103
+ data: string;
104
+ driverParam: string;
105
+ notNull: true;
106
+ hasDefault: false;
107
+ isPrimaryKey: false;
108
+ isAutoincrement: false;
109
+ hasRuntimeDefault: false;
110
+ enumValues: [string, ...string[]];
111
+ baseColumn: never;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }, {}, {}>;
115
+ purpose: drizzle_orm_pg_core.PgColumn<{
116
+ name: "purpose";
117
+ tableName: "verification_codes";
118
+ dataType: "string";
119
+ columnType: "PgText";
120
+ data: "registration" | "login" | "password_reset" | "email_change" | "phone_change";
121
+ driverParam: string;
122
+ notNull: true;
123
+ hasDefault: false;
124
+ isPrimaryKey: false;
125
+ isAutoincrement: false;
126
+ hasRuntimeDefault: false;
127
+ enumValues: ["registration", "login", "password_reset", "email_change", "phone_change"];
128
+ baseColumn: never;
129
+ identity: undefined;
130
+ generated: undefined;
131
+ }, {}, {}>;
132
+ expiresAt: drizzle_orm_pg_core.PgColumn<{
133
+ name: "expires_at";
134
+ tableName: "verification_codes";
135
+ dataType: "date";
136
+ columnType: "PgTimestamp";
137
+ data: Date;
138
+ driverParam: string;
139
+ notNull: true;
140
+ hasDefault: false;
141
+ isPrimaryKey: false;
142
+ isAutoincrement: false;
143
+ hasRuntimeDefault: false;
144
+ enumValues: undefined;
145
+ baseColumn: never;
146
+ identity: undefined;
147
+ generated: undefined;
148
+ }, {}, {}>;
149
+ usedAt: drizzle_orm_pg_core.PgColumn<{
150
+ name: "used_at";
151
+ tableName: "verification_codes";
152
+ dataType: "date";
153
+ columnType: "PgTimestamp";
154
+ data: Date;
155
+ driverParam: string;
156
+ notNull: false;
157
+ hasDefault: false;
158
+ isPrimaryKey: false;
159
+ isAutoincrement: false;
160
+ hasRuntimeDefault: false;
161
+ enumValues: undefined;
162
+ baseColumn: never;
163
+ identity: undefined;
164
+ generated: undefined;
165
+ }, {}, {}>;
166
+ attempts: drizzle_orm_pg_core.PgColumn<{
167
+ name: "attempts";
168
+ tableName: "verification_codes";
169
+ dataType: "string";
170
+ columnType: "PgText";
171
+ data: string;
172
+ driverParam: string;
173
+ notNull: true;
174
+ hasDefault: true;
175
+ isPrimaryKey: false;
176
+ isAutoincrement: false;
177
+ hasRuntimeDefault: false;
178
+ enumValues: [string, ...string[]];
179
+ baseColumn: never;
180
+ identity: undefined;
181
+ generated: undefined;
182
+ }, {}, {}>;
183
+ };
184
+ dialect: "pg";
185
+ }>;
186
+ type VerificationCode = typeof verificationCodes.$inferSelect;
187
+ type NewVerificationCode = typeof verificationCodes.$inferInsert;
188
+ type VerificationTargetType = 'email' | 'phone';
189
+ type VerificationPurpose = 'registration' | 'login' | 'password_reset' | 'email_change' | 'phone_change';
190
+
191
+ export { type NewVerificationCode, type VerificationCode, type VerificationPurpose, type VerificationTargetType, verificationCodes };
@@ -0,0 +1,44 @@
1
+ // src/server/entities/verification-codes.ts
2
+ import { text, timestamp, index } from "drizzle-orm/pg-core";
3
+ import { id, timestamps, createFunctionSchema } from "@spfn/core/db";
4
+ var schema = createFunctionSchema("@spfn/auth");
5
+ var verificationCodes = schema.table(
6
+ "verification_codes",
7
+ {
8
+ id: id(),
9
+ // Target (email or phone)
10
+ target: text("target").notNull(),
11
+ // Email address or E.164 phone number
12
+ targetType: text(
13
+ "target_type",
14
+ {
15
+ enum: ["email", "phone"]
16
+ }
17
+ ).notNull(),
18
+ // Code
19
+ code: text("code").notNull(),
20
+ // 6-digit code by default (configurable)
21
+ // Purpose
22
+ purpose: text(
23
+ "purpose",
24
+ {
25
+ enum: ["registration", "login", "password_reset", "email_change", "phone_change"]
26
+ }
27
+ ).notNull(),
28
+ // Expiry
29
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
30
+ // Usage tracking
31
+ usedAt: timestamp("used_at", { withTimezone: true }),
32
+ attempts: text("attempts").notNull().default("0"),
33
+ // Track failed verification attempts
34
+ ...timestamps()
35
+ },
36
+ (table) => [
37
+ // Index for quick lookup by target and purpose
38
+ index("target_purpose_idx").on(table.target, table.purpose, table.expiresAt)
39
+ ]
40
+ );
41
+ export {
42
+ verificationCodes
43
+ };
44
+ //# sourceMappingURL=verification-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/entities/verification-codes.ts"],"sourcesContent":["/**\n * @spfn/auth - Verification Codes Entity\n *\n * Stores verification codes for email and phone verification\n * Codes expire after a configurable time period\n */\n\nimport { text, timestamp, index } from 'drizzle-orm/pg-core';\nimport { id, timestamps, createFunctionSchema } from '@spfn/core/db';\n\nconst schema = createFunctionSchema('@spfn/auth');\n\nexport const verificationCodes = schema.table('verification_codes',\n {\n id: id(),\n\n // Target (email or phone)\n target: text('target').notNull(), // Email address or E.164 phone number\n targetType: text(\n 'target_type',\n {\n enum: ['email', 'phone']\n }\n ).notNull(),\n\n // Code\n code: text('code').notNull(), // 6-digit code by default (configurable)\n\n // Purpose\n purpose: text(\n 'purpose',\n {\n enum: ['registration', 'login', 'password_reset', 'email_change', 'phone_change']\n }\n ).notNull(),\n\n // Expiry\n expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),\n\n // Usage tracking\n usedAt: timestamp('used_at', { withTimezone: true }),\n attempts: text('attempts').notNull().default('0'), // Track failed verification attempts\n\n ...timestamps(),\n },\n (table) => [\n // Index for quick lookup by target and purpose\n index('target_purpose_idx')\n .on(table.target, table.purpose, table.expiresAt),\n ]\n);\n\n// Type exports\nexport type VerificationCode = typeof verificationCodes.$inferSelect;\nexport type NewVerificationCode = typeof verificationCodes.$inferInsert;\nexport type VerificationTargetType = 'email' | 'phone';\nexport type VerificationPurpose = 'registration' | 'login' | 'password_reset' | 'email_change' | 'phone_change';"],"mappings":";AAOA,SAAS,MAAM,WAAW,aAAa;AACvC,SAAS,IAAI,YAAY,4BAA4B;AAErD,IAAM,SAAS,qBAAqB,YAAY;AAEzC,IAAM,oBAAoB,OAAO;AAAA,EAAM;AAAA,EAC1C;AAAA,IACI,IAAI,GAAG;AAAA;AAAA,IAGP,QAAQ,KAAK,QAAQ,EAAE,QAAQ;AAAA;AAAA,IAC/B,YAAY;AAAA,MACR;AAAA,MACA;AAAA,QACI,MAAM,CAAC,SAAS,OAAO;AAAA,MAC3B;AAAA,IACJ,EAAE,QAAQ;AAAA;AAAA,IAGV,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA;AAAA;AAAA,IAG3B,SAAS;AAAA,MACL;AAAA,MACA;AAAA,QACI,MAAM,CAAC,gBAAgB,SAAS,kBAAkB,gBAAgB,cAAc;AAAA,MACpF;AAAA,IACJ,EAAE,QAAQ;AAAA;AAAA,IAGV,WAAW,UAAU,cAAc,EAAE,cAAc,KAAK,CAAC,EAAE,QAAQ;AAAA;AAAA,IAGnE,QAAQ,UAAU,WAAW,EAAE,cAAc,KAAK,CAAC;AAAA,IACnD,UAAU,KAAK,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG;AAAA;AAAA,IAEhD,GAAG,WAAW;AAAA,EAClB;AAAA,EACA,CAAC,UAAU;AAAA;AAAA,IAEP,MAAM,oBAAoB,EACrB,GAAG,MAAM,QAAQ,MAAM,SAAS,MAAM,SAAS;AAAA,EACxD;AACJ;","names":[]}
@@ -0,0 +1,10 @@
1
+ import * as _spfn_core_route from '@spfn/core/route';
2
+
3
+ /**
4
+ * @spfn/auth - Auth Routes
5
+ *
6
+ * Thin route handlers that delegate to services
7
+ */
8
+ declare const app: _spfn_core_route.SPFNApp;
9
+
10
+ export { app as default };