@arcote.tech/arc-auth 0.4.11 → 0.5.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-auth",
3
3
  "type": "module",
4
- "version": "0.4.11",
4
+ "version": "0.5.0",
5
5
  "private": false,
6
6
  "description": "Reusable authentication module for Arc framework — aggregate-based auth with factory pattern",
7
7
  "main": "./src/index.ts",
@@ -10,7 +10,7 @@
10
10
  "type-check": "tsc --noEmit"
11
11
  },
12
12
  "peerDependencies": {
13
- "@arcote.tech/arc": "^0.4.11",
13
+ "@arcote.tech/arc": "^0.5.0",
14
14
  "react": "^18.0.0 || ^19.0.0",
15
15
  "typescript": "^5.0.0"
16
16
  },
@@ -3,8 +3,8 @@ import {
3
3
  aggregate,
4
4
  boolean,
5
5
  date,
6
+ mergeUnsafe,
6
7
  string,
7
- type $type,
8
8
  type ArcRawShape,
9
9
  } from "@arcote.tech/arc";
10
10
  import type { AccountId } from "../ids/account";
@@ -41,11 +41,17 @@ export const createAccountAggregate = <
41
41
  const { accountId, token, customFields } = data;
42
42
  const tokenFields = data.tokenFields ?? [];
43
43
 
44
- const name = data.name as Data['name'];
44
+ const name = data.name as Data["name"];
45
45
 
46
46
  /** Build JWT params from account — includes accountId + tokenFields */
