@nerdfolio/ba-guest-list 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +11 -9
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +11 -9
- package/package.json +6 -3
- package/src/client.ts +0 -9
- package/src/index.ts +0 -2
- package/src/server.ts +0 -200
- package/src/utils.ts +0 -14
- package/tsup.config.ts +0 -15
package/dist/index.cjs
CHANGED
|
@@ -40,10 +40,10 @@ var import_v4_mini = require("zod/v4-mini");
|
|
|
40
40
|
|
|
41
41
|
// src/utils.ts
|
|
42
42
|
var import_lodash_es = require("lodash-es");
|
|
43
|
-
function
|
|
43
|
+
function getHostName(url) {
|
|
44
44
|
try {
|
|
45
45
|
const parsedUrl = new URL(url);
|
|
46
|
-
return parsedUrl.
|
|
46
|
+
return parsedUrl.hostname;
|
|
47
47
|
} catch (_error) {
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
@@ -73,7 +73,7 @@ var guestList = (options) => {
|
|
|
73
73
|
return {
|
|
74
74
|
id: "guest-list",
|
|
75
75
|
endpoints: {
|
|
76
|
-
|
|
76
|
+
signInGuestList: (0, import_api.createAuthEndpoint)(
|
|
77
77
|
"/sign-in/guest-list",
|
|
78
78
|
{
|
|
79
79
|
method: "POST",
|
|
@@ -82,7 +82,7 @@ var guestList = (options) => {
|
|
|
82
82
|
}),
|
|
83
83
|
metadata: {
|
|
84
84
|
openapi: {
|
|
85
|
-
description: "Sign in
|
|
85
|
+
description: "Sign in via a guest list",
|
|
86
86
|
responses: {
|
|
87
87
|
200: {
|
|
88
88
|
description: "Sign in as a guest successful",
|
|
@@ -91,13 +91,15 @@ var guestList = (options) => {
|
|
|
91
91
|
schema: {
|
|
92
92
|
type: "object",
|
|
93
93
|
properties: {
|
|
94
|
+
token: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "Session token for the authenticated session"
|
|
97
|
+
},
|
|
94
98
|
user: {
|
|
95
99
|
$ref: "#/components/schemas/User"
|
|
96
|
-
},
|
|
97
|
-
session: {
|
|
98
|
-
$ref: "#/components/schemas/Session"
|
|
99
100
|
}
|
|
100
|
-
}
|
|
101
|
+
},
|
|
102
|
+
required: ["token", "user"]
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
105
|
}
|
|
@@ -126,7 +128,7 @@ var guestList = (options) => {
|
|
|
126
128
|
message: options?.revealNames ? `Name not on list. Try: ${JSON.stringify(Object.keys(guestLookup))}` : ERROR_CODES.NAME_NOT_ON_GUEST_LIST
|
|
127
129
|
});
|
|
128
130
|
}
|
|
129
|
-
const { emailDomainName =
|
|
131
|
+
const { emailDomainName = getHostName(ctx.context.baseURL) } = options ?? {};
|
|
130
132
|
const email = `${cleanedName.toLowerCase().replaceAll(/\s/g, "")}.onguestlist@${emailDomainName}`;
|
|
131
133
|
const found = await ctx.context.internalAdapter.findUserByEmail(email);
|
|
132
134
|
async function createNewUser() {
|
package/dist/index.d.cts
CHANGED
|
@@ -26,7 +26,7 @@ interface GuestListOptions {
|
|
|
26
26
|
declare const guestList: (options?: GuestListOptions) => {
|
|
27
27
|
id: "guest-list";
|
|
28
28
|
endpoints: {
|
|
29
|
-
|
|
29
|
+
signInGuestList: {
|
|
30
30
|
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
|
|
31
31
|
body: {
|
|
32
32
|
name: string;
|
|
@@ -91,13 +91,15 @@ declare const guestList: (options?: GuestListOptions) => {
|
|
|
91
91
|
schema: {
|
|
92
92
|
type: "object";
|
|
93
93
|
properties: {
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
token: {
|
|
95
|
+
type: string;
|
|
96
|
+
description: string;
|
|
96
97
|
};
|
|
97
|
-
|
|
98
|
+
user: {
|
|
98
99
|
$ref: string;
|
|
99
100
|
};
|
|
100
101
|
};
|
|
102
|
+
required: string[];
|
|
101
103
|
};
|
|
102
104
|
};
|
|
103
105
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ interface GuestListOptions {
|
|
|
26
26
|
declare const guestList: (options?: GuestListOptions) => {
|
|
27
27
|
id: "guest-list";
|
|
28
28
|
endpoints: {
|
|
29
|
-
|
|
29
|
+
signInGuestList: {
|
|
30
30
|
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
|
|
31
31
|
body: {
|
|
32
32
|
name: string;
|
|
@@ -91,13 +91,15 @@ declare const guestList: (options?: GuestListOptions) => {
|
|
|
91
91
|
schema: {
|
|
92
92
|
type: "object";
|
|
93
93
|
properties: {
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
token: {
|
|
95
|
+
type: string;
|
|
96
|
+
description: string;
|
|
96
97
|
};
|
|
97
|
-
|
|
98
|
+
user: {
|
|
98
99
|
$ref: string;
|
|
99
100
|
};
|
|
100
101
|
};
|
|
102
|
+
required: string[];
|
|
101
103
|
};
|
|
102
104
|
};
|
|
103
105
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -13,10 +13,10 @@ import { z } from "zod/v4-mini";
|
|
|
13
13
|
|
|
14
14
|
// src/utils.ts
|
|
15
15
|
import { capitalize } from "lodash-es";
|
|
16
|
-
function
|
|
16
|
+
function getHostName(url) {
|
|
17
17
|
try {
|
|
18
18
|
const parsedUrl = new URL(url);
|
|
19
|
-
return parsedUrl.
|
|
19
|
+
return parsedUrl.hostname;
|
|
20
20
|
} catch (_error) {
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
@@ -46,7 +46,7 @@ var guestList = (options) => {
|
|
|
46
46
|
return {
|
|
47
47
|
id: "guest-list",
|
|
48
48
|
endpoints: {
|
|
49
|
-
|
|
49
|
+
signInGuestList: createAuthEndpoint(
|
|
50
50
|
"/sign-in/guest-list",
|
|
51
51
|
{
|
|
52
52
|
method: "POST",
|
|
@@ -55,7 +55,7 @@ var guestList = (options) => {
|
|
|
55
55
|
}),
|
|
56
56
|
metadata: {
|
|
57
57
|
openapi: {
|
|
58
|
-
description: "Sign in
|
|
58
|
+
description: "Sign in via a guest list",
|
|
59
59
|
responses: {
|
|
60
60
|
200: {
|
|
61
61
|
description: "Sign in as a guest successful",
|
|
@@ -64,13 +64,15 @@ var guestList = (options) => {
|
|
|
64
64
|
schema: {
|
|
65
65
|
type: "object",
|
|
66
66
|
properties: {
|
|
67
|
+
token: {
|
|
68
|
+
type: "string",
|
|
69
|
+
description: "Session token for the authenticated session"
|
|
70
|
+
},
|
|
67
71
|
user: {
|
|
68
72
|
$ref: "#/components/schemas/User"
|
|
69
|
-
},
|
|
70
|
-
session: {
|
|
71
|
-
$ref: "#/components/schemas/Session"
|
|
72
73
|
}
|
|
73
|
-
}
|
|
74
|
+
},
|
|
75
|
+
required: ["token", "user"]
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
}
|
|
@@ -99,7 +101,7 @@ var guestList = (options) => {
|
|
|
99
101
|
message: options?.revealNames ? `Name not on list. Try: ${JSON.stringify(Object.keys(guestLookup))}` : ERROR_CODES.NAME_NOT_ON_GUEST_LIST
|
|
100
102
|
});
|
|
101
103
|
}
|
|
102
|
-
const { emailDomainName =
|
|
104
|
+
const { emailDomainName = getHostName(ctx.context.baseURL) } = options ?? {};
|
|
103
105
|
const email = `${cleanedName.toLowerCase().replaceAll(/\s/g, "")}.onguestlist@${emailDomainName}`;
|
|
104
106
|
const found = await ctx.context.internalAdapter.findUserByEmail(email);
|
|
105
107
|
async function createNewUser() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nerdfolio/ba-guest-list",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Similar to anonymous, but with a name that must be on a guest list. Useful for testing or demo with fixed logins",
|
|
5
5
|
"repository": "https://github.com/nerdfolio/better-auth-goodies",
|
|
6
6
|
"type": "module",
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"require": "./dist/index.cjs"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
14
17
|
"keywords": [
|
|
15
18
|
"better-auth",
|
|
16
19
|
"better-auth plugin",
|
|
@@ -26,10 +29,10 @@
|
|
|
26
29
|
},
|
|
27
30
|
"devDependencies": {
|
|
28
31
|
"@types/lodash-es": "^4.17.12",
|
|
29
|
-
"better-auth": "1.2.
|
|
32
|
+
"better-auth": "1.2.12"
|
|
30
33
|
},
|
|
31
34
|
"peerDependencies": {
|
|
32
|
-
"better-auth": "1.2.
|
|
35
|
+
"better-auth": "1.2.12"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
38
|
"lodash-es": "^4.17.21",
|
package/src/client.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { BetterAuthClientPlugin } from "better-auth"
|
|
2
|
-
import type { guestList } from "./server"
|
|
3
|
-
|
|
4
|
-
export const guestListClient = () => {
|
|
5
|
-
return {
|
|
6
|
-
id: "guest-list",
|
|
7
|
-
$InferServerPlugin: {} as ReturnType<typeof guestList>,
|
|
8
|
-
} satisfies BetterAuthClientPlugin
|
|
9
|
-
}
|
package/src/index.ts
DELETED
package/src/server.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import type { BetterAuthPlugin } from "better-auth"
|
|
2
|
-
import { APIError, createAuthEndpoint } from "better-auth/api"
|
|
3
|
-
import { setSessionCookie } from "better-auth/cookies"
|
|
4
|
-
import { z } from "zod/v4-mini"
|
|
5
|
-
import { formatName, getHost } from "./utils"
|
|
6
|
-
|
|
7
|
-
type GuestWithRole = {
|
|
8
|
-
name: string
|
|
9
|
-
role: string //comma-separated string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface GuestListOptions {
|
|
13
|
-
/**
|
|
14
|
-
* List of accepted guest names
|
|
15
|
-
*/
|
|
16
|
-
allowGuests: string[] | GuestWithRole[]
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* When true returns the list of guest names via the guestList.reveal() endpoint and via errors.
|
|
20
|
-
* When false returns nothing.
|
|
21
|
-
* @default false
|
|
22
|
-
*/
|
|
23
|
-
revealNames?: boolean
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Configure the domain name of the temporary email
|
|
27
|
-
* address for the guest users in the database.
|
|
28
|
-
* @default "baseURL"
|
|
29
|
-
*/
|
|
30
|
-
emailDomainName?: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const guestList = (options?: GuestListOptions) => {
|
|
34
|
-
const ERROR_CODES = {
|
|
35
|
-
NAME_NOT_PROVIDED: "Guest name not provided",
|
|
36
|
-
NAME_NOT_ON_GUEST_LIST: "Your name is not on the guest list",
|
|
37
|
-
NAME_ONE_WORD_ONLY: "Please only use 1-word names",
|
|
38
|
-
FAILED_TO_CREATE_USER: "Failed to create user",
|
|
39
|
-
COULD_NOT_CREATE_SESSION: "Could not create session",
|
|
40
|
-
} as const
|
|
41
|
-
|
|
42
|
-
const guestLookup = Object.fromEntries(
|
|
43
|
-
(options?.allowGuests ?? [])
|
|
44
|
-
.map((entry) => (typeof entry === "string" ? { name: entry, role: "" } : entry))
|
|
45
|
-
.filter((entry) => !!entry && entry.name)
|
|
46
|
-
.map(({ name, role }) => [
|
|
47
|
-
formatName(name),
|
|
48
|
-
{
|
|
49
|
-
name: formatName(name),
|
|
50
|
-
role: (role ?? "")
|
|
51
|
-
.split(",")
|
|
52
|
-
.map((s) => s.trim())
|
|
53
|
-
.join(","),
|
|
54
|
-
},
|
|
55
|
-
])
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
id: "guest-list",
|
|
60
|
-
endpoints: {
|
|
61
|
-
signInGuest: createAuthEndpoint(
|
|
62
|
-
"/sign-in/guest-list",
|
|
63
|
-
{
|
|
64
|
-
method: "POST",
|
|
65
|
-
body: z.object({
|
|
66
|
-
name: z.string(),
|
|
67
|
-
}),
|
|
68
|
-
metadata: {
|
|
69
|
-
openapi: {
|
|
70
|
-
description: "Sign in as a guest with name only",
|
|
71
|
-
responses: {
|
|
72
|
-
200: {
|
|
73
|
-
description: "Sign in as a guest successful",
|
|
74
|
-
content: {
|
|
75
|
-
"application/json": {
|
|
76
|
-
schema: {
|
|
77
|
-
type: "object",
|
|
78
|
-
properties: {
|
|
79
|
-
user: {
|
|
80
|
-
$ref: "#/components/schemas/User",
|
|
81
|
-
},
|
|
82
|
-
session: {
|
|
83
|
-
$ref: "#/components/schemas/Session",
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
async (ctx) => {
|
|
95
|
-
const { name } = ctx.body
|
|
96
|
-
|
|
97
|
-
if (!name) {
|
|
98
|
-
ctx.context.logger.error("Guest name not provided")
|
|
99
|
-
throw new APIError("UNAUTHORIZED", {
|
|
100
|
-
message: options?.revealNames
|
|
101
|
-
? `Guest name not provided. Try: ${JSON.stringify(Object.keys(guestLookup))}`
|
|
102
|
-
: ERROR_CODES.NAME_NOT_PROVIDED,
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (name.trim().split(/\s+/).length > 1) {
|
|
107
|
-
ctx.context.logger.error("For simplicity, only one word names are allowed")
|
|
108
|
-
throw new APIError("UNAUTHORIZED", {
|
|
109
|
-
message: ERROR_CODES.NAME_ONE_WORD_ONLY,
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const cleanedName = formatName(name)
|
|
114
|
-
|
|
115
|
-
if (!guestLookup[cleanedName]) {
|
|
116
|
-
throw new APIError("UNAUTHORIZED", {
|
|
117
|
-
message: options?.revealNames
|
|
118
|
-
? `Name not on list. Try: ${JSON.stringify(Object.keys(guestLookup))}`
|
|
119
|
-
: ERROR_CODES.NAME_NOT_ON_GUEST_LIST,
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// generate email based the input name
|
|
124
|
-
const { emailDomainName = getHost(ctx.context.baseURL) } = options ?? {}
|
|
125
|
-
const email = `${cleanedName.toLowerCase().replaceAll(/\s/g, "")}.onguestlist@${emailDomainName}`
|
|
126
|
-
|
|
127
|
-
const found = await ctx.context.internalAdapter.findUserByEmail(email)
|
|
128
|
-
|
|
129
|
-
async function createNewUser() {
|
|
130
|
-
const newUser = await ctx.context.internalAdapter.createUser(
|
|
131
|
-
{
|
|
132
|
-
email,
|
|
133
|
-
emailVerified: false,
|
|
134
|
-
name: cleanedName,
|
|
135
|
-
role: guestLookup[cleanedName].role,
|
|
136
|
-
createdAt: new Date(),
|
|
137
|
-
updatedAt: new Date(),
|
|
138
|
-
},
|
|
139
|
-
ctx
|
|
140
|
-
)
|
|
141
|
-
if (!newUser) {
|
|
142
|
-
throw ctx.error("INTERNAL_SERVER_ERROR", {
|
|
143
|
-
message: ERROR_CODES.FAILED_TO_CREATE_USER,
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return newUser
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const user = found ? found.user : await createNewUser()
|
|
151
|
-
|
|
152
|
-
const session = await ctx.context.internalAdapter.createSession(user.id, ctx, true)
|
|
153
|
-
|
|
154
|
-
if (!session) {
|
|
155
|
-
return ctx.json(null, {
|
|
156
|
-
status: 400,
|
|
157
|
-
body: {
|
|
158
|
-
message: ERROR_CODES.COULD_NOT_CREATE_SESSION,
|
|
159
|
-
},
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
await setSessionCookie(ctx, { session, user })
|
|
163
|
-
|
|
164
|
-
return ctx.json({ token: session.token, user })
|
|
165
|
-
}
|
|
166
|
-
),
|
|
167
|
-
|
|
168
|
-
revealGuestList: createAuthEndpoint(
|
|
169
|
-
"/sign-in/guest-list/reveal",
|
|
170
|
-
{
|
|
171
|
-
method: "GET",
|
|
172
|
-
metadata: {
|
|
173
|
-
openapi: {
|
|
174
|
-
description: "Reveal guest list if 'revealNames' is enabled. Empty array otherwise",
|
|
175
|
-
responses: {
|
|
176
|
-
200: {
|
|
177
|
-
description: "List of allowed guest names or empty array",
|
|
178
|
-
content: {
|
|
179
|
-
"application/json": {
|
|
180
|
-
schema: {
|
|
181
|
-
type: "array",
|
|
182
|
-
items: {
|
|
183
|
-
type: "string",
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
async (ctx) => {
|
|
194
|
-
return ctx.json(options?.revealNames ? Object.keys(guestLookup) : [])
|
|
195
|
-
}
|
|
196
|
-
),
|
|
197
|
-
},
|
|
198
|
-
$ERROR_CODES: ERROR_CODES,
|
|
199
|
-
} satisfies BetterAuthPlugin
|
|
200
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { capitalize } from "lodash-es"
|
|
2
|
-
|
|
3
|
-
export function getHost(url: string) {
|
|
4
|
-
try {
|
|
5
|
-
const parsedUrl = new URL(url)
|
|
6
|
-
return parsedUrl.host
|
|
7
|
-
} catch (_error) {
|
|
8
|
-
return null
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function formatName(name: string) {
|
|
13
|
-
return capitalize(name.replaceAll(/\s/g, ""))
|
|
14
|
-
}
|
package/tsup.config.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type Options, defineConfig } from "tsup"
|
|
2
|
-
|
|
3
|
-
const libCfg = {
|
|
4
|
-
entry: ["src/index.ts"],
|
|
5
|
-
splitting: false,
|
|
6
|
-
target: "node22",
|
|
7
|
-
format: ["esm", "cjs"],
|
|
8
|
-
dts: true,
|
|
9
|
-
clean: true,
|
|
10
|
-
outExtension({ format }) {
|
|
11
|
-
return { js: format === "esm" ? ".mjs" : format === "cjs" ? ".cjs" : ".js" }
|
|
12
|
-
},
|
|
13
|
-
} satisfies Options
|
|
14
|
-
|
|
15
|
-
export default defineConfig(libCfg)
|