@spfn/auth 0.1.0-alpha.1 → 0.1.0-alpha.87
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 +250 -0
- package/dist/adapters/nextjs/api.d.ts +446 -0
- package/dist/adapters/nextjs/api.js +3279 -0
- package/dist/adapters/nextjs/api.js.map +1 -0
- package/dist/adapters/nextjs/server.d.ts +246 -0
- package/dist/adapters/nextjs/server.js +3645 -0
- package/dist/adapters/nextjs/server.js.map +1 -0
- package/dist/index.d.ts +3 -46
- package/dist/index.js +7438 -7304
- package/dist/index.js.map +1 -1
- package/dist/lib/api/auth-codes-verify.d.ts +37 -0
- package/dist/lib/api/auth-codes-verify.js +2949 -0
- package/dist/lib/api/auth-codes-verify.js.map +1 -0
- package/dist/lib/api/auth-codes.d.ts +37 -0
- package/dist/lib/api/auth-codes.js +2949 -0
- package/dist/lib/api/auth-codes.js.map +1 -0
- package/dist/lib/api/auth-exists.d.ts +38 -0
- package/dist/lib/api/auth-exists.js +2949 -0
- package/dist/lib/api/auth-exists.js.map +1 -0
- package/dist/lib/api/auth-invitations-accept.d.ts +38 -0
- package/dist/lib/api/auth-invitations-accept.js +2883 -0
- package/dist/lib/api/auth-invitations-accept.js.map +1 -0
- package/dist/lib/api/auth-invitations-cancel.d.ts +37 -0
- package/dist/lib/api/auth-invitations-cancel.js +2883 -0
- package/dist/lib/api/auth-invitations-cancel.js.map +1 -0
- package/dist/lib/api/auth-invitations-delete.d.ts +36 -0
- package/dist/lib/api/auth-invitations-delete.js +2883 -0
- package/dist/lib/api/auth-invitations-delete.js.map +1 -0
- package/dist/lib/api/auth-invitations-resend.d.ts +37 -0
- package/dist/lib/api/auth-invitations-resend.js +2883 -0
- package/dist/lib/api/auth-invitations-resend.js.map +1 -0
- package/dist/lib/api/auth-invitations.d.ts +109 -0
- package/dist/lib/api/auth-invitations.js +2887 -0
- package/dist/lib/api/auth-invitations.js.map +1 -0
- package/dist/lib/api/auth-keys-rotate.d.ts +37 -0
- package/dist/lib/api/auth-keys-rotate.js +2949 -0
- package/dist/lib/api/auth-keys-rotate.js.map +1 -0
- package/dist/lib/api/auth-login.d.ts +39 -0
- package/dist/lib/api/auth-login.js +2949 -0
- package/dist/lib/api/auth-login.js.map +1 -0
- package/dist/lib/api/auth-logout.d.ts +36 -0
- package/dist/lib/api/auth-logout.js +2949 -0
- package/dist/lib/api/auth-logout.js.map +1 -0
- package/dist/lib/api/auth-me.d.ts +50 -0
- package/dist/lib/api/auth-me.js +2949 -0
- package/dist/lib/api/auth-me.js.map +1 -0
- package/dist/lib/api/auth-password.d.ts +36 -0
- package/dist/lib/api/auth-password.js +2949 -0
- package/dist/lib/api/auth-password.js.map +1 -0
- package/dist/lib/api/auth-register.d.ts +38 -0
- package/dist/lib/api/auth-register.js +2949 -0
- package/dist/lib/api/auth-register.js.map +1 -0
- package/dist/lib/api/index.d.ts +356 -0
- package/dist/lib/api/index.js +3261 -0
- package/dist/lib/api/index.js.map +1 -0
- package/dist/lib/config.d.ts +70 -0
- package/dist/lib/config.js +64 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/contracts/auth.d.ts +41 -1
- package/dist/lib/contracts/auth.js +28 -0
- package/dist/lib/contracts/auth.js.map +1 -1
- package/dist/lib/contracts/index.d.ts +1 -1
- package/dist/lib/contracts/index.js +28 -0
- package/dist/lib/contracts/index.js.map +1 -1
- package/dist/lib/crypto.d.ts +76 -0
- package/dist/lib/crypto.js +127 -0
- package/dist/lib/crypto.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +313 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/session.d.ts +68 -0
- package/dist/lib/session.js +126 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/{api-BcQM4WKb.d.ts → lib/types/api.d.ts} +2 -2
- package/dist/lib/types/api.js +1 -0
- package/dist/lib/types/api.js.map +1 -0
- package/dist/lib/types/index.d.ts +3 -0
- package/dist/lib/types/index.js +2647 -0
- package/dist/lib/types/index.js.map +1 -0
- package/dist/lib/types/schemas.d.ts +45 -0
- package/dist/lib/types/schemas.js +2647 -0
- package/dist/lib/types/schemas.js.map +1 -0
- package/dist/lib.d.ts +2 -0
- package/dist/lib.js +1 -0
- package/dist/lib.js.map +1 -0
- package/dist/plugin.js +7438 -7304
- package/dist/plugin.js.map +1 -1
- package/dist/server/entities/index.d.ts +1 -0
- package/dist/server/entities/index.js +23 -27
- package/dist/server/entities/index.js.map +1 -1
- package/dist/server/entities/invitations.js +12 -9
- package/dist/server/entities/invitations.js.map +1 -1
- package/dist/server/entities/permissions.js +8 -3
- package/dist/server/entities/permissions.js.map +1 -1
- package/dist/server/entities/role-permissions.js +12 -9
- package/dist/server/entities/role-permissions.js.map +1 -1
- package/dist/server/entities/roles.js +8 -3
- package/dist/server/entities/roles.js.map +1 -1
- package/dist/server/entities/schema.d.ts +14 -0
- package/dist/server/entities/schema.js +7 -0
- package/dist/server/entities/schema.js.map +1 -0
- package/dist/server/entities/user-permissions.js +14 -12
- package/dist/server/entities/user-permissions.js.map +1 -1
- package/dist/server/entities/user-public-keys.js +12 -9
- package/dist/server/entities/user-public-keys.js.map +1 -1
- package/dist/server/entities/user-social-accounts.js +12 -9
- package/dist/server/entities/user-social-accounts.js.map +1 -1
- package/dist/server/entities/users.js +10 -6
- package/dist/server/entities/users.js.map +1 -1
- package/dist/server/entities/verification-codes.js +8 -3
- package/dist/server/entities/verification-codes.js.map +1 -1
- package/dist/server/routes/auth/index.js +497 -512
- package/dist/server/routes/auth/index.js.map +1 -1
- package/dist/server/routes/index.js +777 -545
- package/dist/server/routes/index.js.map +1 -1
- package/dist/server/routes/invitations/index.js +416 -230
- package/dist/server/routes/invitations/index.js.map +1 -1
- package/dist/server.d.ts +91 -62
- package/dist/server.js +323 -327
- package/dist/server.js.map +1 -1
- package/migrations/{0000_tired_gambit.sql → 0000_familiar_firebrand.sql} +2 -0
- package/migrations/meta/0000_snapshot.json +4 -2
- package/migrations/meta/_journal.json +2 -2
- package/package.json +41 -7
|
@@ -8,26 +8,83 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// src/server/entities/schema.ts
|
|
12
|
+
import { createFunctionSchema } from "@spfn/core/db";
|
|
13
|
+
var authSchema;
|
|
14
|
+
var init_schema = __esm({
|
|
15
|
+
"src/server/entities/schema.ts"() {
|
|
16
|
+
"use strict";
|
|
17
|
+
authSchema = createFunctionSchema("@spfn/auth");
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// src/server/entities/verification-codes.ts
|
|
22
|
+
import { text, timestamp, index } from "drizzle-orm/pg-core";
|
|
23
|
+
import { id, timestamps } from "@spfn/core/db";
|
|
24
|
+
var verificationCodes;
|
|
25
|
+
var init_verification_codes = __esm({
|
|
26
|
+
"src/server/entities/verification-codes.ts"() {
|
|
27
|
+
"use strict";
|
|
28
|
+
init_schema();
|
|
29
|
+
verificationCodes = authSchema.table(
|
|
30
|
+
"verification_codes",
|
|
31
|
+
{
|
|
32
|
+
id: id(),
|
|
33
|
+
// Target (email or phone)
|
|
34
|
+
target: text("target").notNull(),
|
|
35
|
+
// Email address or E.164 phone number
|
|
36
|
+
targetType: text(
|
|
37
|
+
"target_type",
|
|
38
|
+
{
|
|
39
|
+
enum: ["email", "phone"]
|
|
40
|
+
}
|
|
41
|
+
).notNull(),
|
|
42
|
+
// Code
|
|
43
|
+
code: text("code").notNull(),
|
|
44
|
+
// 6-digit code by default (configurable)
|
|
45
|
+
// Purpose
|
|
46
|
+
purpose: text(
|
|
47
|
+
"purpose",
|
|
48
|
+
{
|
|
49
|
+
enum: ["registration", "login", "password_reset", "email_change", "phone_change"]
|
|
50
|
+
}
|
|
51
|
+
).notNull(),
|
|
52
|
+
// Expiry
|
|
53
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
54
|
+
// Usage tracking
|
|
55
|
+
usedAt: timestamp("used_at", { withTimezone: true }),
|
|
56
|
+
attempts: text("attempts").notNull().default("0"),
|
|
57
|
+
// Track failed verification attempts
|
|
58
|
+
...timestamps()
|
|
59
|
+
},
|
|
60
|
+
(table) => [
|
|
61
|
+
// Index for quick lookup by target and purpose
|
|
62
|
+
index("target_purpose_idx").on(table.target, table.purpose, table.expiresAt)
|
|
63
|
+
]
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
11
68
|
// src/server/entities/roles.ts
|
|
12
|
-
import { text, boolean, integer, index } from "drizzle-orm/pg-core";
|
|
13
|
-
import { id, timestamps
|
|
14
|
-
var
|
|
69
|
+
import { text as text2, boolean, integer, index as index2 } from "drizzle-orm/pg-core";
|
|
70
|
+
import { id as id2, timestamps as timestamps2 } from "@spfn/core/db";
|
|
71
|
+
var roles;
|
|
15
72
|
var init_roles = __esm({
|
|
16
73
|
"src/server/entities/roles.ts"() {
|
|
17
74
|
"use strict";
|
|
18
|
-
|
|
19
|
-
roles =
|
|
75
|
+
init_schema();
|
|
76
|
+
roles = authSchema.table(
|
|
20
77
|
"roles",
|
|
21
78
|
{
|
|
22
79
|
// Primary key
|
|
23
|
-
id:
|
|
80
|
+
id: id2(),
|
|
24
81
|
// Role identifier (used in code, e.g., 'admin', 'editor')
|
|
25
82
|
// Must be unique, lowercase, kebab-case recommended
|
|
26
|
-
name:
|
|
83
|
+
name: text2("name").notNull().unique(),
|
|
27
84
|
// Display name for UI (e.g., 'Administrator', 'Content Editor')
|
|
28
|
-
displayName:
|
|
85
|
+
displayName: text2("display_name").notNull(),
|
|
29
86
|
// Role description
|
|
30
|
-
description:
|
|
87
|
+
description: text2("description"),
|
|
31
88
|
// Built-in role flag
|
|
32
89
|
// true: Core package roles (user, admin, superadmin) - cannot be deleted
|
|
33
90
|
// false: Custom or preset roles - can be deleted
|
|
@@ -43,45 +100,45 @@ var init_roles = __esm({
|
|
|
43
100
|
// superadmin: 100, admin: 80, user: 10
|
|
44
101
|
// Used for role hierarchy and conflict resolution
|
|
45
102
|
priority: integer("priority").notNull().default(10),
|
|
46
|
-
...
|
|
103
|
+
...timestamps2()
|
|
47
104
|
},
|
|
48
105
|
(table) => [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
106
|
+
index2("roles_name_idx").on(table.name),
|
|
107
|
+
index2("roles_is_system_idx").on(table.isSystem),
|
|
108
|
+
index2("roles_is_active_idx").on(table.isActive),
|
|
109
|
+
index2("roles_is_builtin_idx").on(table.isBuiltin),
|
|
110
|
+
index2("roles_priority_idx").on(table.priority)
|
|
54
111
|
]
|
|
55
112
|
);
|
|
56
113
|
}
|
|
57
114
|
});
|
|
58
115
|
|
|
59
116
|
// src/server/entities/users.ts
|
|
60
|
-
import { text as
|
|
61
|
-
import { id as
|
|
117
|
+
import { text as text3, timestamp as timestamp2, check, boolean as boolean2, bigint, index as index3 } from "drizzle-orm/pg-core";
|
|
118
|
+
import { id as id3, timestamps as timestamps3 } from "@spfn/core/db";
|
|
62
119
|
import { sql } from "drizzle-orm";
|
|
63
|
-
var
|
|
120
|
+
var users;
|
|
64
121
|
var init_users = __esm({
|
|
65
122
|
"src/server/entities/users.ts"() {
|
|
66
123
|
"use strict";
|
|
67
124
|
init_roles();
|
|
68
|
-
|
|
69
|
-
users =
|
|
125
|
+
init_schema();
|
|
126
|
+
users = authSchema.table(
|
|
70
127
|
"users",
|
|
71
128
|
{
|
|
72
129
|
// Identity
|
|
73
|
-
id:
|
|
130
|
+
id: id3(),
|
|
74
131
|
// Email address (unique identifier)
|
|
75
132
|
// Used for: login, password reset, notifications
|
|
76
|
-
email:
|
|
133
|
+
email: text3("email").unique(),
|
|
77
134
|
// Phone number in E.164 international format
|
|
78
135
|
// Format: +[country code][number] (e.g., +821012345678)
|
|
79
136
|
// Used for: SMS login, 2FA, notifications
|
|
80
|
-
phone:
|
|
137
|
+
phone: text3("phone").unique(),
|
|
81
138
|
// Authentication
|
|
82
139
|
// Bcrypt password hash ($2b$10$[salt][hash], 60 chars)
|
|
83
140
|
// Nullable to support OAuth-only accounts
|
|
84
|
-
passwordHash:
|
|
141
|
+
passwordHash: text3("password_hash"),
|
|
85
142
|
// Force password change on next login
|
|
86
143
|
// Use cases: initial setup, security breach, policy violation
|
|
87
144
|
passwordChangeRequired: boolean2("password_change_required").notNull().default(false),
|
|
@@ -94,7 +151,7 @@ var init_users = __esm({
|
|
|
94
151
|
// - active: Normal operation (default)
|
|
95
152
|
// - inactive: Deactivated (user request, dormant)
|
|
96
153
|
// - suspended: Locked (security incident, ToS violation)
|
|
97
|
-
status:
|
|
154
|
+
status: text3(
|
|
98
155
|
"status",
|
|
99
156
|
{
|
|
100
157
|
enum: ["active", "inactive", "suspended"]
|
|
@@ -103,14 +160,14 @@ var init_users = __esm({
|
|
|
103
160
|
// Verification timestamps
|
|
104
161
|
// null = unverified, timestamp = verified at this time
|
|
105
162
|
// Email verification (via verification code or magic link)
|
|
106
|
-
emailVerifiedAt:
|
|
163
|
+
emailVerifiedAt: timestamp2("email_verified_at", { withTimezone: true }),
|
|
107
164
|
// Phone verification (via SMS OTP)
|
|
108
|
-
phoneVerifiedAt:
|
|
165
|
+
phoneVerifiedAt: timestamp2("phone_verified_at", { withTimezone: true }),
|
|
109
166
|
// Metadata
|
|
110
167
|
// Last successful login timestamp
|
|
111
168
|
// Used for: security auditing, dormant account detection
|
|
112
|
-
lastLoginAt:
|
|
113
|
-
...
|
|
169
|
+
lastLoginAt: timestamp2("last_login_at", { withTimezone: true }),
|
|
170
|
+
...timestamps3()
|
|
114
171
|
},
|
|
115
172
|
(table) => [
|
|
116
173
|
// Database constraints
|
|
@@ -120,44 +177,44 @@ var init_users = __esm({
|
|
|
120
177
|
sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`
|
|
121
178
|
),
|
|
122
179
|
// Indexes for query optimization
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
180
|
+
index3("users_email_idx").on(table.email),
|
|
181
|
+
index3("users_phone_idx").on(table.phone),
|
|
182
|
+
index3("users_status_idx").on(table.status),
|
|
183
|
+
index3("users_role_id_idx").on(table.roleId)
|
|
127
184
|
]
|
|
128
185
|
);
|
|
129
186
|
}
|
|
130
187
|
});
|
|
131
188
|
|
|
132
189
|
// src/server/entities/user-social-accounts.ts
|
|
133
|
-
import { text as
|
|
134
|
-
import { id as
|
|
135
|
-
var
|
|
190
|
+
import { text as text4, timestamp as timestamp3, uniqueIndex } from "drizzle-orm/pg-core";
|
|
191
|
+
import { id as id4, timestamps as timestamps4, foreignKey } from "@spfn/core/db";
|
|
192
|
+
var userSocialAccounts;
|
|
136
193
|
var init_user_social_accounts = __esm({
|
|
137
194
|
"src/server/entities/user-social-accounts.ts"() {
|
|
138
195
|
"use strict";
|
|
139
196
|
init_users();
|
|
140
|
-
|
|
141
|
-
userSocialAccounts =
|
|
197
|
+
init_schema();
|
|
198
|
+
userSocialAccounts = authSchema.table(
|
|
142
199
|
"user_social_accounts",
|
|
143
200
|
{
|
|
144
|
-
id:
|
|
201
|
+
id: id4(),
|
|
145
202
|
// Foreign key to users
|
|
146
203
|
userId: foreignKey("user", () => users.id),
|
|
147
204
|
// Provider info
|
|
148
|
-
provider:
|
|
205
|
+
provider: text4(
|
|
149
206
|
"provider",
|
|
150
207
|
{
|
|
151
208
|
enum: ["google", "github", "kakao", "naver"]
|
|
152
209
|
}
|
|
153
210
|
).notNull(),
|
|
154
|
-
providerUserId:
|
|
155
|
-
providerEmail:
|
|
211
|
+
providerUserId: text4("provider_user_id").notNull(),
|
|
212
|
+
providerEmail: text4("provider_email"),
|
|
156
213
|
// OAuth tokens (encrypted in production)
|
|
157
|
-
accessToken:
|
|
158
|
-
refreshToken:
|
|
159
|
-
tokenExpiresAt:
|
|
160
|
-
...
|
|
214
|
+
accessToken: text4("access_token"),
|
|
215
|
+
refreshToken: text4("refresh_token"),
|
|
216
|
+
tokenExpiresAt: timestamp3("token_expires_at", { withTimezone: true }),
|
|
217
|
+
...timestamps4()
|
|
161
218
|
},
|
|
162
219
|
(table) => [
|
|
163
220
|
// Unique constraint: one provider account per provider
|
|
@@ -168,92 +225,45 @@ var init_user_social_accounts = __esm({
|
|
|
168
225
|
});
|
|
169
226
|
|
|
170
227
|
// src/server/entities/user-public-keys.ts
|
|
171
|
-
import { text as
|
|
172
|
-
import { id as
|
|
173
|
-
var
|
|
228
|
+
import { text as text5, timestamp as timestamp4, boolean as boolean3, index as index4 } from "drizzle-orm/pg-core";
|
|
229
|
+
import { id as id5, foreignKey as foreignKey2 } from "@spfn/core/db";
|
|
230
|
+
var userPublicKeys;
|
|
174
231
|
var init_user_public_keys = __esm({
|
|
175
232
|
"src/server/entities/user-public-keys.ts"() {
|
|
176
233
|
"use strict";
|
|
177
234
|
init_users();
|
|
178
|
-
|
|
179
|
-
userPublicKeys =
|
|
235
|
+
init_schema();
|
|
236
|
+
userPublicKeys = authSchema.table(
|
|
180
237
|
"user_public_keys",
|
|
181
238
|
{
|
|
182
|
-
id:
|
|
239
|
+
id: id5(),
|
|
183
240
|
// User reference
|
|
184
241
|
userId: foreignKey2("user", () => users.id),
|
|
185
242
|
// Key identification (client-generated UUID)
|
|
186
|
-
keyId:
|
|
243
|
+
keyId: text5("key_id").notNull().unique(),
|
|
187
244
|
// Public key in Base64-encoded DER format (SPKI)
|
|
188
|
-
publicKey:
|
|
245
|
+
publicKey: text5("public_key").notNull(),
|
|
189
246
|
// Algorithm used (ES256 recommended, RS256 fallback)
|
|
190
|
-
algorithm:
|
|
247
|
+
algorithm: text5("algorithm", {
|
|
191
248
|
enum: ["ES256", "RS256"]
|
|
192
249
|
}).notNull().default("ES256"),
|
|
193
250
|
// Key fingerprint (SHA-256 hash for quick identification)
|
|
194
|
-
fingerprint:
|
|
251
|
+
fingerprint: text5("fingerprint").notNull(),
|
|
195
252
|
// Key status
|
|
196
253
|
isActive: boolean3("is_active").notNull().default(true),
|
|
197
254
|
// Timestamps
|
|
198
|
-
createdAt:
|
|
199
|
-
lastUsedAt:
|
|
200
|
-
expiresAt:
|
|
255
|
+
createdAt: timestamp4("created_at", { mode: "date", withTimezone: true }).notNull().defaultNow(),
|
|
256
|
+
lastUsedAt: timestamp4("last_used_at", { mode: "date", withTimezone: true }),
|
|
257
|
+
expiresAt: timestamp4("expires_at", { mode: "date", withTimezone: true }),
|
|
201
258
|
// Revocation
|
|
202
|
-
revokedAt:
|
|
203
|
-
revokedReason:
|
|
204
|
-
},
|
|
205
|
-
(table) => [
|
|
206
|
-
index3("user_public_keys_user_id_idx").on(table.userId),
|
|
207
|
-
index3("user_public_keys_key_id_idx").on(table.keyId),
|
|
208
|
-
index3("user_public_keys_active_idx").on(table.isActive),
|
|
209
|
-
index3("user_public_keys_fingerprint_idx").on(table.fingerprint)
|
|
210
|
-
]
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// src/server/entities/verification-codes.ts
|
|
216
|
-
import { text as text5, timestamp as timestamp4, index as index4 } from "drizzle-orm/pg-core";
|
|
217
|
-
import { id as id5, timestamps as timestamps4, createFunctionSchema as createFunctionSchema5 } from "@spfn/core/db";
|
|
218
|
-
var schema5, verificationCodes;
|
|
219
|
-
var init_verification_codes = __esm({
|
|
220
|
-
"src/server/entities/verification-codes.ts"() {
|
|
221
|
-
"use strict";
|
|
222
|
-
schema5 = createFunctionSchema5("@spfn/auth");
|
|
223
|
-
verificationCodes = schema5.table(
|
|
224
|
-
"verification_codes",
|
|
225
|
-
{
|
|
226
|
-
id: id5(),
|
|
227
|
-
// Target (email or phone)
|
|
228
|
-
target: text5("target").notNull(),
|
|
229
|
-
// Email address or E.164 phone number
|
|
230
|
-
targetType: text5(
|
|
231
|
-
"target_type",
|
|
232
|
-
{
|
|
233
|
-
enum: ["email", "phone"]
|
|
234
|
-
}
|
|
235
|
-
).notNull(),
|
|
236
|
-
// Code
|
|
237
|
-
code: text5("code").notNull(),
|
|
238
|
-
// 6-digit code by default (configurable)
|
|
239
|
-
// Purpose
|
|
240
|
-
purpose: text5(
|
|
241
|
-
"purpose",
|
|
242
|
-
{
|
|
243
|
-
enum: ["registration", "login", "password_reset", "email_change", "phone_change"]
|
|
244
|
-
}
|
|
245
|
-
).notNull(),
|
|
246
|
-
// Expiry
|
|
247
|
-
expiresAt: timestamp4("expires_at", { withTimezone: true }).notNull(),
|
|
248
|
-
// Usage tracking
|
|
249
|
-
usedAt: timestamp4("used_at", { withTimezone: true }),
|
|
250
|
-
attempts: text5("attempts").notNull().default("0"),
|
|
251
|
-
// Track failed verification attempts
|
|
252
|
-
...timestamps4()
|
|
259
|
+
revokedAt: timestamp4("revoked_at", { mode: "date", withTimezone: true }),
|
|
260
|
+
revokedReason: text5("revoked_reason")
|
|
253
261
|
},
|
|
254
262
|
(table) => [
|
|
255
|
-
|
|
256
|
-
index4("
|
|
263
|
+
index4("user_public_keys_user_id_idx").on(table.userId),
|
|
264
|
+
index4("user_public_keys_key_id_idx").on(table.keyId),
|
|
265
|
+
index4("user_public_keys_active_idx").on(table.isActive),
|
|
266
|
+
index4("user_public_keys_fingerprint_idx").on(table.fingerprint)
|
|
257
267
|
]
|
|
258
268
|
);
|
|
259
269
|
}
|
|
@@ -261,15 +271,15 @@ var init_verification_codes = __esm({
|
|
|
261
271
|
|
|
262
272
|
// src/server/entities/invitations.ts
|
|
263
273
|
import { text as text6, timestamp as timestamp5, bigint as bigint2, index as index5, jsonb } from "drizzle-orm/pg-core";
|
|
264
|
-
import { id as id6, timestamps as timestamps5
|
|
265
|
-
var
|
|
274
|
+
import { id as id6, timestamps as timestamps5 } from "@spfn/core/db";
|
|
275
|
+
var invitations;
|
|
266
276
|
var init_invitations = __esm({
|
|
267
277
|
"src/server/entities/invitations.ts"() {
|
|
268
278
|
"use strict";
|
|
269
279
|
init_roles();
|
|
270
280
|
init_users();
|
|
271
|
-
|
|
272
|
-
invitations =
|
|
281
|
+
init_schema();
|
|
282
|
+
invitations = authSchema.table(
|
|
273
283
|
"user_invitations",
|
|
274
284
|
{
|
|
275
285
|
// Primary key
|
|
@@ -337,13 +347,13 @@ var init_invitations = __esm({
|
|
|
337
347
|
|
|
338
348
|
// src/server/entities/permissions.ts
|
|
339
349
|
import { text as text7, boolean as boolean4, index as index6 } from "drizzle-orm/pg-core";
|
|
340
|
-
import { id as id7, timestamps as timestamps6
|
|
341
|
-
var
|
|
350
|
+
import { id as id7, timestamps as timestamps6 } from "@spfn/core/db";
|
|
351
|
+
var permissions;
|
|
342
352
|
var init_permissions = __esm({
|
|
343
353
|
"src/server/entities/permissions.ts"() {
|
|
344
354
|
"use strict";
|
|
345
|
-
|
|
346
|
-
permissions =
|
|
355
|
+
init_schema();
|
|
356
|
+
permissions = authSchema.table(
|
|
347
357
|
"permissions",
|
|
348
358
|
{
|
|
349
359
|
// Primary key
|
|
@@ -384,15 +394,15 @@ var init_permissions = __esm({
|
|
|
384
394
|
|
|
385
395
|
// src/server/entities/role-permissions.ts
|
|
386
396
|
import { bigint as bigint3, index as index7, unique } from "drizzle-orm/pg-core";
|
|
387
|
-
import { id as id8, timestamps as timestamps7
|
|
388
|
-
var
|
|
397
|
+
import { id as id8, timestamps as timestamps7 } from "@spfn/core/db";
|
|
398
|
+
var rolePermissions;
|
|
389
399
|
var init_role_permissions = __esm({
|
|
390
400
|
"src/server/entities/role-permissions.ts"() {
|
|
391
401
|
"use strict";
|
|
392
402
|
init_roles();
|
|
393
403
|
init_permissions();
|
|
394
|
-
|
|
395
|
-
rolePermissions =
|
|
404
|
+
init_schema();
|
|
405
|
+
rolePermissions = authSchema.table(
|
|
396
406
|
"role_permissions",
|
|
397
407
|
{
|
|
398
408
|
// Primary key
|
|
@@ -416,15 +426,15 @@ var init_role_permissions = __esm({
|
|
|
416
426
|
|
|
417
427
|
// src/server/entities/user-permissions.ts
|
|
418
428
|
import { bigint as bigint4, boolean as boolean5, text as text8, timestamp as timestamp6, index as index8, unique as unique2 } from "drizzle-orm/pg-core";
|
|
419
|
-
import { id as id9, timestamps as timestamps8
|
|
420
|
-
var
|
|
429
|
+
import { id as id9, timestamps as timestamps8 } from "@spfn/core/db";
|
|
430
|
+
var userPermissions;
|
|
421
431
|
var init_user_permissions = __esm({
|
|
422
432
|
"src/server/entities/user-permissions.ts"() {
|
|
423
433
|
"use strict";
|
|
424
434
|
init_users();
|
|
425
435
|
init_permissions();
|
|
426
|
-
|
|
427
|
-
userPermissions =
|
|
436
|
+
init_schema();
|
|
437
|
+
userPermissions = authSchema.table(
|
|
428
438
|
"user_permissions",
|
|
429
439
|
{
|
|
430
440
|
// Primary key
|
|
@@ -461,6 +471,7 @@ var init_user_permissions = __esm({
|
|
|
461
471
|
var init_entities = __esm({
|
|
462
472
|
"src/server/entities/index.ts"() {
|
|
463
473
|
"use strict";
|
|
474
|
+
init_schema();
|
|
464
475
|
init_users();
|
|
465
476
|
init_user_social_accounts();
|
|
466
477
|
init_user_public_keys();
|
|
@@ -486,14 +497,14 @@ __export(role_service_exports, {
|
|
|
486
497
|
setRolePermissions: () => setRolePermissions,
|
|
487
498
|
updateRole: () => updateRole
|
|
488
499
|
});
|
|
489
|
-
import { getDatabase as
|
|
490
|
-
import { eq as
|
|
500
|
+
import { getDatabase as getDatabase3 } from "@spfn/core/db";
|
|
501
|
+
import { eq as eq3, and as and3 } from "drizzle-orm";
|
|
491
502
|
async function createRole(data) {
|
|
492
|
-
const db =
|
|
503
|
+
const db = getDatabase3();
|
|
493
504
|
if (!db) {
|
|
494
505
|
throw new Error("[Auth] Database not initialized");
|
|
495
506
|
}
|
|
496
|
-
const existing = await db.select().from(roles).where(
|
|
507
|
+
const existing = await db.select().from(roles).where(eq3(roles.name, data.name)).limit(1);
|
|
497
508
|
if (existing.length > 0) {
|
|
498
509
|
throw new Error(`Role with name '${data.name}' already exists`);
|
|
499
510
|
}
|
|
@@ -517,28 +528,28 @@ async function createRole(data) {
|
|
|
517
528
|
return newRole;
|
|
518
529
|
}
|
|
519
530
|
async function updateRole(roleId, data) {
|
|
520
|
-
const db =
|
|
531
|
+
const db = getDatabase3();
|
|
521
532
|
if (!db) {
|
|
522
533
|
throw new Error("[Auth] Database not initialized");
|
|
523
534
|
}
|
|
524
535
|
const roleIdNum = Number(roleId);
|
|
525
|
-
const [role] = await db.select().from(roles).where(
|
|
536
|
+
const [role] = await db.select().from(roles).where(eq3(roles.id, roleIdNum)).limit(1);
|
|
526
537
|
if (!role) {
|
|
527
538
|
throw new Error("Role not found");
|
|
528
539
|
}
|
|
529
540
|
if (role.isBuiltin && data.priority !== void 0) {
|
|
530
541
|
throw new Error("Cannot modify priority of built-in roles");
|
|
531
542
|
}
|
|
532
|
-
const [updated] = await db.update(roles).set(data).where(
|
|
543
|
+
const [updated] = await db.update(roles).set(data).where(eq3(roles.id, roleIdNum)).returning();
|
|
533
544
|
return updated;
|
|
534
545
|
}
|
|
535
546
|
async function deleteRole(roleId) {
|
|
536
|
-
const db =
|
|
547
|
+
const db = getDatabase3();
|
|
537
548
|
if (!db) {
|
|
538
549
|
throw new Error("[Auth] Database not initialized");
|
|
539
550
|
}
|
|
540
551
|
const roleIdNum = Number(roleId);
|
|
541
|
-
const [role] = await db.select().from(roles).where(
|
|
552
|
+
const [role] = await db.select().from(roles).where(eq3(roles.id, roleIdNum)).limit(1);
|
|
542
553
|
if (!role) {
|
|
543
554
|
throw new Error("Role not found");
|
|
544
555
|
}
|
|
@@ -548,20 +559,20 @@ async function deleteRole(roleId) {
|
|
|
548
559
|
if (role.isSystem) {
|
|
549
560
|
throw new Error(`Cannot delete system role: ${role.name}. Deactivate it instead.`);
|
|
550
561
|
}
|
|
551
|
-
await db.delete(roles).where(
|
|
562
|
+
await db.delete(roles).where(eq3(roles.id, roleIdNum));
|
|
552
563
|
console.log(`[Auth] \u{1F5D1}\uFE0F Deleted role: ${role.name}`);
|
|
553
564
|
}
|
|
554
565
|
async function addPermissionToRole(roleId, permissionId) {
|
|
555
|
-
const db =
|
|
566
|
+
const db = getDatabase3();
|
|
556
567
|
if (!db) {
|
|
557
568
|
throw new Error("[Auth] Database not initialized");
|
|
558
569
|
}
|
|
559
570
|
const roleIdNum = Number(roleId);
|
|
560
571
|
const permissionIdNum = Number(permissionId);
|
|
561
572
|
const existing = await db.select().from(rolePermissions).where(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
573
|
+
and3(
|
|
574
|
+
eq3(rolePermissions.roleId, roleIdNum),
|
|
575
|
+
eq3(rolePermissions.permissionId, permissionIdNum)
|
|
565
576
|
)
|
|
566
577
|
).limit(1);
|
|
567
578
|
if (existing.length > 0) {
|
|
@@ -573,26 +584,26 @@ async function addPermissionToRole(roleId, permissionId) {
|
|
|
573
584
|
});
|
|
574
585
|
}
|
|
575
586
|
async function removePermissionFromRole(roleId, permissionId) {
|
|
576
|
-
const db =
|
|
587
|
+
const db = getDatabase3();
|
|
577
588
|
if (!db) {
|
|
578
589
|
throw new Error("[Auth] Database not initialized");
|
|
579
590
|
}
|
|
580
591
|
const roleIdNum = Number(roleId);
|
|
581
592
|
const permissionIdNum = Number(permissionId);
|
|
582
593
|
await db.delete(rolePermissions).where(
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
594
|
+
and3(
|
|
595
|
+
eq3(rolePermissions.roleId, roleIdNum),
|
|
596
|
+
eq3(rolePermissions.permissionId, permissionIdNum)
|
|
586
597
|
)
|
|
587
598
|
);
|
|
588
599
|
}
|
|
589
600
|
async function setRolePermissions(roleId, permissionIds) {
|
|
590
|
-
const db =
|
|
601
|
+
const db = getDatabase3();
|
|
591
602
|
if (!db) {
|
|
592
603
|
throw new Error("[Auth] Database not initialized");
|
|
593
604
|
}
|
|
594
605
|
const roleIdNum = Number(roleId);
|
|
595
|
-
await db.delete(rolePermissions).where(
|
|
606
|
+
await db.delete(rolePermissions).where(eq3(rolePermissions.roleId, roleIdNum));
|
|
596
607
|
if (permissionIds.length > 0) {
|
|
597
608
|
const mappings = permissionIds.map((permId) => ({
|
|
598
609
|
roleId: roleIdNum,
|
|
@@ -602,31 +613,31 @@ async function setRolePermissions(roleId, permissionIds) {
|
|
|
602
613
|
}
|
|
603
614
|
}
|
|
604
615
|
async function getAllRoles(includeInactive = false) {
|
|
605
|
-
const db =
|
|
616
|
+
const db = getDatabase3();
|
|
606
617
|
if (!db) {
|
|
607
618
|
throw new Error("[Auth] Database not initialized");
|
|
608
619
|
}
|
|
609
620
|
const query = db.select().from(roles);
|
|
610
621
|
if (!includeInactive) {
|
|
611
|
-
return query.where(
|
|
622
|
+
return query.where(eq3(roles.isActive, true));
|
|
612
623
|
}
|
|
613
624
|
return query;
|
|
614
625
|
}
|
|
615
626
|
async function getRoleByName(name) {
|
|
616
|
-
const db =
|
|
627
|
+
const db = getDatabase3();
|
|
617
628
|
if (!db) {
|
|
618
629
|
throw new Error("[Auth] Database not initialized");
|
|
619
630
|
}
|
|
620
|
-
const [role] = await db.select().from(roles).where(
|
|
631
|
+
const [role] = await db.select().from(roles).where(eq3(roles.name, name)).limit(1);
|
|
621
632
|
return role || null;
|
|
622
633
|
}
|
|
623
634
|
async function getRolePermissions(roleId) {
|
|
624
|
-
const db =
|
|
635
|
+
const db = getDatabase3();
|
|
625
636
|
if (!db) {
|
|
626
637
|
throw new Error("[Auth] Database not initialized");
|
|
627
638
|
}
|
|
628
639
|
const roleIdNum = Number(roleId);
|
|
629
|
-
const perms = await db.select({ name: permissions.name }).from(rolePermissions).innerJoin(permissions,
|
|
640
|
+
const perms = await db.select({ name: permissions.name }).from(rolePermissions).innerJoin(permissions, eq3(rolePermissions.permissionId, permissions.id)).where(eq3(rolePermissions.roleId, roleIdNum));
|
|
630
641
|
return perms.map((p) => p.name);
|
|
631
642
|
}
|
|
632
643
|
var init_role_service = __esm({
|
|
@@ -739,8 +750,8 @@ function Clone(value) {
|
|
|
739
750
|
}
|
|
740
751
|
|
|
741
752
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/clone/type.mjs
|
|
742
|
-
function CloneType(
|
|
743
|
-
return options === void 0 ? Clone(
|
|
753
|
+
function CloneType(schema, options) {
|
|
754
|
+
return options === void 0 ? Clone(schema) : Clone({ ...options, ...schema });
|
|
744
755
|
}
|
|
745
756
|
|
|
746
757
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/value/guard/guard.mjs
|
|
@@ -817,8 +828,8 @@ function Immutable(value) {
|
|
|
817
828
|
}
|
|
818
829
|
|
|
819
830
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/create/type.mjs
|
|
820
|
-
function CreateType(
|
|
821
|
-
const result = options !== void 0 ? { ...options, ...
|
|
831
|
+
function CreateType(schema, options) {
|
|
832
|
+
const result = options !== void 0 ? { ...options, ...schema } : schema;
|
|
822
833
|
switch (TypeSystemPolicy.InstanceMode) {
|
|
823
834
|
case "freeze":
|
|
824
835
|
return Immutable(result);
|
|
@@ -1136,16 +1147,16 @@ function IsBoolean3(value) {
|
|
|
1136
1147
|
return IsKindOf2(value, "Boolean") && value.type === "boolean" && IsOptionalString(value.$id);
|
|
1137
1148
|
}
|
|
1138
1149
|
function IsComputed2(value) {
|
|
1139
|
-
return IsKindOf2(value, "Computed") && IsString(value.target) && IsArray(value.parameters) && value.parameters.every((
|
|
1150
|
+
return IsKindOf2(value, "Computed") && IsString(value.target) && IsArray(value.parameters) && value.parameters.every((schema) => IsSchema2(schema));
|
|
1140
1151
|
}
|
|
1141
1152
|
function IsConstructor2(value) {
|
|
1142
|
-
return IsKindOf2(value, "Constructor") && value.type === "Constructor" && IsOptionalString(value.$id) && IsArray(value.parameters) && value.parameters.every((
|
|
1153
|
+
return IsKindOf2(value, "Constructor") && value.type === "Constructor" && IsOptionalString(value.$id) && IsArray(value.parameters) && value.parameters.every((schema) => IsSchema2(schema)) && IsSchema2(value.returns);
|
|
1143
1154
|
}
|
|
1144
1155
|
function IsDate3(value) {
|
|
1145
1156
|
return IsKindOf2(value, "Date") && value.type === "Date" && IsOptionalString(value.$id) && IsOptionalNumber(value.exclusiveMaximumTimestamp) && IsOptionalNumber(value.exclusiveMinimumTimestamp) && IsOptionalNumber(value.maximumTimestamp) && IsOptionalNumber(value.minimumTimestamp) && IsOptionalNumber(value.multipleOfTimestamp);
|
|
1146
1157
|
}
|
|
1147
1158
|
function IsFunction3(value) {
|
|
1148
|
-
return IsKindOf2(value, "Function") && value.type === "Function" && IsOptionalString(value.$id) && IsArray(value.parameters) && value.parameters.every((
|
|
1159
|
+
return IsKindOf2(value, "Function") && value.type === "Function" && IsOptionalString(value.$id) && IsArray(value.parameters) && value.parameters.every((schema) => IsSchema2(schema)) && IsSchema2(value.returns);
|
|
1149
1160
|
}
|
|
1150
1161
|
function IsImport(value) {
|
|
1151
1162
|
return IsKindOf2(value, "Import") && HasPropertyKey(value, "$defs") && IsObject(value.$defs) && IsProperties(value.$defs) && HasPropertyKey(value, "$ref") && IsString(value.$ref) && value.$ref in value.$defs;
|
|
@@ -1154,10 +1165,10 @@ function IsInteger2(value) {
|
|
|
1154
1165
|
return IsKindOf2(value, "Integer") && value.type === "integer" && IsOptionalString(value.$id) && IsOptionalNumber(value.exclusiveMaximum) && IsOptionalNumber(value.exclusiveMinimum) && IsOptionalNumber(value.maximum) && IsOptionalNumber(value.minimum) && IsOptionalNumber(value.multipleOf);
|
|
1155
1166
|
}
|
|
1156
1167
|
function IsProperties(value) {
|
|
1157
|
-
return IsObject(value) && Object.entries(value).every(([key,
|
|
1168
|
+
return IsObject(value) && Object.entries(value).every(([key, schema]) => IsControlCharacterFree(key) && IsSchema2(schema));
|
|
1158
1169
|
}
|
|
1159
1170
|
function IsIntersect2(value) {
|
|
1160
|
-
return IsKindOf2(value, "Intersect") && (IsString(value.type) && value.type !== "object" ? false : true) && IsArray(value.allOf) && value.allOf.every((
|
|
1171
|
+
return IsKindOf2(value, "Intersect") && (IsString(value.type) && value.type !== "object" ? false : true) && IsArray(value.allOf) && value.allOf.every((schema) => IsSchema2(schema) && !IsTransform2(schema)) && IsOptionalString(value.type) && (IsOptionalBoolean(value.unevaluatedProperties) || IsOptionalSchema(value.unevaluatedProperties)) && IsOptionalString(value.$id);
|
|
1161
1172
|
}
|
|
1162
1173
|
function IsIterator3(value) {
|
|
1163
1174
|
return IsKindOf2(value, "Iterator") && value.type === "Iterator" && IsOptionalString(value.$id) && IsSchema2(value.items);
|
|
@@ -1205,9 +1216,9 @@ function IsPromise2(value) {
|
|
|
1205
1216
|
return IsKindOf2(value, "Promise") && value.type === "Promise" && IsOptionalString(value.$id) && IsSchema2(value.item);
|
|
1206
1217
|
}
|
|
1207
1218
|
function IsRecord2(value) {
|
|
1208
|
-
return IsKindOf2(value, "Record") && value.type === "object" && IsOptionalString(value.$id) && IsAdditionalProperties(value.additionalProperties) && IsObject(value.patternProperties) && ((
|
|
1209
|
-
const keys = Object.getOwnPropertyNames(
|
|
1210
|
-
return keys.length === 1 && IsPattern(keys[0]) && IsObject(
|
|
1219
|
+
return IsKindOf2(value, "Record") && value.type === "object" && IsOptionalString(value.$id) && IsAdditionalProperties(value.additionalProperties) && IsObject(value.patternProperties) && ((schema) => {
|
|
1220
|
+
const keys = Object.getOwnPropertyNames(schema.patternProperties);
|
|
1221
|
+
return keys.length === 1 && IsPattern(keys[0]) && IsObject(schema.patternProperties) && IsSchema2(schema.patternProperties[keys[0]]);
|
|
1211
1222
|
})(value);
|
|
1212
1223
|
}
|
|
1213
1224
|
function IsRecursive(value) {
|
|
@@ -1236,16 +1247,16 @@ function IsTransform2(value) {
|
|
|
1236
1247
|
}
|
|
1237
1248
|
function IsTuple2(value) {
|
|
1238
1249
|
return IsKindOf2(value, "Tuple") && value.type === "array" && IsOptionalString(value.$id) && IsNumber(value.minItems) && IsNumber(value.maxItems) && value.minItems === value.maxItems && // empty
|
|
1239
|
-
(IsUndefined(value.items) && IsUndefined(value.additionalItems) && value.minItems === 0 || IsArray(value.items) && value.items.every((
|
|
1250
|
+
(IsUndefined(value.items) && IsUndefined(value.additionalItems) && value.minItems === 0 || IsArray(value.items) && value.items.every((schema) => IsSchema2(schema)));
|
|
1240
1251
|
}
|
|
1241
1252
|
function IsUndefined4(value) {
|
|
1242
1253
|
return IsKindOf2(value, "Undefined") && value.type === "undefined" && IsOptionalString(value.$id);
|
|
1243
1254
|
}
|
|
1244
1255
|
function IsUnionLiteral(value) {
|
|
1245
|
-
return IsUnion2(value) && value.anyOf.every((
|
|
1256
|
+
return IsUnion2(value) && value.anyOf.every((schema) => IsLiteralString(schema) || IsLiteralNumber(schema));
|
|
1246
1257
|
}
|
|
1247
1258
|
function IsUnion2(value) {
|
|
1248
|
-
return IsKindOf2(value, "Union") && IsOptionalString(value.$id) && IsObject(value) && IsArray(value.anyOf) && value.anyOf.every((
|
|
1259
|
+
return IsKindOf2(value, "Union") && IsOptionalString(value.$id) && IsObject(value) && IsArray(value.anyOf) && value.anyOf.every((schema) => IsSchema2(schema));
|
|
1249
1260
|
}
|
|
1250
1261
|
function IsUint8Array3(value) {
|
|
1251
1262
|
return IsKindOf2(value, "Uint8Array") && value.type === "Uint8Array" && IsOptionalString(value.$id) && IsOptionalNumber(value.minByteLength) && IsOptionalNumber(value.maxByteLength);
|
|
@@ -1527,8 +1538,8 @@ function IsTemplateLiteralExpressionFinite(expression) {
|
|
|
1527
1538
|
throw new TemplateLiteralFiniteError(`Unknown expression type`);
|
|
1528
1539
|
})();
|
|
1529
1540
|
}
|
|
1530
|
-
function IsTemplateLiteralFinite(
|
|
1531
|
-
const expression = TemplateLiteralParseExact(
|
|
1541
|
+
function IsTemplateLiteralFinite(schema) {
|
|
1542
|
+
const expression = TemplateLiteralParseExact(schema.pattern);
|
|
1532
1543
|
return IsTemplateLiteralExpressionFinite(expression);
|
|
1533
1544
|
}
|
|
1534
1545
|
|
|
@@ -1559,8 +1570,8 @@ function* TemplateLiteralExpressionGenerate(expression) {
|
|
|
1559
1570
|
throw new TemplateLiteralGenerateError("Unknown expression");
|
|
1560
1571
|
})();
|
|
1561
1572
|
}
|
|
1562
|
-
function TemplateLiteralGenerate(
|
|
1563
|
-
const expression = TemplateLiteralParseExact(
|
|
1573
|
+
function TemplateLiteralGenerate(schema) {
|
|
1574
|
+
const expression = TemplateLiteralParseExact(schema.pattern);
|
|
1564
1575
|
return IsTemplateLiteralExpressionFinite(expression) ? [...TemplateLiteralExpressionGenerate(expression)] : [];
|
|
1565
1576
|
}
|
|
1566
1577
|
|
|
@@ -1636,18 +1647,18 @@ var TemplateLiteralPatternError = class extends TypeBoxError {
|
|
|
1636
1647
|
function Escape(value) {
|
|
1637
1648
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1638
1649
|
}
|
|
1639
|
-
function Visit2(
|
|
1640
|
-
return IsTemplateLiteral(
|
|
1641
|
-
throw new TemplateLiteralPatternError(`Unexpected Kind '${
|
|
1650
|
+
function Visit2(schema, acc) {
|
|
1651
|
+
return IsTemplateLiteral(schema) ? schema.pattern.slice(1, schema.pattern.length - 1) : IsUnion(schema) ? `(${schema.anyOf.map((schema2) => Visit2(schema2, acc)).join("|")})` : IsNumber3(schema) ? `${acc}${PatternNumber}` : IsInteger(schema) ? `${acc}${PatternNumber}` : IsBigInt2(schema) ? `${acc}${PatternNumber}` : IsString2(schema) ? `${acc}${PatternString}` : IsLiteral(schema) ? `${acc}${Escape(schema.const.toString())}` : IsBoolean2(schema) ? `${acc}${PatternBoolean}` : (() => {
|
|
1652
|
+
throw new TemplateLiteralPatternError(`Unexpected Kind '${schema[Kind]}'`);
|
|
1642
1653
|
})();
|
|
1643
1654
|
}
|
|
1644
1655
|
function TemplateLiteralPattern(kinds) {
|
|
1645
|
-
return `^${kinds.map((
|
|
1656
|
+
return `^${kinds.map((schema) => Visit2(schema, "")).join("")}$`;
|
|
1646
1657
|
}
|
|
1647
1658
|
|
|
1648
1659
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/template-literal/union.mjs
|
|
1649
|
-
function TemplateLiteralToUnion(
|
|
1650
|
-
const R = TemplateLiteralGenerate(
|
|
1660
|
+
function TemplateLiteralToUnion(schema) {
|
|
1661
|
+
const R = TemplateLiteralGenerate(schema);
|
|
1651
1662
|
const L = R.map((S) => Literal(S));
|
|
1652
1663
|
return UnionEvaluated(L);
|
|
1653
1664
|
}
|
|
@@ -1784,18 +1795,18 @@ function Promise2(item, options) {
|
|
|
1784
1795
|
}
|
|
1785
1796
|
|
|
1786
1797
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/readonly/readonly.mjs
|
|
1787
|
-
function RemoveReadonly(
|
|
1788
|
-
return CreateType(Discard(
|
|
1798
|
+
function RemoveReadonly(schema) {
|
|
1799
|
+
return CreateType(Discard(schema, [ReadonlyKind]));
|
|
1789
1800
|
}
|
|
1790
|
-
function AddReadonly(
|
|
1791
|
-
return CreateType({ ...
|
|
1801
|
+
function AddReadonly(schema) {
|
|
1802
|
+
return CreateType({ ...schema, [ReadonlyKind]: "Readonly" });
|
|
1792
1803
|
}
|
|
1793
|
-
function ReadonlyWithFlag(
|
|
1794
|
-
return F === false ? RemoveReadonly(
|
|
1804
|
+
function ReadonlyWithFlag(schema, F) {
|
|
1805
|
+
return F === false ? RemoveReadonly(schema) : AddReadonly(schema);
|
|
1795
1806
|
}
|
|
1796
|
-
function Readonly(
|
|
1807
|
+
function Readonly(schema, enable) {
|
|
1797
1808
|
const F = enable ?? true;
|
|
1798
|
-
return IsMappedResult(
|
|
1809
|
+
return IsMappedResult(schema) ? ReadonlyFromMappedResult(schema, F) : ReadonlyWithFlag(schema, F);
|
|
1799
1810
|
}
|
|
1800
1811
|
|
|
1801
1812
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/readonly/readonly-from-mapped-result.mjs
|
|
@@ -1874,18 +1885,18 @@ function Mapped(key, map, options) {
|
|
|
1874
1885
|
}
|
|
1875
1886
|
|
|
1876
1887
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/optional/optional.mjs
|
|
1877
|
-
function RemoveOptional(
|
|
1878
|
-
return CreateType(Discard(
|
|
1888
|
+
function RemoveOptional(schema) {
|
|
1889
|
+
return CreateType(Discard(schema, [OptionalKind]));
|
|
1879
1890
|
}
|
|
1880
|
-
function AddOptional(
|
|
1881
|
-
return CreateType({ ...
|
|
1891
|
+
function AddOptional(schema) {
|
|
1892
|
+
return CreateType({ ...schema, [OptionalKind]: "Optional" });
|
|
1882
1893
|
}
|
|
1883
|
-
function OptionalWithFlag(
|
|
1884
|
-
return F === false ? RemoveOptional(
|
|
1894
|
+
function OptionalWithFlag(schema, F) {
|
|
1895
|
+
return F === false ? RemoveOptional(schema) : AddOptional(schema);
|
|
1885
1896
|
}
|
|
1886
|
-
function Optional(
|
|
1897
|
+
function Optional(schema, enable) {
|
|
1887
1898
|
const F = enable ?? true;
|
|
1888
|
-
return IsMappedResult(
|
|
1899
|
+
return IsMappedResult(schema) ? OptionalFromMappedResult(schema, F) : OptionalWithFlag(schema, F);
|
|
1889
1900
|
}
|
|
1890
1901
|
|
|
1891
1902
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/optional/optional-from-mapped-result.mjs
|
|
@@ -1905,7 +1916,7 @@ function OptionalFromMappedResult(R, F) {
|
|
|
1905
1916
|
|
|
1906
1917
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/intersect/intersect-create.mjs
|
|
1907
1918
|
function IntersectCreate(T, options = {}) {
|
|
1908
|
-
const allObjects = T.every((
|
|
1919
|
+
const allObjects = T.every((schema) => IsObject3(schema));
|
|
1909
1920
|
const clonedUnevaluatedProperties = IsSchema(options.unevaluatedProperties) ? { unevaluatedProperties: options.unevaluatedProperties } : {};
|
|
1910
1921
|
return CreateType(options.unevaluatedProperties === false || IsSchema(options.unevaluatedProperties) || allObjects ? { ...clonedUnevaluatedProperties, [Kind]: "Intersect", type: "object", allOf: T } : { ...clonedUnevaluatedProperties, [Kind]: "Intersect", allOf: T }, options);
|
|
1911
1922
|
}
|
|
@@ -1928,7 +1939,7 @@ function IntersectEvaluated(types, options = {}) {
|
|
|
1928
1939
|
return CreateType(types[0], options);
|
|
1929
1940
|
if (types.length === 0)
|
|
1930
1941
|
return Never(options);
|
|
1931
|
-
if (types.some((
|
|
1942
|
+
if (types.some((schema) => IsTransform(schema)))
|
|
1932
1943
|
throw new Error("Cannot intersect transform types");
|
|
1933
1944
|
return ResolveIntersect(types, options);
|
|
1934
1945
|
}
|
|
@@ -1939,7 +1950,7 @@ function Intersect(types, options) {
|
|
|
1939
1950
|
return CreateType(types[0], options);
|
|
1940
1951
|
if (types.length === 0)
|
|
1941
1952
|
return Never(options);
|
|
1942
|
-
if (types.some((
|
|
1953
|
+
if (types.some((schema) => IsTransform(schema)))
|
|
1943
1954
|
throw new Error("Cannot intersect transform types");
|
|
1944
1955
|
return IntersectCreate(types, options);
|
|
1945
1956
|
}
|
|
@@ -2130,8 +2141,8 @@ function Const(T, options) {
|
|
|
2130
2141
|
}
|
|
2131
2142
|
|
|
2132
2143
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/constructor-parameters/constructor-parameters.mjs
|
|
2133
|
-
function ConstructorParameters(
|
|
2134
|
-
return IsConstructor(
|
|
2144
|
+
function ConstructorParameters(schema, options) {
|
|
2145
|
+
return IsConstructor(schema) ? Tuple(schema.parameters, options) : Never(options);
|
|
2135
2146
|
}
|
|
2136
2147
|
|
|
2137
2148
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/enum/enum.mjs
|
|
@@ -2169,7 +2180,7 @@ function FromAnyRight(left, right) {
|
|
|
2169
2180
|
return ExtendsResult.True;
|
|
2170
2181
|
}
|
|
2171
2182
|
function FromAny(left, right) {
|
|
2172
|
-
return type_exports.IsIntersect(right) ? FromIntersectRight(left, right) : type_exports.IsUnion(right) && right.anyOf.some((
|
|
2183
|
+
return type_exports.IsIntersect(right) ? FromIntersectRight(left, right) : type_exports.IsUnion(right) && right.anyOf.some((schema) => type_exports.IsAny(schema) || type_exports.IsUnknown(schema)) ? ExtendsResult.True : type_exports.IsUnion(right) ? ExtendsResult.Union : type_exports.IsUnknown(right) ? ExtendsResult.True : type_exports.IsAny(right) ? ExtendsResult.True : ExtendsResult.Union;
|
|
2173
2184
|
}
|
|
2174
2185
|
function FromArrayRight(left, right) {
|
|
2175
2186
|
return type_exports.IsUnknown(left) ? ExtendsResult.False : type_exports.IsAny(left) ? ExtendsResult.Union : type_exports.IsNever(left) ? ExtendsResult.True : ExtendsResult.False;
|
|
@@ -2190,13 +2201,13 @@ function FromBoolean(left, right) {
|
|
|
2190
2201
|
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : type_exports.IsRecord(right) ? FromRecordRight(left, right) : type_exports.IsBoolean(right) ? ExtendsResult.True : ExtendsResult.False;
|
|
2191
2202
|
}
|
|
2192
2203
|
function FromConstructor(left, right) {
|
|
2193
|
-
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : !type_exports.IsConstructor(right) ? ExtendsResult.False : left.parameters.length > right.parameters.length ? ExtendsResult.False : !left.parameters.every((
|
|
2204
|
+
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : !type_exports.IsConstructor(right) ? ExtendsResult.False : left.parameters.length > right.parameters.length ? ExtendsResult.False : !left.parameters.every((schema, index9) => IntoBooleanResult(Visit3(right.parameters[index9], schema)) === ExtendsResult.True) ? ExtendsResult.False : IntoBooleanResult(Visit3(left.returns, right.returns));
|
|
2194
2205
|
}
|
|
2195
2206
|
function FromDate(left, right) {
|
|
2196
2207
|
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : type_exports.IsRecord(right) ? FromRecordRight(left, right) : type_exports.IsDate(right) ? ExtendsResult.True : ExtendsResult.False;
|
|
2197
2208
|
}
|
|
2198
2209
|
function FromFunction(left, right) {
|
|
2199
|
-
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : !type_exports.IsFunction(right) ? ExtendsResult.False : left.parameters.length > right.parameters.length ? ExtendsResult.False : !left.parameters.every((
|
|
2210
|
+
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : !type_exports.IsFunction(right) ? ExtendsResult.False : left.parameters.length > right.parameters.length ? ExtendsResult.False : !left.parameters.every((schema, index9) => IntoBooleanResult(Visit3(right.parameters[index9], schema)) === ExtendsResult.True) ? ExtendsResult.False : IntoBooleanResult(Visit3(left.returns, right.returns));
|
|
2200
2211
|
}
|
|
2201
2212
|
function FromIntegerRight(left, right) {
|
|
2202
2213
|
return type_exports.IsLiteral(left) && value_exports.IsNumber(left.const) ? ExtendsResult.True : type_exports.IsNumber(left) || type_exports.IsInteger(left) ? ExtendsResult.True : ExtendsResult.False;
|
|
@@ -2205,10 +2216,10 @@ function FromInteger(left, right) {
|
|
|
2205
2216
|
return type_exports.IsInteger(right) || type_exports.IsNumber(right) ? ExtendsResult.True : IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : type_exports.IsRecord(right) ? FromRecordRight(left, right) : ExtendsResult.False;
|
|
2206
2217
|
}
|
|
2207
2218
|
function FromIntersectRight(left, right) {
|
|
2208
|
-
return right.allOf.every((
|
|
2219
|
+
return right.allOf.every((schema) => Visit3(left, schema) === ExtendsResult.True) ? ExtendsResult.True : ExtendsResult.False;
|
|
2209
2220
|
}
|
|
2210
2221
|
function FromIntersect4(left, right) {
|
|
2211
|
-
return left.allOf.some((
|
|
2222
|
+
return left.allOf.some((schema) => Visit3(schema, right) === ExtendsResult.True) ? ExtendsResult.True : ExtendsResult.False;
|
|
2212
2223
|
}
|
|
2213
2224
|
function FromIterator(left, right) {
|
|
2214
2225
|
return IsStructuralRight(right) ? StructuralRight(left, right) : !type_exports.IsIterator(right) ? ExtendsResult.False : IntoBooleanResult(Visit3(left.items, right.items));
|
|
@@ -2222,8 +2233,8 @@ function FromNeverRight(left, right) {
|
|
|
2222
2233
|
function FromNever(left, right) {
|
|
2223
2234
|
return ExtendsResult.True;
|
|
2224
2235
|
}
|
|
2225
|
-
function UnwrapTNot(
|
|
2226
|
-
let [current, depth] = [
|
|
2236
|
+
function UnwrapTNot(schema) {
|
|
2237
|
+
let [current, depth] = [schema, 0];
|
|
2227
2238
|
while (true) {
|
|
2228
2239
|
if (!type_exports.IsNot(current))
|
|
2229
2240
|
break;
|
|
@@ -2244,44 +2255,44 @@ function FromNumberRight(left, right) {
|
|
|
2244
2255
|
function FromNumber(left, right) {
|
|
2245
2256
|
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : type_exports.IsRecord(right) ? FromRecordRight(left, right) : type_exports.IsInteger(right) || type_exports.IsNumber(right) ? ExtendsResult.True : ExtendsResult.False;
|
|
2246
2257
|
}
|
|
2247
|
-
function IsObjectPropertyCount(
|
|
2248
|
-
return Object.getOwnPropertyNames(
|
|
2258
|
+
function IsObjectPropertyCount(schema, count) {
|
|
2259
|
+
return Object.getOwnPropertyNames(schema.properties).length === count;
|
|
2249
2260
|
}
|
|
2250
|
-
function IsObjectStringLike(
|
|
2251
|
-
return IsObjectArrayLike(
|
|
2261
|
+
function IsObjectStringLike(schema) {
|
|
2262
|
+
return IsObjectArrayLike(schema);
|
|
2252
2263
|
}
|
|
2253
|
-
function IsObjectSymbolLike(
|
|
2254
|
-
return IsObjectPropertyCount(
|
|
2264
|
+
function IsObjectSymbolLike(schema) {
|
|
2265
|
+
return IsObjectPropertyCount(schema, 0) || IsObjectPropertyCount(schema, 1) && "description" in schema.properties && type_exports.IsUnion(schema.properties.description) && schema.properties.description.anyOf.length === 2 && (type_exports.IsString(schema.properties.description.anyOf[0]) && type_exports.IsUndefined(schema.properties.description.anyOf[1]) || type_exports.IsString(schema.properties.description.anyOf[1]) && type_exports.IsUndefined(schema.properties.description.anyOf[0]));
|
|
2255
2266
|
}
|
|
2256
|
-
function IsObjectNumberLike(
|
|
2257
|
-
return IsObjectPropertyCount(
|
|
2267
|
+
function IsObjectNumberLike(schema) {
|
|
2268
|
+
return IsObjectPropertyCount(schema, 0);
|
|
2258
2269
|
}
|
|
2259
|
-
function IsObjectBooleanLike(
|
|
2260
|
-
return IsObjectPropertyCount(
|
|
2270
|
+
function IsObjectBooleanLike(schema) {
|
|
2271
|
+
return IsObjectPropertyCount(schema, 0);
|
|
2261
2272
|
}
|
|
2262
|
-
function IsObjectBigIntLike(
|
|
2263
|
-
return IsObjectPropertyCount(
|
|
2273
|
+
function IsObjectBigIntLike(schema) {
|
|
2274
|
+
return IsObjectPropertyCount(schema, 0);
|
|
2264
2275
|
}
|
|
2265
|
-
function IsObjectDateLike(
|
|
2266
|
-
return IsObjectPropertyCount(
|
|
2276
|
+
function IsObjectDateLike(schema) {
|
|
2277
|
+
return IsObjectPropertyCount(schema, 0);
|
|
2267
2278
|
}
|
|
2268
|
-
function IsObjectUint8ArrayLike(
|
|
2269
|
-
return IsObjectArrayLike(
|
|
2279
|
+
function IsObjectUint8ArrayLike(schema) {
|
|
2280
|
+
return IsObjectArrayLike(schema);
|
|
2270
2281
|
}
|
|
2271
|
-
function IsObjectFunctionLike(
|
|
2282
|
+
function IsObjectFunctionLike(schema) {
|
|
2272
2283
|
const length = Number2();
|
|
2273
|
-
return IsObjectPropertyCount(
|
|
2284
|
+
return IsObjectPropertyCount(schema, 0) || IsObjectPropertyCount(schema, 1) && "length" in schema.properties && IntoBooleanResult(Visit3(schema.properties["length"], length)) === ExtendsResult.True;
|
|
2274
2285
|
}
|
|
2275
|
-
function IsObjectConstructorLike(
|
|
2276
|
-
return IsObjectPropertyCount(
|
|
2286
|
+
function IsObjectConstructorLike(schema) {
|
|
2287
|
+
return IsObjectPropertyCount(schema, 0);
|
|
2277
2288
|
}
|
|
2278
|
-
function IsObjectArrayLike(
|
|
2289
|
+
function IsObjectArrayLike(schema) {
|
|
2279
2290
|
const length = Number2();
|
|
2280
|
-
return IsObjectPropertyCount(
|
|
2291
|
+
return IsObjectPropertyCount(schema, 0) || IsObjectPropertyCount(schema, 1) && "length" in schema.properties && IntoBooleanResult(Visit3(schema.properties["length"], length)) === ExtendsResult.True;
|
|
2281
2292
|
}
|
|
2282
|
-
function IsObjectPromiseLike(
|
|
2293
|
+
function IsObjectPromiseLike(schema) {
|
|
2283
2294
|
const then = Function([Any()], Any());
|
|
2284
|
-
return IsObjectPropertyCount(
|
|
2295
|
+
return IsObjectPropertyCount(schema, 0) || IsObjectPropertyCount(schema, 1) && "then" in schema.properties && IntoBooleanResult(Visit3(schema.properties["then"], then)) === ExtendsResult.True;
|
|
2285
2296
|
}
|
|
2286
2297
|
function Property(left, right) {
|
|
2287
2298
|
return Visit3(left, right) === ExtendsResult.False ? ExtendsResult.False : type_exports.IsOptional(left) && !type_exports.IsOptional(right) ? ExtendsResult.False : ExtendsResult.True;
|
|
@@ -2312,11 +2323,11 @@ function FromObject(left, right) {
|
|
|
2312
2323
|
function FromPromise2(left, right) {
|
|
2313
2324
|
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) && IsObjectPromiseLike(right) ? ExtendsResult.True : !type_exports.IsPromise(right) ? ExtendsResult.False : IntoBooleanResult(Visit3(left.item, right.item));
|
|
2314
2325
|
}
|
|
2315
|
-
function RecordKey(
|
|
2316
|
-
return PatternNumberExact in
|
|
2326
|
+
function RecordKey(schema) {
|
|
2327
|
+
return PatternNumberExact in schema.patternProperties ? Number2() : PatternStringExact in schema.patternProperties ? String2() : Throw("Unknown record key pattern");
|
|
2317
2328
|
}
|
|
2318
|
-
function RecordValue(
|
|
2319
|
-
return PatternNumberExact in
|
|
2329
|
+
function RecordValue(schema) {
|
|
2330
|
+
return PatternNumberExact in schema.patternProperties ? schema.patternProperties[PatternNumberExact] : PatternStringExact in schema.patternProperties ? schema.patternProperties[PatternStringExact] : Throw("Unable to get record value schema");
|
|
2320
2331
|
}
|
|
2321
2332
|
function FromRecordRight(left, right) {
|
|
2322
2333
|
const [Key, Value] = [RecordKey(right), RecordValue(right)];
|
|
@@ -2350,13 +2361,13 @@ function FromTemplateLiteral2(left, right) {
|
|
|
2350
2361
|
return type_exports.IsTemplateLiteral(left) ? Visit3(TemplateLiteralToUnion(left), right) : type_exports.IsTemplateLiteral(right) ? Visit3(left, TemplateLiteralToUnion(right)) : Throw("Invalid fallthrough for TemplateLiteral");
|
|
2351
2362
|
}
|
|
2352
2363
|
function IsArrayOfTuple(left, right) {
|
|
2353
|
-
return type_exports.IsArray(right) && left.items !== void 0 && left.items.every((
|
|
2364
|
+
return type_exports.IsArray(right) && left.items !== void 0 && left.items.every((schema) => Visit3(schema, right.items) === ExtendsResult.True);
|
|
2354
2365
|
}
|
|
2355
2366
|
function FromTupleRight(left, right) {
|
|
2356
2367
|
return type_exports.IsNever(left) ? ExtendsResult.True : type_exports.IsUnknown(left) ? ExtendsResult.False : type_exports.IsAny(left) ? ExtendsResult.Union : ExtendsResult.False;
|
|
2357
2368
|
}
|
|
2358
2369
|
function FromTuple3(left, right) {
|
|
2359
|
-
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) && IsObjectArrayLike(right) ? ExtendsResult.True : type_exports.IsArray(right) && IsArrayOfTuple(left, right) ? ExtendsResult.True : !type_exports.IsTuple(right) ? ExtendsResult.False : value_exports.IsUndefined(left.items) && !value_exports.IsUndefined(right.items) || !value_exports.IsUndefined(left.items) && value_exports.IsUndefined(right.items) ? ExtendsResult.False : value_exports.IsUndefined(left.items) && !value_exports.IsUndefined(right.items) ? ExtendsResult.True : left.items.every((
|
|
2370
|
+
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) && IsObjectArrayLike(right) ? ExtendsResult.True : type_exports.IsArray(right) && IsArrayOfTuple(left, right) ? ExtendsResult.True : !type_exports.IsTuple(right) ? ExtendsResult.False : value_exports.IsUndefined(left.items) && !value_exports.IsUndefined(right.items) || !value_exports.IsUndefined(left.items) && value_exports.IsUndefined(right.items) ? ExtendsResult.False : value_exports.IsUndefined(left.items) && !value_exports.IsUndefined(right.items) ? ExtendsResult.True : left.items.every((schema, index9) => Visit3(schema, right.items[index9]) === ExtendsResult.True) ? ExtendsResult.True : ExtendsResult.False;
|
|
2360
2371
|
}
|
|
2361
2372
|
function FromUint8Array(left, right) {
|
|
2362
2373
|
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : type_exports.IsRecord(right) ? FromRecordRight(left, right) : type_exports.IsUint8Array(right) ? ExtendsResult.True : ExtendsResult.False;
|
|
@@ -2365,10 +2376,10 @@ function FromUndefined(left, right) {
|
|
|
2365
2376
|
return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : type_exports.IsRecord(right) ? FromRecordRight(left, right) : type_exports.IsVoid(right) ? FromVoidRight(left, right) : type_exports.IsUndefined(right) ? ExtendsResult.True : ExtendsResult.False;
|
|
2366
2377
|
}
|
|
2367
2378
|
function FromUnionRight(left, right) {
|
|
2368
|
-
return right.anyOf.some((
|
|
2379
|
+
return right.anyOf.some((schema) => Visit3(left, schema) === ExtendsResult.True) ? ExtendsResult.True : ExtendsResult.False;
|
|
2369
2380
|
}
|
|
2370
2381
|
function FromUnion6(left, right) {
|
|
2371
|
-
return left.anyOf.every((
|
|
2382
|
+
return left.anyOf.every((schema) => Visit3(schema, right) === ExtendsResult.True) ? ExtendsResult.True : ExtendsResult.False;
|
|
2372
2383
|
}
|
|
2373
2384
|
function FromUnknownRight(left, right) {
|
|
2374
2385
|
return ExtendsResult.True;
|
|
@@ -2505,13 +2516,13 @@ function ExtractFromMappedResult(R, T) {
|
|
|
2505
2516
|
}
|
|
2506
2517
|
|
|
2507
2518
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/instance-type/instance-type.mjs
|
|
2508
|
-
function InstanceType(
|
|
2509
|
-
return IsConstructor(
|
|
2519
|
+
function InstanceType(schema, options) {
|
|
2520
|
+
return IsConstructor(schema) ? CreateType(schema.returns, options) : Never(options);
|
|
2510
2521
|
}
|
|
2511
2522
|
|
|
2512
2523
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/readonly-optional/readonly-optional.mjs
|
|
2513
|
-
function ReadonlyOptional(
|
|
2514
|
-
return Readonly(Optional(
|
|
2524
|
+
function ReadonlyOptional(schema) {
|
|
2525
|
+
return Readonly(Optional(schema));
|
|
2515
2526
|
}
|
|
2516
2527
|
|
|
2517
2528
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/record/record.mjs
|
|
@@ -2684,11 +2695,11 @@ function ApplyUppercase(value) {
|
|
|
2684
2695
|
function ApplyLowercase(value) {
|
|
2685
2696
|
return value.toLowerCase();
|
|
2686
2697
|
}
|
|
2687
|
-
function FromTemplateLiteral3(
|
|
2688
|
-
const expression = TemplateLiteralParseExact(
|
|
2698
|
+
function FromTemplateLiteral3(schema, mode, options) {
|
|
2699
|
+
const expression = TemplateLiteralParseExact(schema.pattern);
|
|
2689
2700
|
const finite = IsTemplateLiteralExpressionFinite(expression);
|
|
2690
2701
|
if (!finite)
|
|
2691
|
-
return { ...
|
|
2702
|
+
return { ...schema, pattern: FromLiteralValue(schema.pattern, mode) };
|
|
2692
2703
|
const strings = [...TemplateLiteralExpressionGenerate(expression)];
|
|
2693
2704
|
const literals = strings.map((value) => Literal(value));
|
|
2694
2705
|
const mapped = FromRest5(literals, mode);
|
|
@@ -2701,14 +2712,14 @@ function FromLiteralValue(value, mode) {
|
|
|
2701
2712
|
function FromRest5(T, M) {
|
|
2702
2713
|
return T.map((L) => Intrinsic(L, M));
|
|
2703
2714
|
}
|
|
2704
|
-
function Intrinsic(
|
|
2715
|
+
function Intrinsic(schema, mode, options = {}) {
|
|
2705
2716
|
return (
|
|
2706
2717
|
// Intrinsic-Mapped-Inference
|
|
2707
|
-
IsMappedKey(
|
|
2718
|
+
IsMappedKey(schema) ? IntrinsicFromMappedKey(schema, mode, options) : (
|
|
2708
2719
|
// Standard-Inference
|
|
2709
|
-
IsTemplateLiteral(
|
|
2720
|
+
IsTemplateLiteral(schema) ? FromTemplateLiteral3(schema, mode, options) : IsUnion(schema) ? Union(FromRest5(schema.anyOf, mode), options) : IsLiteral(schema) ? Literal(FromLiteralValue(schema.const, mode), options) : (
|
|
2710
2721
|
// Default Type
|
|
2711
|
-
CreateType(
|
|
2722
|
+
CreateType(schema, options)
|
|
2712
2723
|
)
|
|
2713
2724
|
)
|
|
2714
2725
|
);
|
|
@@ -3105,8 +3116,8 @@ function Not(type, options) {
|
|
|
3105
3116
|
}
|
|
3106
3117
|
|
|
3107
3118
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/parameters/parameters.mjs
|
|
3108
|
-
function Parameters(
|
|
3109
|
-
return IsFunction2(
|
|
3119
|
+
function Parameters(schema, options) {
|
|
3120
|
+
return IsFunction2(schema) ? Tuple(schema.parameters, options) : Never();
|
|
3110
3121
|
}
|
|
3111
3122
|
|
|
3112
3123
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/recursive/recursive.mjs
|
|
@@ -3134,40 +3145,40 @@ function Rest(T) {
|
|
|
3134
3145
|
}
|
|
3135
3146
|
|
|
3136
3147
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/return-type/return-type.mjs
|
|
3137
|
-
function ReturnType(
|
|
3138
|
-
return IsFunction2(
|
|
3148
|
+
function ReturnType(schema, options) {
|
|
3149
|
+
return IsFunction2(schema) ? CreateType(schema.returns, options) : Never(options);
|
|
3139
3150
|
}
|
|
3140
3151
|
|
|
3141
3152
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/transform/transform.mjs
|
|
3142
3153
|
var TransformDecodeBuilder = class {
|
|
3143
|
-
constructor(
|
|
3144
|
-
this.schema =
|
|
3154
|
+
constructor(schema) {
|
|
3155
|
+
this.schema = schema;
|
|
3145
3156
|
}
|
|
3146
3157
|
Decode(decode) {
|
|
3147
3158
|
return new TransformEncodeBuilder(this.schema, decode);
|
|
3148
3159
|
}
|
|
3149
3160
|
};
|
|
3150
3161
|
var TransformEncodeBuilder = class {
|
|
3151
|
-
constructor(
|
|
3152
|
-
this.schema =
|
|
3162
|
+
constructor(schema, decode) {
|
|
3163
|
+
this.schema = schema;
|
|
3153
3164
|
this.decode = decode;
|
|
3154
3165
|
}
|
|
3155
|
-
EncodeTransform(encode,
|
|
3156
|
-
const Encode = (value) =>
|
|
3157
|
-
const Decode = (value) => this.decode(
|
|
3166
|
+
EncodeTransform(encode, schema) {
|
|
3167
|
+
const Encode = (value) => schema[TransformKind].Encode(encode(value));
|
|
3168
|
+
const Decode = (value) => this.decode(schema[TransformKind].Decode(value));
|
|
3158
3169
|
const Codec = { Encode, Decode };
|
|
3159
|
-
return { ...
|
|
3170
|
+
return { ...schema, [TransformKind]: Codec };
|
|
3160
3171
|
}
|
|
3161
|
-
EncodeSchema(encode,
|
|
3172
|
+
EncodeSchema(encode, schema) {
|
|
3162
3173
|
const Codec = { Decode: this.decode, Encode: encode };
|
|
3163
|
-
return { ...
|
|
3174
|
+
return { ...schema, [TransformKind]: Codec };
|
|
3164
3175
|
}
|
|
3165
3176
|
Encode(encode) {
|
|
3166
3177
|
return IsTransform(this.schema) ? this.EncodeTransform(encode, this.schema) : this.EncodeSchema(encode, this.schema);
|
|
3167
3178
|
}
|
|
3168
3179
|
};
|
|
3169
|
-
function Transform(
|
|
3170
|
-
return new TransformDecodeBuilder(
|
|
3180
|
+
function Transform(schema) {
|
|
3181
|
+
return new TransformDecodeBuilder(schema);
|
|
3171
3182
|
}
|
|
3172
3183
|
|
|
3173
3184
|
// ../../node_modules/.pnpm/@sinclair+typebox@0.34.41/node_modules/@sinclair/typebox/build/esm/type/unsafe/unsafe.mjs
|
|
@@ -3545,6 +3556,33 @@ var changePasswordContract = {
|
|
|
3545
3556
|
})
|
|
3546
3557
|
)
|
|
3547
3558
|
};
|
|
3559
|
+
var getMeContract = {
|
|
3560
|
+
method: "GET",
|
|
3561
|
+
path: "/_auth/me",
|
|
3562
|
+
body: Type.Object({}),
|
|
3563
|
+
response: ApiResponseSchema(
|
|
3564
|
+
Type.Object({
|
|
3565
|
+
userId: Type.String({ description: "User ID" }),
|
|
3566
|
+
email: Type.Optional(Type.String({ description: "User email address" })),
|
|
3567
|
+
phone: Type.Optional(Type.String({ description: "User phone number" })),
|
|
3568
|
+
role: Type.Object({
|
|
3569
|
+
id: Type.Number({ description: "Role ID" }),
|
|
3570
|
+
name: Type.String({ description: "Role name (e.g., user, admin)" }),
|
|
3571
|
+
displayName: Type.String({ description: "Display name for UI" }),
|
|
3572
|
+
priority: Type.Number({ description: "Role priority level" })
|
|
3573
|
+
}, { description: "User role information" }),
|
|
3574
|
+
permissions: Type.Array(
|
|
3575
|
+
Type.Object({
|
|
3576
|
+
id: Type.Number({ description: "Permission ID" }),
|
|
3577
|
+
name: Type.String({ description: "Permission name (e.g., user:delete)" }),
|
|
3578
|
+
displayName: Type.String({ description: "Display name for UI" }),
|
|
3579
|
+
category: Type.Optional(Type.String({ description: "Permission category" }))
|
|
3580
|
+
}),
|
|
3581
|
+
{ description: "List of permissions granted through role" }
|
|
3582
|
+
)
|
|
3583
|
+
})
|
|
3584
|
+
)
|
|
3585
|
+
};
|
|
3548
3586
|
|
|
3549
3587
|
// src/lib/contracts/invitation.ts
|
|
3550
3588
|
var UUID_PATTERN2 = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
|
|
@@ -3778,216 +3816,6 @@ var deleteInvitationContract = {
|
|
|
3778
3816
|
)
|
|
3779
3817
|
};
|
|
3780
3818
|
|
|
3781
|
-
// src/server/helpers/jwt.ts
|
|
3782
|
-
import jwt from "jsonwebtoken";
|
|
3783
|
-
import crypto from "crypto";
|
|
3784
|
-
var JWT_SECRET = process.env.SPFN_AUTH_JWT_SECRET || // New prefixed version (recommended)
|
|
3785
|
-
process.env.JWT_SECRET || // Legacy fallback
|
|
3786
|
-
"dev-secret-key-change-in-production";
|
|
3787
|
-
var JWT_EXPIRES_IN = process.env.SPFN_AUTH_JWT_EXPIRES_IN || // New prefixed version (recommended)
|
|
3788
|
-
process.env.JWT_EXPIRES_IN || // Legacy fallback
|
|
3789
|
-
"7d";
|
|
3790
|
-
function verifyClientToken(token, publicKeyB64, algorithm) {
|
|
3791
|
-
try {
|
|
3792
|
-
const publicKeyDER = Buffer.from(publicKeyB64, "base64");
|
|
3793
|
-
const publicKeyObject = crypto.createPublicKey({
|
|
3794
|
-
key: publicKeyDER,
|
|
3795
|
-
format: "der",
|
|
3796
|
-
type: "spki"
|
|
3797
|
-
});
|
|
3798
|
-
const decoded = jwt.verify(token, publicKeyObject, {
|
|
3799
|
-
algorithms: [algorithm],
|
|
3800
|
-
// Prevent algorithm confusion attacks
|
|
3801
|
-
issuer: "spfn-client"
|
|
3802
|
-
// Validate token issuer
|
|
3803
|
-
});
|
|
3804
|
-
if (typeof decoded === "string") {
|
|
3805
|
-
throw new Error("Invalid token format: expected object payload");
|
|
3806
|
-
}
|
|
3807
|
-
return decoded;
|
|
3808
|
-
} catch (error) {
|
|
3809
|
-
if (error instanceof jwt.TokenExpiredError) {
|
|
3810
|
-
throw new Error("Token has expired");
|
|
3811
|
-
}
|
|
3812
|
-
if (error instanceof jwt.JsonWebTokenError) {
|
|
3813
|
-
throw new Error("Invalid token signature");
|
|
3814
|
-
}
|
|
3815
|
-
throw new Error(`Token verification failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3816
|
-
}
|
|
3817
|
-
}
|
|
3818
|
-
function verifyKeyFingerprint(publicKeyB64, expectedFingerprint) {
|
|
3819
|
-
try {
|
|
3820
|
-
const publicKeyDER = Buffer.from(publicKeyB64, "base64");
|
|
3821
|
-
const fingerprint = crypto.createHash("sha256").update(publicKeyDER).digest("hex");
|
|
3822
|
-
return fingerprint === expectedFingerprint;
|
|
3823
|
-
} catch (error) {
|
|
3824
|
-
console.error("Failed to verify key fingerprint:", error);
|
|
3825
|
-
return false;
|
|
3826
|
-
}
|
|
3827
|
-
}
|
|
3828
|
-
|
|
3829
|
-
// src/server/middleware/authenticate.ts
|
|
3830
|
-
init_entities();
|
|
3831
|
-
import { findOne, getDatabase } from "@spfn/core/db";
|
|
3832
|
-
|
|
3833
|
-
// src/server/errors/auth-errors.ts
|
|
3834
|
-
import {
|
|
3835
|
-
ValidationError,
|
|
3836
|
-
UnauthorizedError,
|
|
3837
|
-
ForbiddenError,
|
|
3838
|
-
ConflictError
|
|
3839
|
-
} from "@spfn/core/errors";
|
|
3840
|
-
var InvalidCredentialsError = class extends UnauthorizedError {
|
|
3841
|
-
constructor(message = "Invalid credentials") {
|
|
3842
|
-
super(message);
|
|
3843
|
-
this.name = "InvalidCredentialsError";
|
|
3844
|
-
}
|
|
3845
|
-
};
|
|
3846
|
-
var InvalidTokenError = class extends UnauthorizedError {
|
|
3847
|
-
constructor(message = "Invalid authentication token") {
|
|
3848
|
-
super(message);
|
|
3849
|
-
this.name = "InvalidTokenError";
|
|
3850
|
-
}
|
|
3851
|
-
};
|
|
3852
|
-
var TokenExpiredError = class extends UnauthorizedError {
|
|
3853
|
-
constructor(message = "Authentication token has expired") {
|
|
3854
|
-
super(message);
|
|
3855
|
-
this.name = "TokenExpiredError";
|
|
3856
|
-
}
|
|
3857
|
-
};
|
|
3858
|
-
var KeyExpiredError = class extends UnauthorizedError {
|
|
3859
|
-
constructor(message = "Public key has expired") {
|
|
3860
|
-
super(message);
|
|
3861
|
-
this.name = "KeyExpiredError";
|
|
3862
|
-
}
|
|
3863
|
-
};
|
|
3864
|
-
var AccountDisabledError = class extends ForbiddenError {
|
|
3865
|
-
constructor(status = "disabled") {
|
|
3866
|
-
super(`Account is ${status}`);
|
|
3867
|
-
this.name = "AccountDisabledError";
|
|
3868
|
-
this.details = { status };
|
|
3869
|
-
}
|
|
3870
|
-
};
|
|
3871
|
-
var AccountAlreadyExistsError = class extends ConflictError {
|
|
3872
|
-
constructor(identifier, identifierType) {
|
|
3873
|
-
super("Account already exists");
|
|
3874
|
-
this.name = "AccountAlreadyExistsError";
|
|
3875
|
-
this.details = { identifier, identifierType };
|
|
3876
|
-
}
|
|
3877
|
-
};
|
|
3878
|
-
var InvalidVerificationCodeError = class extends ValidationError {
|
|
3879
|
-
constructor(reason = "Invalid verification code") {
|
|
3880
|
-
super(reason);
|
|
3881
|
-
this.name = "InvalidVerificationCodeError";
|
|
3882
|
-
}
|
|
3883
|
-
};
|
|
3884
|
-
var InvalidVerificationTokenError = class extends ValidationError {
|
|
3885
|
-
constructor(message = "Invalid or expired verification token") {
|
|
3886
|
-
super(message);
|
|
3887
|
-
this.name = "InvalidVerificationTokenError";
|
|
3888
|
-
}
|
|
3889
|
-
};
|
|
3890
|
-
var InvalidKeyFingerprintError = class extends ValidationError {
|
|
3891
|
-
constructor(message = "Invalid key fingerprint") {
|
|
3892
|
-
super(message);
|
|
3893
|
-
this.name = "InvalidKeyFingerprintError";
|
|
3894
|
-
}
|
|
3895
|
-
};
|
|
3896
|
-
var VerificationTokenPurposeMismatchError = class extends ValidationError {
|
|
3897
|
-
constructor(expected, actual) {
|
|
3898
|
-
super(`Verification token is for ${actual}, but ${expected} was expected`);
|
|
3899
|
-
this.name = "VerificationTokenPurposeMismatchError";
|
|
3900
|
-
this.details = { expected, actual };
|
|
3901
|
-
}
|
|
3902
|
-
};
|
|
3903
|
-
var VerificationTokenTargetMismatchError = class extends ValidationError {
|
|
3904
|
-
constructor() {
|
|
3905
|
-
super("Verification token does not match provided email/phone");
|
|
3906
|
-
this.name = "VerificationTokenTargetMismatchError";
|
|
3907
|
-
}
|
|
3908
|
-
};
|
|
3909
|
-
|
|
3910
|
-
// src/server/middleware/authenticate.ts
|
|
3911
|
-
import { UnauthorizedError as UnauthorizedError2 } from "@spfn/core/errors";
|
|
3912
|
-
import { eq, and } from "drizzle-orm";
|
|
3913
|
-
async function authenticate(c, next) {
|
|
3914
|
-
const authHeader = c.req.header("Authorization");
|
|
3915
|
-
const keyId = c.req.header("X-Key-Id");
|
|
3916
|
-
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
3917
|
-
throw new UnauthorizedError2("Missing or invalid authorization header");
|
|
3918
|
-
}
|
|
3919
|
-
if (!keyId) {
|
|
3920
|
-
throw new UnauthorizedError2("Missing X-Key-Id header");
|
|
3921
|
-
}
|
|
3922
|
-
const token = authHeader.substring(7);
|
|
3923
|
-
const db = getDatabase();
|
|
3924
|
-
const [keyRecord] = await db.select().from(userPublicKeys).where(
|
|
3925
|
-
and(
|
|
3926
|
-
eq(userPublicKeys.keyId, keyId),
|
|
3927
|
-
eq(userPublicKeys.isActive, true)
|
|
3928
|
-
)
|
|
3929
|
-
);
|
|
3930
|
-
if (!keyRecord) {
|
|
3931
|
-
throw new UnauthorizedError2("Invalid or revoked key");
|
|
3932
|
-
}
|
|
3933
|
-
if (keyRecord.expiresAt && /* @__PURE__ */ new Date() > keyRecord.expiresAt) {
|
|
3934
|
-
throw new KeyExpiredError();
|
|
3935
|
-
}
|
|
3936
|
-
try {
|
|
3937
|
-
verifyClientToken(
|
|
3938
|
-
token,
|
|
3939
|
-
keyRecord.publicKey,
|
|
3940
|
-
keyRecord.algorithm
|
|
3941
|
-
);
|
|
3942
|
-
} catch (err) {
|
|
3943
|
-
if (err instanceof Error) {
|
|
3944
|
-
if (err.name === "TokenExpiredError") {
|
|
3945
|
-
throw new TokenExpiredError();
|
|
3946
|
-
}
|
|
3947
|
-
if (err.name === "JsonWebTokenError") {
|
|
3948
|
-
throw new InvalidTokenError("Invalid token signature");
|
|
3949
|
-
}
|
|
3950
|
-
}
|
|
3951
|
-
throw new UnauthorizedError2("Authentication failed");
|
|
3952
|
-
}
|
|
3953
|
-
const user = await findOne(users, { id: keyRecord.userId });
|
|
3954
|
-
if (!user) {
|
|
3955
|
-
throw new UnauthorizedError2("User not found");
|
|
3956
|
-
}
|
|
3957
|
-
if (user.status !== "active") {
|
|
3958
|
-
throw new AccountDisabledError(user.status);
|
|
3959
|
-
}
|
|
3960
|
-
db.update(userPublicKeys).set({ lastUsedAt: /* @__PURE__ */ new Date() }).where(eq(userPublicKeys.id, keyRecord.id)).execute().catch((err) => console.error("Failed to update lastUsedAt:", err));
|
|
3961
|
-
c.set("auth", {
|
|
3962
|
-
user,
|
|
3963
|
-
userId: String(user.id),
|
|
3964
|
-
keyId
|
|
3965
|
-
});
|
|
3966
|
-
await next();
|
|
3967
|
-
}
|
|
3968
|
-
|
|
3969
|
-
// src/server/helpers/context.ts
|
|
3970
|
-
function getAuth(c) {
|
|
3971
|
-
if ("raw" in c && c.raw) {
|
|
3972
|
-
return c.raw.get("auth");
|
|
3973
|
-
}
|
|
3974
|
-
return c.get("auth");
|
|
3975
|
-
}
|
|
3976
|
-
function getUser(c) {
|
|
3977
|
-
return getAuth(c).user;
|
|
3978
|
-
}
|
|
3979
|
-
|
|
3980
|
-
// src/server/services/permission.service.ts
|
|
3981
|
-
init_entities();
|
|
3982
|
-
import { getDatabase as getDatabase2 } from "@spfn/core/db";
|
|
3983
|
-
import { eq as eq2, and as and2 } from "drizzle-orm";
|
|
3984
|
-
|
|
3985
|
-
// src/server/middleware/require-permission.ts
|
|
3986
|
-
import { ForbiddenError as ForbiddenError2 } from "@spfn/core/errors";
|
|
3987
|
-
|
|
3988
|
-
// src/server/middleware/require-role.ts
|
|
3989
|
-
import { ForbiddenError as ForbiddenError3 } from "@spfn/core/errors";
|
|
3990
|
-
|
|
3991
3819
|
// src/server/helpers/password.ts
|
|
3992
3820
|
import bcrypt from "bcrypt";
|
|
3993
3821
|
var SALT_ROUNDS = parseInt(
|
|
@@ -4012,11 +3840,31 @@ async function verifyPassword(password, hash) {
|
|
|
4012
3840
|
return bcrypt.compare(password, hash);
|
|
4013
3841
|
}
|
|
4014
3842
|
|
|
3843
|
+
// src/server/helpers/jwt.ts
|
|
3844
|
+
import jwt from "jsonwebtoken";
|
|
3845
|
+
import crypto from "crypto";
|
|
3846
|
+
var JWT_SECRET = process.env.SPFN_AUTH_JWT_SECRET || // New prefixed version (recommended)
|
|
3847
|
+
process.env.JWT_SECRET || // Legacy fallback
|
|
3848
|
+
"dev-secret-key-change-in-production";
|
|
3849
|
+
var JWT_EXPIRES_IN = process.env.SPFN_AUTH_JWT_EXPIRES_IN || // New prefixed version (recommended)
|
|
3850
|
+
process.env.JWT_EXPIRES_IN || // Legacy fallback
|
|
3851
|
+
"7d";
|
|
3852
|
+
function verifyKeyFingerprint(publicKeyB64, expectedFingerprint) {
|
|
3853
|
+
try {
|
|
3854
|
+
const publicKeyDER = Buffer.from(publicKeyB64, "base64");
|
|
3855
|
+
const fingerprint = crypto.createHash("sha256").update(publicKeyDER).digest("hex");
|
|
3856
|
+
return fingerprint === expectedFingerprint;
|
|
3857
|
+
} catch (error) {
|
|
3858
|
+
console.error("Failed to verify key fingerprint:", error);
|
|
3859
|
+
return false;
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
|
|
4015
3863
|
// src/server/helpers/verification.ts
|
|
4016
3864
|
init_verification_codes();
|
|
4017
3865
|
import jwt2 from "jsonwebtoken";
|
|
4018
|
-
import { getDatabase
|
|
4019
|
-
import { eq
|
|
3866
|
+
import { getDatabase, create } from "@spfn/core/db";
|
|
3867
|
+
import { eq, and } from "drizzle-orm";
|
|
4020
3868
|
function getVerificationTokenSecret() {
|
|
4021
3869
|
const secret = process.env.SPFN_AUTH_VERIFICATION_TOKEN_SECRET || // New prefixed version (recommended)
|
|
4022
3870
|
process.env.VERIFICATION_TOKEN_SECRET || // Legacy fallback
|
|
@@ -4035,7 +3883,7 @@ function generateVerificationCode() {
|
|
|
4035
3883
|
return code;
|
|
4036
3884
|
}
|
|
4037
3885
|
async function storeVerificationCode(target, targetType, code, purpose) {
|
|
4038
|
-
const db =
|
|
3886
|
+
const db = getDatabase();
|
|
4039
3887
|
if (!db) {
|
|
4040
3888
|
throw new Error("Database not initialized");
|
|
4041
3889
|
}
|
|
@@ -4052,16 +3900,16 @@ async function storeVerificationCode(target, targetType, code, purpose) {
|
|
|
4052
3900
|
return record;
|
|
4053
3901
|
}
|
|
4054
3902
|
async function validateVerificationCode(target, targetType, code, purpose) {
|
|
4055
|
-
const db =
|
|
3903
|
+
const db = getDatabase();
|
|
4056
3904
|
if (!db) {
|
|
4057
3905
|
throw new Error("Database not initialized");
|
|
4058
3906
|
}
|
|
4059
3907
|
const records = await db.select().from(verificationCodes).where(
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
3908
|
+
and(
|
|
3909
|
+
eq(verificationCodes.target, target),
|
|
3910
|
+
eq(verificationCodes.targetType, targetType),
|
|
3911
|
+
eq(verificationCodes.code, code),
|
|
3912
|
+
eq(verificationCodes.purpose, purpose)
|
|
4065
3913
|
)
|
|
4066
3914
|
).limit(1);
|
|
4067
3915
|
if (records.length === 0) {
|
|
@@ -4078,15 +3926,15 @@ async function validateVerificationCode(target, targetType, code, purpose) {
|
|
|
4078
3926
|
if (attempts >= MAX_VERIFICATION_ATTEMPTS) {
|
|
4079
3927
|
return { valid: false, error: "Too many attempts, please request a new code" };
|
|
4080
3928
|
}
|
|
4081
|
-
await db.update(verificationCodes).set({ attempts: (attempts + 1).toString() }).where(
|
|
3929
|
+
await db.update(verificationCodes).set({ attempts: (attempts + 1).toString() }).where(eq(verificationCodes.id, record.id));
|
|
4082
3930
|
return { valid: true, codeId: record.id };
|
|
4083
3931
|
}
|
|
4084
3932
|
async function markCodeAsUsed(codeId) {
|
|
4085
|
-
const db =
|
|
3933
|
+
const db = getDatabase();
|
|
4086
3934
|
if (!db) {
|
|
4087
3935
|
throw new Error("Database not initialized");
|
|
4088
3936
|
}
|
|
4089
|
-
await db.update(verificationCodes).set({ usedAt: /* @__PURE__ */ new Date() }).where(
|
|
3937
|
+
await db.update(verificationCodes).set({ usedAt: /* @__PURE__ */ new Date() }).where(eq(verificationCodes.id, codeId));
|
|
4090
3938
|
}
|
|
4091
3939
|
function createVerificationToken(payload) {
|
|
4092
3940
|
const secret = getVerificationTokenSecret();
|
|
@@ -4119,15 +3967,82 @@ async function sendVerificationSMS(phone, code, purpose) {
|
|
|
4119
3967
|
console.log(`[VERIFICATION SMS] To: ${phone}, Code: ${code}, Purpose: ${purpose}`);
|
|
4120
3968
|
}
|
|
4121
3969
|
|
|
3970
|
+
// src/server/helpers/context.ts
|
|
3971
|
+
function getAuth(c) {
|
|
3972
|
+
if ("raw" in c && c.raw) {
|
|
3973
|
+
return c.raw.get("auth");
|
|
3974
|
+
}
|
|
3975
|
+
return c.get("auth");
|
|
3976
|
+
}
|
|
3977
|
+
function getUser(c) {
|
|
3978
|
+
return getAuth(c).user;
|
|
3979
|
+
}
|
|
3980
|
+
|
|
4122
3981
|
// src/server/services/auth.service.ts
|
|
4123
3982
|
init_entities();
|
|
4124
|
-
import { findOne as
|
|
3983
|
+
import { findOne as findOne2, create as create3 } from "@spfn/core/db";
|
|
4125
3984
|
import { ValidationError as ValidationError2 } from "@spfn/core/errors";
|
|
4126
3985
|
|
|
3986
|
+
// src/server/errors/auth-errors.ts
|
|
3987
|
+
import {
|
|
3988
|
+
ValidationError,
|
|
3989
|
+
UnauthorizedError,
|
|
3990
|
+
ForbiddenError,
|
|
3991
|
+
ConflictError
|
|
3992
|
+
} from "@spfn/core/errors";
|
|
3993
|
+
var InvalidCredentialsError = class extends UnauthorizedError {
|
|
3994
|
+
constructor(message = "Invalid credentials") {
|
|
3995
|
+
super(message);
|
|
3996
|
+
this.name = "InvalidCredentialsError";
|
|
3997
|
+
}
|
|
3998
|
+
};
|
|
3999
|
+
var AccountDisabledError = class extends ForbiddenError {
|
|
4000
|
+
constructor(status = "disabled") {
|
|
4001
|
+
super(`Account is ${status}`, { details: { status } });
|
|
4002
|
+
this.name = "AccountDisabledError";
|
|
4003
|
+
}
|
|
4004
|
+
};
|
|
4005
|
+
var AccountAlreadyExistsError = class extends ConflictError {
|
|
4006
|
+
constructor(identifier, identifierType) {
|
|
4007
|
+
super("Account already exists", { details: { identifier, identifierType } });
|
|
4008
|
+
this.name = "AccountAlreadyExistsError";
|
|
4009
|
+
}
|
|
4010
|
+
};
|
|
4011
|
+
var InvalidVerificationCodeError = class extends ValidationError {
|
|
4012
|
+
constructor(reason = "Invalid verification code") {
|
|
4013
|
+
super(reason);
|
|
4014
|
+
this.name = "InvalidVerificationCodeError";
|
|
4015
|
+
}
|
|
4016
|
+
};
|
|
4017
|
+
var InvalidVerificationTokenError = class extends ValidationError {
|
|
4018
|
+
constructor(message = "Invalid or expired verification token") {
|
|
4019
|
+
super(message);
|
|
4020
|
+
this.name = "InvalidVerificationTokenError";
|
|
4021
|
+
}
|
|
4022
|
+
};
|
|
4023
|
+
var InvalidKeyFingerprintError = class extends ValidationError {
|
|
4024
|
+
constructor(message = "Invalid key fingerprint") {
|
|
4025
|
+
super(message);
|
|
4026
|
+
this.name = "InvalidKeyFingerprintError";
|
|
4027
|
+
}
|
|
4028
|
+
};
|
|
4029
|
+
var VerificationTokenPurposeMismatchError = class extends ValidationError {
|
|
4030
|
+
constructor(expected, actual) {
|
|
4031
|
+
super(`Verification token is for ${actual}, but ${expected} was expected`, { details: { expected, actual } });
|
|
4032
|
+
this.name = "VerificationTokenPurposeMismatchError";
|
|
4033
|
+
}
|
|
4034
|
+
};
|
|
4035
|
+
var VerificationTokenTargetMismatchError = class extends ValidationError {
|
|
4036
|
+
constructor() {
|
|
4037
|
+
super("Verification token does not match provided email/phone");
|
|
4038
|
+
this.name = "VerificationTokenTargetMismatchError";
|
|
4039
|
+
}
|
|
4040
|
+
};
|
|
4041
|
+
|
|
4127
4042
|
// src/server/services/key.service.ts
|
|
4128
4043
|
init_entities();
|
|
4129
|
-
import { create as create2, getDatabase as
|
|
4130
|
-
import { eq as
|
|
4044
|
+
import { create as create2, getDatabase as getDatabase2 } from "@spfn/core/db";
|
|
4045
|
+
import { eq as eq2, and as and2 } from "drizzle-orm";
|
|
4131
4046
|
function getKeyExpiryDate() {
|
|
4132
4047
|
const expiresAt = /* @__PURE__ */ new Date();
|
|
4133
4048
|
expiresAt.setDate(expiresAt.getDate() + 90);
|
|
@@ -4156,15 +4071,15 @@ async function rotateKeyService(params) {
|
|
|
4156
4071
|
if (!isValidFingerprint) {
|
|
4157
4072
|
throw new InvalidKeyFingerprintError();
|
|
4158
4073
|
}
|
|
4159
|
-
const db =
|
|
4074
|
+
const db = getDatabase2();
|
|
4160
4075
|
await db.update(userPublicKeys).set({
|
|
4161
4076
|
isActive: false,
|
|
4162
4077
|
revokedAt: /* @__PURE__ */ new Date(),
|
|
4163
4078
|
revokedReason: "Replaced by key rotation"
|
|
4164
4079
|
}).where(
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4080
|
+
and2(
|
|
4081
|
+
eq2(userPublicKeys.keyId, oldKeyId),
|
|
4082
|
+
eq2(userPublicKeys.userId, userId)
|
|
4168
4083
|
)
|
|
4169
4084
|
);
|
|
4170
4085
|
await create2(userPublicKeys, {
|
|
@@ -4184,22 +4099,22 @@ async function rotateKeyService(params) {
|
|
|
4184
4099
|
}
|
|
4185
4100
|
async function revokeKeyService(params) {
|
|
4186
4101
|
const { userId, keyId, reason } = params;
|
|
4187
|
-
const db =
|
|
4102
|
+
const db = getDatabase2();
|
|
4188
4103
|
await db.update(userPublicKeys).set({
|
|
4189
4104
|
isActive: false,
|
|
4190
4105
|
revokedAt: /* @__PURE__ */ new Date(),
|
|
4191
4106
|
revokedReason: reason
|
|
4192
4107
|
}).where(
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4108
|
+
and2(
|
|
4109
|
+
eq2(userPublicKeys.keyId, keyId),
|
|
4110
|
+
eq2(userPublicKeys.userId, userId)
|
|
4196
4111
|
)
|
|
4197
4112
|
);
|
|
4198
4113
|
}
|
|
4199
4114
|
|
|
4200
4115
|
// src/server/services/user.service.ts
|
|
4201
4116
|
init_entities();
|
|
4202
|
-
import { findOne
|
|
4117
|
+
import { findOne, updateOne } from "@spfn/core/db";
|
|
4203
4118
|
async function updateLastLoginService(userId) {
|
|
4204
4119
|
await updateOne(users, { id: userId }, {
|
|
4205
4120
|
lastLoginAt: /* @__PURE__ */ new Date()
|
|
@@ -4215,11 +4130,11 @@ async function checkAccountExistsService(params) {
|
|
|
4215
4130
|
if (email) {
|
|
4216
4131
|
identifier = email;
|
|
4217
4132
|
identifierType = "email";
|
|
4218
|
-
user = await
|
|
4133
|
+
user = await findOne2(users, { email });
|
|
4219
4134
|
} else if (phone) {
|
|
4220
4135
|
identifier = phone;
|
|
4221
4136
|
identifierType = "phone";
|
|
4222
|
-
user = await
|
|
4137
|
+
user = await findOne2(users, { phone });
|
|
4223
4138
|
} else {
|
|
4224
4139
|
throw new ValidationError2("Either email or phone must be provided");
|
|
4225
4140
|
}
|
|
@@ -4248,9 +4163,9 @@ async function registerService(params) {
|
|
|
4248
4163
|
}
|
|
4249
4164
|
let existingUser;
|
|
4250
4165
|
if (email) {
|
|
4251
|
-
existingUser = await
|
|
4166
|
+
existingUser = await findOne2(users, { email });
|
|
4252
4167
|
} else if (phone) {
|
|
4253
|
-
existingUser = await
|
|
4168
|
+
existingUser = await findOne2(users, { phone });
|
|
4254
4169
|
} else {
|
|
4255
4170
|
throw new ValidationError2("Either email or phone must be provided");
|
|
4256
4171
|
}
|
|
@@ -4291,15 +4206,17 @@ async function loginService(params) {
|
|
|
4291
4206
|
const { email, phone, password, publicKey, keyId, fingerprint, oldKeyId, algorithm } = params;
|
|
4292
4207
|
let user;
|
|
4293
4208
|
if (email) {
|
|
4294
|
-
user = await
|
|
4209
|
+
user = await findOne2(users, { email });
|
|
4295
4210
|
} else if (phone) {
|
|
4296
|
-
user = await
|
|
4211
|
+
user = await findOne2(users, { phone });
|
|
4297
4212
|
} else {
|
|
4298
4213
|
throw new ValidationError2("Either email or phone must be provided");
|
|
4299
4214
|
}
|
|
4300
4215
|
if (!user || !user.passwordHash) {
|
|
4301
4216
|
throw new InvalidCredentialsError();
|
|
4302
4217
|
}
|
|
4218
|
+
console.log("user", user);
|
|
4219
|
+
console.log("\uD328\uC2A4\uC6CC\uB4DC: ", password);
|
|
4303
4220
|
const isValid = await verifyPassword(password, user.passwordHash);
|
|
4304
4221
|
if (!isValid) {
|
|
4305
4222
|
throw new InvalidCredentialsError();
|
|
@@ -4343,7 +4260,7 @@ async function changePasswordService(params) {
|
|
|
4343
4260
|
if (providedHash) {
|
|
4344
4261
|
passwordHash = providedHash;
|
|
4345
4262
|
} else {
|
|
4346
|
-
const user = await
|
|
4263
|
+
const user = await findOne2(users, { id: userId });
|
|
4347
4264
|
if (!user) {
|
|
4348
4265
|
throw new ValidationError2("User not found");
|
|
4349
4266
|
}
|
|
@@ -4399,10 +4316,69 @@ async function verifyCodeService(params) {
|
|
|
4399
4316
|
};
|
|
4400
4317
|
}
|
|
4401
4318
|
|
|
4319
|
+
// src/server/services/me.service.ts
|
|
4320
|
+
init_entities();
|
|
4321
|
+
import { getDatabase as getDatabase4 } from "@spfn/core/db";
|
|
4322
|
+
import { eq as eq4, and as and4 } from "drizzle-orm";
|
|
4323
|
+
async function getMeService(userId) {
|
|
4324
|
+
const db = getDatabase4();
|
|
4325
|
+
if (!db) {
|
|
4326
|
+
throw new Error("[Auth] Database not initialized");
|
|
4327
|
+
}
|
|
4328
|
+
const userIdNum = typeof userId === "string" ? Number(userId) : Number(userId);
|
|
4329
|
+
const [userWithRole] = await db.select({
|
|
4330
|
+
userId: users.id,
|
|
4331
|
+
email: users.email,
|
|
4332
|
+
phone: users.phone,
|
|
4333
|
+
roleId: roles.id,
|
|
4334
|
+
roleName: roles.name,
|
|
4335
|
+
roleDisplayName: roles.displayName,
|
|
4336
|
+
rolePriority: roles.priority
|
|
4337
|
+
}).from(users).innerJoin(roles, eq4(users.roleId, roles.id)).where(eq4(users.id, userIdNum)).limit(1);
|
|
4338
|
+
if (!userWithRole) {
|
|
4339
|
+
throw new Error("[Auth] User not found");
|
|
4340
|
+
}
|
|
4341
|
+
const rolePerms = await db.select({
|
|
4342
|
+
id: permissions.id,
|
|
4343
|
+
name: permissions.name,
|
|
4344
|
+
displayName: permissions.displayName,
|
|
4345
|
+
category: permissions.category
|
|
4346
|
+
}).from(rolePermissions).innerJoin(permissions, eq4(rolePermissions.permissionId, permissions.id)).where(
|
|
4347
|
+
and4(
|
|
4348
|
+
eq4(rolePermissions.roleId, userWithRole.roleId),
|
|
4349
|
+
eq4(permissions.isActive, true)
|
|
4350
|
+
)
|
|
4351
|
+
);
|
|
4352
|
+
return {
|
|
4353
|
+
userId: userWithRole.userId.toString(),
|
|
4354
|
+
email: userWithRole.email ?? void 0,
|
|
4355
|
+
phone: userWithRole.phone ?? void 0,
|
|
4356
|
+
role: {
|
|
4357
|
+
id: userWithRole.roleId,
|
|
4358
|
+
name: userWithRole.roleName,
|
|
4359
|
+
displayName: userWithRole.roleDisplayName,
|
|
4360
|
+
priority: userWithRole.rolePriority
|
|
4361
|
+
},
|
|
4362
|
+
permissions: rolePerms.map((perm) => ({
|
|
4363
|
+
id: perm.id,
|
|
4364
|
+
name: perm.name,
|
|
4365
|
+
displayName: perm.displayName,
|
|
4366
|
+
category: perm.category ?? void 0
|
|
4367
|
+
}))
|
|
4368
|
+
};
|
|
4369
|
+
}
|
|
4370
|
+
|
|
4402
4371
|
// src/server/services/rbac.service.ts
|
|
4403
4372
|
init_entities();
|
|
4373
|
+
import { getDatabase as getDatabase5 } from "@spfn/core/db";
|
|
4374
|
+
import { logger } from "@spfn/core/logger";
|
|
4375
|
+
import { eq as eq5, and as and5, inArray } from "drizzle-orm";
|
|
4376
|
+
var authLogger = logger.child("@spfn/auth");
|
|
4377
|
+
|
|
4378
|
+
// src/server/services/permission.service.ts
|
|
4379
|
+
init_entities();
|
|
4404
4380
|
import { getDatabase as getDatabase6 } from "@spfn/core/db";
|
|
4405
|
-
import { eq as eq6, and as and6
|
|
4381
|
+
import { eq as eq6, and as and6 } from "drizzle-orm";
|
|
4406
4382
|
|
|
4407
4383
|
// src/server/services/index.ts
|
|
4408
4384
|
init_role_service();
|
|
@@ -4439,12 +4415,16 @@ app.bind(loginContract, async (c) => {
|
|
|
4439
4415
|
const result = await loginService(body);
|
|
4440
4416
|
return c.success(result);
|
|
4441
4417
|
});
|
|
4442
|
-
app.bind(logoutContract,
|
|
4443
|
-
const
|
|
4418
|
+
app.bind(logoutContract, async (c) => {
|
|
4419
|
+
const auth = getAuth(c);
|
|
4420
|
+
if (!auth) {
|
|
4421
|
+
return c.success({ success: true });
|
|
4422
|
+
}
|
|
4423
|
+
const { keyId, userId } = auth;
|
|
4444
4424
|
await logoutService({ userId: Number(userId), keyId });
|
|
4445
4425
|
return c.success({ success: true });
|
|
4446
4426
|
});
|
|
4447
|
-
app.bind(rotateKeyContract,
|
|
4427
|
+
app.bind(rotateKeyContract, async (c) => {
|
|
4448
4428
|
const body = await c.data();
|
|
4449
4429
|
const { keyId: oldKeyId, userId } = getAuth(c);
|
|
4450
4430
|
const result = await rotateKeyService({
|
|
@@ -4457,7 +4437,7 @@ app.bind(rotateKeyContract, [authenticate], async (c) => {
|
|
|
4457
4437
|
});
|
|
4458
4438
|
return c.success(result);
|
|
4459
4439
|
});
|
|
4460
|
-
app.bind(changePasswordContract,
|
|
4440
|
+
app.bind(changePasswordContract, async (c) => {
|
|
4461
4441
|
const body = await c.data();
|
|
4462
4442
|
const user = getUser(c);
|
|
4463
4443
|
await changePasswordService({
|
|
@@ -4468,6 +4448,11 @@ app.bind(changePasswordContract, [authenticate], async (c) => {
|
|
|
4468
4448
|
});
|
|
4469
4449
|
return c.success({ success: true });
|
|
4470
4450
|
});
|
|
4451
|
+
app.bind(getMeContract, async (c) => {
|
|
4452
|
+
const { userId } = getAuth(c);
|
|
4453
|
+
const result = await getMeService(userId);
|
|
4454
|
+
return c.success(result);
|
|
4455
|
+
});
|
|
4471
4456
|
var auth_default = app;
|
|
4472
4457
|
export {
|
|
4473
4458
|
auth_default as default
|