47
- const buildTokenParams = (account: any) => {
48
- const params: any = { accountId: account._id };
47
+ const buildTokenParams = (account: {
48
+ _id: unknown;
49
+ [key: string]: unknown;
50
+ }) => {
51
+ const params = { accountId: account._id as string } as Record<
52
+ string,
53
+ unknown
54
+ > & { accountId: string };
49
55
  for (const field of tokenFields) {
50
56
  params[field] = account[field];
51
57
  }
@@ -53,263 +59,246 @@ export const createAccountAggregate = <
53
59
  };
54
60
 
55
61
  return (
56
- aggregate(`${name}Accounts`, accountId, {
57
- email: string().email(),
58
- isEmailVerified: boolean(),
59
- passwordHash: string().optional(),
60
- authMethod: string(),
61
- registeredAt: date(),
62
- lastSignedInAt: date().optional(),
63
- ...customFields,
64
- })
65
- // --- Public Events ---
66
-
67
- .publicEvent(
68
- `${name}AccountRegistered`,
62
+ aggregate(
63
+ `${name}Accounts`,
64
+ accountId,
65
+ mergeUnsafe(
69
66
  {
70
- accountId,
71
67
  email: string().email(),
72
- passwordHash: string(),
73
- ...customFields,
68
+ isEmailVerified: boolean(),
69
+ passwordHash: string().optional(),
70
+ authMethod: string(),
71
+ registeredAt: date(),
72
+ lastSignedInAt: date().optional(),
74
73
  },
74
+ customFields,
75
+ ),
76
+ )
77
+ // --- Public Events ---
78
+
79
+ .publicEvent(
80
+ "accountRegistered",
81
+ mergeUnsafe(
82
+ {
83
+ accountId,
84
+ email: string().email(),
85
+ passwordHash: string(),
86
+ },
87
+ customFields,
88
+ ),
75
89
  async (ctx, event) => {
76
- const {
77
- accountId: id,
78
- email,
79
- passwordHash,
80
- ...customData
81
- } = event.payload as any;
82
- await ctx.set(id, {
83
- email,
90
+ event.payload;
91
+ await ctx.set(event.payload.accountId, {
84
92
  isEmailVerified: false,
85
- passwordHash,
86
93
  authMethod: "email",
87
94
  registeredAt: event.createdAt,
88
- lastSignedInAt: null,
89
- ...customData,
90
- } as any);
95
+ lastSignedInAt: undefined,
96
+ ...event.payload,
97
+ });
91
98
  },
92
99
  )
93
100
 
94
101
  .publicEvent(
95
- `${name}AccountRegisteredViaOAuth`,
96
- {
97
- accountId,
98
- email: string().email(),
99
- provider: string(),
100
- providerUserId: string(),
101
- ...customFields,
102
- },
102
+ "accountRegisteredViaOAuth",
103
+ mergeUnsafe(
104
+ {
105
+ accountId,
106
+ email: string().email(),
107
+ provider: string(),
108
+ providerUserId: string(),
109
+ },
110
+ customFields,
111
+ ),
103
112
  async (ctx, event) => {
104
- const {
105
- accountId: id,
106
- email,
107
- provider: _provider,
108
- providerUserId: _providerUserId,
109
- ...customData
110
- } = event.payload as any;
111
- await ctx.set(id, {
112
- email,
113
+ await ctx.set(event.payload.accountId, {
113
114
  isEmailVerified: true,
114
- passwordHash: null,
115
+ passwordHash: undefined,
115
116
  authMethod: "oauth",
116
117
  registeredAt: event.createdAt,
117
118
  lastSignedInAt: event.createdAt,
118
- ...customData,
119
- } as any);
119
+ ...event.payload,
120
+ });
120
121
  },
121
122
  )
122
123
 
123
124
  .publicEvent(
124
- `${name}SignedIn`,
125
+ "signedIn",
125
126
  { accountId, email: string().email() },
126
127
  async (ctx, event) => {
127
- await ctx.modify(
128
- event.payload.accountId as any,
129
- {
130
- lastSignedInAt: event.createdAt,
131
- } as any,
132
- );
128
+ await ctx.modify(event.payload.accountId, {
129
+ lastSignedInAt: event.createdAt,
130
+ });
133
131
  },
134
132
  )
135
133
 
136
- .publicEvent(`${name}EmailVerified`, { accountId }, async (ctx, event) => {
137
- await ctx.modify(
138
- event.payload.accountId as any,
139
- {
140
- isEmailVerified: true,
141
- } as any,
142
- );
134
+ .publicEvent("emailVerified", { accountId }, async (ctx, event) => {
135
+ await ctx.modify(event.payload.accountId, {
136
+ isEmailVerified: true,
137
+ });
143
138
  })
144
139
 
145
140
  // --- Mutate Methods ---
146
141
 
147
- /**
148
- * register — server-only. Hashes password, emits `${name}AccountRegistered`.
149
- */
150
- .mutateMethod(
151
- "register",
152
- {
153
- params: {
154
- email: string().email(),
155
- password: string().minLength(6).maxLength(32),
156
- ...customFields,
157
- },
158
- },
159
- ONLY_SERVER &&
160
- (async (ctx: any, params: any) => {
161
- const existing = await ctx.$query.findOne({ email: params.email });
162
- if (existing) {
163
- return { error: "EMAIL_ALREADY_TAKEN" as const };
164
- }
165
-
166
- const id = accountId.generate();
167
- const pwHash = await hashPassword(params.password);
168
- const { email, password: _pw, ...custom } = params;
169
-
170
- await ctx[`${name}AccountRegistered`].emit({
171
- accountId: id,
172
- email,
173
- passwordHash: pwHash,
174
- ...custom,
175
- });
176
-
177
- return { accountId: id };
178
- }),
142
+ .mutateMethod("register", (fn) =>
143
+ fn
144
+ .withParams(
145
+ mergeUnsafe(
146
+ {
147
+ email: string().email(),
148
+ password: string().minLength(6).maxLength(32),
149
+ },
150
+ customFields,
151
+ ),
152
+ )
153
+ .handle(
154
+ ONLY_SERVER &&
155
+ (async (ctx, params) => {
156
+ const existing = await ctx.$query.findOne({
157
+ email: params.email,
158
+ });
159
+ if (existing) {
160
+ return { error: "EMAIL_ALREADY_TAKEN" as const };
161
+ }
162
+
163
+ const id = accountId.generate();
164
+ const pwHash = await hashPassword(params.password);
165
+
166
+ await ctx.accountRegistered.emit({
167
+ ...params,
168
+ accountId: id,
169
+ passwordHash: pwHash,
170
+ });
171
+
172
+ return { accountId: id };
173
+ }),
174
+ ),
179
175
  )
180
176
 
181
- /**
182
- * signIn — server-only. Verifies password, checks email verification, returns JWT.
183
- */
184
- .mutateMethod(
185
- "signIn",
186
- {
187
- params: {
177
+ .mutateMethod("signIn", (fn) =>
178
+ fn
179
+ .withParams({
188
180
  email: string().email(),
189
181
  password: string().minLength(6).maxLength(32),
190
- },
191
- },
192
- ONLY_SERVER &&
193
- (async (ctx: any, params: any) => {
194
- const account = await ctx.$query.findOne({ email: params.email });
195
-
196
- if (!account) {
197
- return { error: "INVALID_EMAIL_OR_PASSWORD" as const };
198
- }
199
-
200
- const isValid = await verifyPassword(
201
- params.password,
202
- account.passwordHash,
203
- );
204
- if (!isValid) {
205
- return { error: "INVALID_EMAIL_OR_PASSWORD" as const };
206
- }
207
-
208
- if (!account.isEmailVerified) {
209
- return {
210
- error: "EMAIL_NOT_VERIFIED" as const,
211
- email: params.email,
212
- };
213
- }
214
-
215
- const jwtToken = token.generateJWT(buildTokenParams(account));
216
-
217
- await ctx[`${name}SignedIn`].emit({
218
- accountId: account._id,
219
- email: params.email,
220
- });
221
-
222
- return { token: jwtToken };
223
- }),
182
+ })
183
+ .handle(
184
+ ONLY_SERVER &&
185
+ (async (ctx, params) => {
186
+ const account = await ctx.$query.findOne({
187
+ email: params.email,
188
+ });
189
+
190
+ if (!account) {
191
+ return { error: "INVALID_EMAIL_OR_PASSWORD" as const };
192
+ }
193
+
194
+ const isValid = await verifyPassword(
195
+ params.password,
196
+ account.passwordHash!,
197
+ );
198
+ if (!isValid) {
199
+ return { error: "INVALID_EMAIL_OR_PASSWORD" as const };
200
+ }
201
+
202
+ if (!account.isEmailVerified) {
203
+ return {
204
+ error: "EMAIL_NOT_VERIFIED" as const,
205
+ email: params.email,
206
+ };
207
+ }
208
+
209
+ const jwtToken = token.generateJWT(buildTokenParams(account));
210
+
211
+ await ctx.signedIn.emit({
212
+ accountId: account._id,
213
+ email: params.email,
214
+ });
215
+
216
+ return { token: jwtToken };
217
+ }),
218
+ ),
224
219
  )
225
220
 
226
- /**
227
- * registerViaOAuth — server-only. Creates account from OAuth provider data.
228
- */
229
- .mutateMethod(
230
- "registerViaOAuth",
231
- {
232
- params: {
233
- email: string().email(),
234
- provider: string(),
235
- providerUserId: string(),
236
- ...customFields,
237
- },
238
- result: {} as
239
- | { accountId: $type<typeof accountId>; token: string }
240
- | {
241
- error: "EMAIL_ALREADY_TAKEN";
242
- accountId: $type<typeof accountId>;
243
- token: string;
221
+ .mutateMethod("registerViaOAuth", (fn) =>
222
+ fn
223
+ .withParams(
224
+ mergeUnsafe(
225
+ {
226
+ email: string().email(),
227
+ provider: string(),
228
+ providerUserId: string(),
244
229
  },
245
- },
246
- ONLY_SERVER &&
247
- (async (ctx: any, params: any) => {
248
- const existing = await ctx.$query.findOne({ email: params.email });
249
- if (existing) {
250
- return {
251
- error: "EMAIL_ALREADY_TAKEN" as const,
252
- accountId: existing._id,
253
- token: token.generateJWT(buildTokenParams(existing)),
254
- };
255
- }
256
-
257
- const id = accountId.generate();
258
- const { email, provider, providerUserId, ...custom } = params;
259
-
260
- await ctx[`${name}AccountRegisteredViaOAuth`].emit({
261
- accountId: id,
262
- email,
263
- provider,
264
- providerUserId,
265
- ...custom,
266
- });
267
-
268
- // Fetch newly created account to get defaults (e.g. role)
269
- const newAccount = await ctx.$query.findOne({ _id: id });
270
- return {
271
- accountId: id,
272
- token: token.generateJWT(buildTokenParams(newAccount ?? { _id: id })),
273
- };
274
- }),
230
+ customFields,
231
+ ),
232
+ )
233
+ .handle(
234
+ ONLY_SERVER &&
235
+ (async (ctx, params) => {
236
+ const existing = await ctx.$query.findOne({
237
+ email: params.email,
238
+ });
239
+ if (existing) {
240
+ return {
241
+ error: "EMAIL_ALREADY_TAKEN" as const,
242
+ accountId: existing._id,
243
+ token: token.generateJWT(buildTokenParams(existing)),
244
+ };
245
+ }
246
+
247
+ const id = accountId.generate();
248
+
249
+ await ctx.accountRegisteredViaOAuth.emit({
250
+ ...params,
251
+ accountId: id,
252
+ });
253
+
254
+ const newAccount = await ctx.$query.findOne({ _id: id });
255
+ return {
256
+ accountId: id,
257
+ token: token.generateJWT(
258
+ buildTokenParams(newAccount ?? { _id: id }),
259
+ ),
260
+ };
261
+ }),
262
+ ),
275
263
  )
276
264
 
277
- /**
278
- * signInViaOAuth — server-only. Signs in via OAuth (no password check).
279
- * Identity already verified by the OAuth provider.
280
- */
281
- .mutateMethod(
282
- "signInViaOAuth",
283
- {
284
- params: {
265
+ .mutateMethod("signInViaOAuth", (fn) =>
266
+ fn
267
+ .withParams({
285
268
  email: string().email(),
286
269
  provider: string(),
287
270
  providerUserId: string(),
288
- },
289
- result: {} as { token: string } | { error: "ACCOUNT_NOT_FOUND" },
290
- },
291
- ONLY_SERVER &&
292
- (async (ctx: any, params: any) => {
293
- const account = await ctx.$query.findOne({ email: params.email });
294
-
295
- if (!account) {
296
- return { error: "ACCOUNT_NOT_FOUND" as const };
297
- }
298
-
299
- const jwtToken = token.generateJWT(buildTokenParams(account));
300
-
301
- await ctx[`${name}SignedIn`].emit({
302
- accountId: account._id,
303
- email: params.email,
304
- });
305
-
306
- return { token: jwtToken };
307
- }),
271
+ })
272
+ .handle(
273
+ ONLY_SERVER &&
274
+ (async (ctx, params) => {
275
+ const account = await ctx.$query.findOne({
276
+ email: params.email,
277
+ });
278
+
279
+ if (!account) {
280
+ return { error: "ACCOUNT_NOT_FOUND" as const };
281
+ }
282
+
283
+ const jwtToken = token.generateJWT(buildTokenParams(account));
284
+
285
+ await ctx.signedIn.emit({
286
+ accountId: account._id,
287
+ email: params.email,
288
+ });
289
+
290
+ return { token: jwtToken };
291
+ }),
292
+ ),
308
293
  )
309
294
 
310
- .protectBy(token, (params: any) => ({ _id: params.accountId }))
311
- .clientQuery("getAll", async (ctx) => ctx.$query.find({}))
312
- .clientQuery("getMe", async (ctx) => ctx.$query.findOne({}))
295
+ .protectBy(token, (params) => ({ _id: params.accountId }))
296
+ .clientQuery("getAll", (fn) =>
297
+ fn.handle(async (ctx) => ctx.$query.find({})),
298
+ )
299
+ .clientQuery("getMe", (fn) =>
300
+ fn.handle(async (ctx) => ctx.$query.findOne({})),
301
+ )
313
302
  );
314
303
  };
315
304
 
@@ -1,6 +1,6 @@
1
1
  import { aggregate, date, string } from "@arcote.tech/arc";
2
- import type { OAuthIdentityId } from "../ids/oauth-identity";
3
2
  import type { AccountId } from "../ids/account";
3
+ import type { OAuthIdentityId } from "../ids/oauth-identity";
4
4
 
5
5
  export type OAuthIdentityAggregateData = {
6
6
  name: string;
@@ -14,7 +14,7 @@ export const createOAuthIdentityAggregate = <
14
14
  data: Data,
15
15
  ) => {
16
16
  const { oauthIdentityId, accountId } = data;
17
- const name = data.name as Data['name'];
17
+ const name = data.name as Data["name"];
18
18
 
19
19
  return aggregate(`${name}OAuthIdentities`, oauthIdentityId, {
20
20
  accountId,
@@ -25,7 +25,7 @@ export const createOAuthIdentityAggregate = <
25
25
  lastUsedAt: date().optional(),
26
26
  })
27
27
  .publicEvent(
28
- `${name}OauthIdentityLinked`,
28
+ "oauthIdentityLinked",
29
29
  {
30
30
  oauthIdentityId,
31
31
  accountId,
@@ -40,90 +40,94 @@ export const createOAuthIdentityAggregate = <
40
40
  provider,
41
41
  providerUserId,
42
42
  providerEmail,
43
- } = event.payload as any;
43
+ } = event.payload;
44
44
  await ctx.set(id, {
45
45
  accountId: accId,
46
46
  provider,
47
47
  providerUserId,
48
48
  providerEmail,
49
49
  linkedAt: event.createdAt,
50
- lastUsedAt: null,
51
- } as any);
50
+ lastUsedAt: undefined,
51
+ });
52
52
  },
53
53
  )
54
54
 
55
55
  .publicEvent(
56
- `${name}OauthIdentityUsed`,
56
+ "oauthIdentityUsed",
57
57
  { oauthIdentityId },
58
58
  async (ctx, event) => {
59
- await ctx.modify(event.payload.oauthIdentityId as any, {
59
+ await ctx.modify(event.payload.oauthIdentityId, {
60
60
  lastUsedAt: event.createdAt,
61
- } as any);
61
+ });
62
62
  },
63
63
  )
64
64
 
65
65
  .publicEvent(
66
- `${name}OauthIdentityUnlinked`,
66
+ "oauthIdentityUnlinked",
67
67
  { oauthIdentityId },
68
68
  async (ctx, event) => {
69
- await ctx.remove(event.payload.oauthIdentityId as any);
69
+ await ctx.remove(event.payload.oauthIdentityId);
70
70
  },
71
71
  )
72
72
 
73
- .mutateMethod(
74
- "linkIdentity",
75
- {
76
- params: {
73
+ .mutateMethod("linkIdentity", (fn) =>
74
+ fn
75
+ .withParams({
77
76
  accountId,
78
77
  provider: string(),
79
78
  providerUserId: string(),
80
79
  providerEmail: string().email(),
81
- },
82
- },
83
- ONLY_SERVER &&
84
- (async (ctx: any, params: any) => {
85
- const existing = await ctx.$query.findOne({
86
- provider: params.provider,
87
- providerUserId: params.providerUserId,
88
- });
89
- if (existing) {
90
- return { error: "OAUTH_IDENTITY_ALREADY_LINKED" as const };
91
- }
80
+ })
81
+ .handle(
82
+ ONLY_SERVER &&
83
+ (async (ctx, params) => {
84
+ const existing = await ctx.$query.findOne({
85
+ provider: params.provider,
86
+ providerUserId: params.providerUserId,
87
+ });
88
+ if (existing) {
89
+ return { error: "OAUTH_IDENTITY_ALREADY_LINKED" as const };
90
+ }
92
91
 
93
- const id = oauthIdentityId.generate();
92
+ const id = oauthIdentityId.generate();
94
93
 
95
- await ctx[`${name}OauthIdentityLinked`].emit({
96
- oauthIdentityId: id,
97
- accountId: params.accountId,
98
- provider: params.provider,
99
- providerUserId: params.providerUserId,
100
- providerEmail: params.providerEmail,
101
- });
94
+ await ctx.oauthIdentityLinked.emit({
95
+ oauthIdentityId: id,
96
+ accountId: params.accountId,
97
+ provider: params.provider,
98
+ providerUserId: params.providerUserId,
99
+ providerEmail: params.providerEmail,
100
+ });
102
101
 
103
- return { oauthIdentityId: id };
104
- }),
102
+ return { oauthIdentityId: id };
103
+ }),
104
+ ),
105
105
  )
106
106
 
107
- .mutateMethod(
108
- "markUsed",
109
- { params: { oauthIdentityId } },
110
- ONLY_SERVER &&
111
- (async (ctx: any, params: any) => {
112
- await ctx[`${name}OauthIdentityUsed`].emit({
113
- oauthIdentityId: params.oauthIdentityId,
114
- });
115
- }),
107
+ .mutateMethod("markUsed", (fn) =>
108
+ fn.withParams({ oauthIdentityId }).handle(
109
+ ONLY_SERVER &&
110
+ (async (ctx, params) => {
111
+ await ctx["oauthIdentityUsed"].emit({
112
+ oauthIdentityId: params.oauthIdentityId,
113
+ });
114
+ }),
115
+ ),
116
116
  )
117
- .clientQuery("getAll", async (ctx) => ctx.$query.find({}))
118
- .clientQuery(
119
- "findByProvider",
120
- async (ctx, params: { provider: string; providerUserId: string }) =>
121
- ctx.$query.findOne({
122
- provider: params.provider,
123
- providerUserId: params.providerUserId,
124
- }),
117
+ .clientQuery("getAll", (fn) =>
118
+ fn.handle(async (ctx) => ctx.$query.find({})),
125
119
  )
126
- ;
120
+ .clientQuery("findByProvider", (fn) =>
121
+ fn
122
+ .withParams({ provider: string(), providerUserId: string() })
123
+ .handle(
124
+ async (ctx, params: { provider: string; providerUserId: string }) =>
125
+ ctx.$query.findOne({
126
+ provider: params.provider,
127
+ providerUserId: params.providerUserId,
128
+ }),
129
+ ),
130
+ );
127
131
  };
128
132
 
129
133
  export type OAuthIdentityAggregate<
@@ -1,23 +1,26 @@
1
1
  import {
2
2
  context,
3
3
  route,
4
- type ArcAggregateElement,
5
4
  type ArcContextElement,
6
5
  type ArcRawShape,
7
6
  } from "@arcote.tech/arc";
7
+ import type { AccountAggregate } from "./aggregates/account";
8
+ import type { OAuthIdentityAggregate } from "./aggregates/oauth-identity";
8
9
  import { createAccountAggregate } from "./aggregates/account";
9
10
  import { createOAuthIdentityAggregate } from "./aggregates/oauth-identity";
10
11
  import { createAccountId } from "./ids/account";
11
12
  import { createOAuthIdentityId } from "./ids/oauth-identity";
12
13
  import { createToken } from "./tokens/token";
13
14
  import { createOAuthRoutes } from "./routes/oauth-routes";
15
+ import type { AccountId } from "./ids/account";
14
16
  import type { OAuthProvidersConfig } from "./providers/types";
17
+ import type { Token } from "./tokens/token";
15
18
 
16
19
  export class AuthBuilder<
17
- AccId,
18
- Tok,
19
- Account extends ArcAggregateElement<any, any, any, any, any, any>,
20
- OAuthIdentity extends ArcAggregateElement<any, any, any, any, any, any> | undefined,
20
+ AccId extends AccountId,
21
+ Tok extends Token,
22
+ Account extends AccountAggregate,
23
+ OAuthIdentity extends OAuthIdentityAggregate | undefined,
21
24
  EnabledProviders extends string[],
22
25
  Elements extends ArcContextElement<any>[],
23
26
  > {
@@ -39,7 +42,7 @@ export class AuthBuilder<
39
42
  const OAuthIdentity = createOAuthIdentityAggregate({
40
43
  name: this._name,
41
44
  oauthIdentityId,
42
- accountId: this.accountId as any,
45
+ accountId: this.accountId,
43
46
  });
44
47
 
45
48
  const hasProviders = config.providers && config.baseUrl;
@@ -47,7 +50,7 @@ export class AuthBuilder<
47
50
  ? createOAuthRoutes({
48
51
  providers: config.providers!,
49
52
  baseUrl: config.baseUrl!,
50
- token: this.token as any,
53
+ token: this.token,
51
54
  accountElement: this.Account,
52
55
  oauthIdentityElement: OAuthIdentity,
53
56
  })
@@ -248,9 +248,13 @@ export function createOAuthRoutes(data: OAuthRoutesData) {
248
248
  const targetUrl = new URL(decodedRedirect, baseUrl);
249
249
  targetUrl.searchParams.set("token", jwtToken);
250
250
 
251
- // Clear state cookie
251
+ // Set auth cookie + clear state cookie
252
252
  const response = Response.redirect(targetUrl.toString(), 302);
253
253
  const headers = new Headers(response.headers);
254
+ headers.append(
255
+ "Set-Cookie",
256
+ `arc_token=${encodeURIComponent(jwtToken)}; HttpOnly; SameSite=Lax; Path=/; Max-Age=604800`,
257
+ );
254
258
  headers.append(
255
259
  "Set-Cookie",
256
260
  `oauth_state=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`,
@@ -10,7 +10,7 @@ export const createToken = <const Data extends TokenData>(data: Data) =>
10
10
  token(`${data.name}Account`, {
11
11
  accountId: string(),
12
12
  ...(data.extraParams ?? {}),
13
- } as any).secret(data.secret);
13
+ }).secret(data.secret);
14
14
 
15
15
  export type Token<Data extends TokenData = TokenData> = ReturnType<
16
16
  typeof createToken<Data>