@withwiz/toolkit 0.8.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.ko.md +16 -25
  2. package/README.md +16 -25
  3. package/dist/{chunk-XXPB4C37.js → chunk-2GK4LDPV.js} +6 -2
  4. package/dist/chunk-2JUFL4KX.js +41 -0
  5. package/dist/{chunk-NTZBMWB6.js → chunk-3P4TZM3O.js} +1 -1
  6. package/dist/chunk-43XXILCX.js +118 -0
  7. package/dist/{chunk-VWAB4PM7.js → chunk-5S7M2AJL.js} +1 -1
  8. package/dist/chunk-5VDT3ZB4.js +139 -0
  9. package/dist/{chunk-SCAFDDJP.js → chunk-BICSVLN7.js} +2 -2
  10. package/dist/chunk-E4TKORMQ.js +59 -0
  11. package/dist/chunk-GSRAIDD7.js +134 -0
  12. package/dist/{chunk-BRBOGLFT.js → chunk-KHXS4DGA.js} +3 -3
  13. package/dist/{chunk-V3WZFUY3.js → chunk-QMBNFCCK.js} +1 -1
  14. package/dist/{chunk-OII5BXCZ.js → chunk-U2TGXJ3A.js} +1 -1
  15. package/dist/{chunk-NLV7IEYM.js → chunk-WSHRBK6Y.js} +1 -1
  16. package/dist/{chunk-VH57Y5Z4.js → chunk-XDB3K74B.js} +1 -1
  17. package/dist/{chunk-JHUWZ6YW.js → chunk-YYTA6ERS.js} +6 -36
  18. package/dist/core/auth/adapters/sql/dialect.d.ts +21 -0
  19. package/dist/core/auth/adapters/sql/dialect.js +11 -0
  20. package/dist/core/auth/adapters/sql/email-token-repository.d.ts +17 -0
  21. package/dist/core/auth/adapters/sql/email-token-repository.js +9 -0
  22. package/dist/core/auth/adapters/sql/index.d.ts +7 -0
  23. package/dist/core/auth/adapters/sql/index.js +27 -0
  24. package/dist/core/auth/adapters/sql/oauth-account-repository.d.ts +18 -0
  25. package/dist/core/auth/adapters/sql/oauth-account-repository.js +9 -0
  26. package/dist/core/auth/adapters/sql/types.d.ts +73 -0
  27. package/dist/core/auth/adapters/sql/types.js +7 -0
  28. package/dist/core/auth/adapters/sql/user-repository.d.ts +20 -0
  29. package/dist/core/auth/adapters/sql/user-repository.js +9 -0
  30. package/dist/core/auth/index.js +9 -9
  31. package/dist/core/auth/oauth/index.js +7 -7
  32. package/dist/core/auth/oauth/providers/index.js +6 -6
  33. package/dist/core/auth/services/index.js +4 -4
  34. package/dist/core/cache/cache-factory.js +3 -3
  35. package/dist/core/cache/cache-invalidation.js +4 -4
  36. package/dist/core/cache/cache-wrapper.js +4 -4
  37. package/dist/core/cache/cache.js +5 -5
  38. package/dist/core/cache/hybrid-cache-manager.js +2 -2
  39. package/dist/core/cache/index.js +5 -5
  40. package/dist/core/cache/inmemory-cache-manager.d.ts +0 -9
  41. package/dist/core/cache/inmemory-cache-manager.js +1 -1
  42. package/dist/core/error/friendly-messages-v2.js +3 -3
  43. package/dist/core/error/index.js +6 -6
  44. package/dist/core/error/messages/index.js +2 -2
  45. package/dist/core/geolocation/index.js +7 -7
  46. package/dist/core/geolocation/providers/index.js +7 -7
  47. package/dist/core/system/health-check.js +2 -2
  48. package/dist/core/system/index.js +5 -5
  49. package/dist/initialize.js +6 -6
  50. package/dist/next/auth-handlers/index.js +16 -16
  51. package/dist/next/auth-handlers/oauth-authorize.handler.js +4 -4
  52. package/dist/next/auth-handlers/oauth-callback.handler.js +5 -5
  53. package/dist/next/error/index.js +7 -7
  54. package/dist/next/middleware/error-handler.js +4 -4
  55. package/dist/next/middleware/index.js +6 -6
  56. package/dist/next/middleware/wrappers.js +6 -6
  57. package/dist/next/utils/index.js +19 -19
  58. package/package.json +3 -2
  59. package/dist/{chunk-KKZCNF6U.js → chunk-7WG7XPXC.js} +3 -3
  60. package/dist/{chunk-SXBDP3CK.js → chunk-JOYW3OZB.js} +3 -3
  61. package/dist/{chunk-ER6LSA4M.js → chunk-P7WHMKN5.js} +6 -6
  62. package/dist/{chunk-VDRLJU6C.js → chunk-Q5RPNLET.js} +6 -6
@@ -0,0 +1,134 @@
1
+ import {
2
+ resolveConfig
3
+ } from "./chunk-E4TKORMQ.js";
4
+ import {
5
+ ParamBuilder,
6
+ columnList,
7
+ getDialect
8
+ } from "./chunk-2JUFL4KX.js";
9
+
10
+ // src/core/auth/adapters/sql/user-repository.ts
11
+ import { randomUUID } from "crypto";
12
+ var SqlUserRepository = class {
13
+ constructor(exec, config) {
14
+ this.exec = exec;
15
+ this.config = resolveConfig(config);
16
+ this.dialect = getDialect(this.config.dialect);
17
+ }
18
+ get table() {
19
+ return this.dialect.quoteId(this.config.tables.user);
20
+ }
21
+ get cols() {
22
+ return this.config.userColumns;
23
+ }
24
+ /** password 제외 SELECT/매핑 대상 컬럼. */
25
+ selectColumns() {
26
+ const c = this.cols;
27
+ return [c.id, c.email, c.name, c.role, c.image, c.emailVerified, c.isActive, c.createdAt, c.updatedAt];
28
+ }
29
+ async findById(id) {
30
+ const pb = new ParamBuilder(this.dialect);
31
+ const sql = `SELECT ${columnList(this.selectColumns(), this.dialect)} FROM ${this.table} WHERE ${this.dialect.quoteId(this.cols.id)} = ${pb.add(id)}`;
32
+ const rows = await this.exec.query(sql, pb.params);
33
+ return rows[0] ? this.mapToBaseUser(rows[0]) : null;
34
+ }
35
+ async findByEmail(email) {
36
+ var _a;
37
+ const pb = new ParamBuilder(this.dialect);
38
+ const cols = [...this.selectColumns(), this.cols.password];
39
+ const sql = `SELECT ${columnList(cols, this.dialect)} FROM ${this.table} WHERE ${this.dialect.quoteId(this.cols.email)} = ${pb.add(email)}`;
40
+ const rows = await this.exec.query(sql, pb.params);
41
+ if (!rows[0]) return null;
42
+ const baseUser = this.mapToBaseUser(rows[0]);
43
+ return Object.assign(baseUser, { password: (_a = rows[0][this.cols.password]) != null ? _a : null });
44
+ }
45
+ async create(data) {
46
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
47
+ const c = this.cols;
48
+ const id = randomUUID();
49
+ const now = /* @__PURE__ */ new Date();
50
+ const pb = new ParamBuilder(this.dialect);
51
+ const entries = [
52
+ [c.id, id],
53
+ [c.email, data.email],
54
+ [c.name, (_a = data.name) != null ? _a : null],
55
+ [c.password, (_b = data.password) != null ? _b : null],
56
+ [c.role, (_c = data.role) != null ? _c : null],
57
+ [c.emailVerified, (_d = data.emailVerified) != null ? _d : null],
58
+ [c.image, (_e = data.image) != null ? _e : null],
59
+ [c.isActive, true],
60
+ [c.createdAt, now],
61
+ [c.updatedAt, now]
62
+ ];
63
+ const colSql = entries.map(([col]) => this.dialect.quoteId(col)).join(", ");
64
+ const valSql = entries.map(([, val]) => pb.add(val)).join(", ");
65
+ const sql = `INSERT INTO ${this.table} (${colSql}) VALUES (${valSql})`;
66
+ await this.exec.query(sql, pb.params);
67
+ return {
68
+ id,
69
+ email: data.email,
70
+ name: (_f = data.name) != null ? _f : null,
71
+ role: (_g = data.role) != null ? _g : void 0,
72
+ emailVerified: (_h = data.emailVerified) != null ? _h : null,
73
+ image: (_i = data.image) != null ? _i : null,
74
+ isActive: true,
75
+ createdAt: now,
76
+ updatedAt: now
77
+ };
78
+ }
79
+ async update(id, data) {
80
+ const c = this.cols;
81
+ const pb = new ParamBuilder(this.dialect);
82
+ const sets = [];
83
+ const assign = (col, val) => {
84
+ sets.push(`${this.dialect.quoteId(col)} = ${pb.add(val)}`);
85
+ };
86
+ if (data.email !== void 0) assign(c.email, data.email);
87
+ if (data.name !== void 0) assign(c.name, data.name);
88
+ if (data.isActive !== void 0) assign(c.isActive, data.isActive);
89
+ if (data.password !== void 0) assign(c.password, data.password);
90
+ if (data.role !== void 0) assign(c.role, data.role);
91
+ if (data.emailVerified !== void 0) assign(c.emailVerified, data.emailVerified);
92
+ if (data.image !== void 0) assign(c.image, data.image);
93
+ assign(c.updatedAt, /* @__PURE__ */ new Date());
94
+ const sql = `UPDATE ${this.table} SET ${sets.join(", ")} WHERE ${this.dialect.quoteId(c.id)} = ${pb.add(id)}`;
95
+ await this.exec.query(sql, pb.params);
96
+ const updated = await this.findById(id);
97
+ if (!updated) throw new Error(`User not found after update: ${id}`);
98
+ return updated;
99
+ }
100
+ async delete(id) {
101
+ const pb = new ParamBuilder(this.dialect);
102
+ const sql = `DELETE FROM ${this.table} WHERE ${this.dialect.quoteId(this.cols.id)} = ${pb.add(id)}`;
103
+ await this.exec.query(sql, pb.params);
104
+ }
105
+ async updateLastLoginAt(id) {
106
+ const pb = new ParamBuilder(this.dialect);
107
+ const sql = `UPDATE ${this.table} SET ${this.dialect.quoteId(this.cols.lastLoginAt)} = ${pb.add(/* @__PURE__ */ new Date())} WHERE ${this.dialect.quoteId(this.cols.id)} = ${pb.add(id)}`;
108
+ await this.exec.query(sql, pb.params);
109
+ }
110
+ async verifyEmail(email) {
111
+ const pb = new ParamBuilder(this.dialect);
112
+ const sql = `UPDATE ${this.table} SET ${this.dialect.quoteId(this.cols.emailVerified)} = ${pb.add(/* @__PURE__ */ new Date())} WHERE ${this.dialect.quoteId(this.cols.email)} = ${pb.add(email)}`;
113
+ await this.exec.query(sql, pb.params);
114
+ }
115
+ mapToBaseUser(row) {
116
+ var _a, _b, _c;
117
+ const c = this.cols;
118
+ return {
119
+ id: row[c.id],
120
+ email: row[c.email],
121
+ name: (_a = row[c.name]) != null ? _a : null,
122
+ role: row[c.role],
123
+ emailVerified: (_b = row[c.emailVerified]) != null ? _b : null,
124
+ isActive: row[c.isActive],
125
+ image: (_c = row[c.image]) != null ? _c : null,
126
+ createdAt: row[c.createdAt],
127
+ updatedAt: row[c.updatedAt]
128
+ };
129
+ }
130
+ };
131
+
132
+ export {
133
+ SqlUserRepository
134
+ };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  AUTH_ERROR_CODE_MAP
3
3
  } from "./chunk-R7EFDSPZ.js";
4
- import {
5
- getErrorMessage
6
- } from "./chunk-KKZCNF6U.js";
7
4
  import {
8
5
  AppError
9
6
  } from "./chunk-ATAQRXTH.js";
7
+ import {
8
+ getErrorMessage
9
+ } from "./chunk-7WG7XPXC.js";
10
10
  import {
11
11
  ERROR_CODES,
12
12
  classifyError
@@ -23,7 +23,7 @@ import {
23
23
  } from "./chunk-UWOWKOOQ.js";
24
24
  import {
25
25
  errorHandlerMiddleware
26
- } from "./chunk-BRBOGLFT.js";
26
+ } from "./chunk-KHXS4DGA.js";
27
27
 
28
28
  // src/next/middleware/wrappers.ts
29
29
  function withPublicApi(handler) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OAuthManager
3
- } from "./chunk-ER6LSA4M.js";
3
+ } from "./chunk-P7WHMKN5.js";
4
4
  import {
5
5
  generateOAuthState,
6
6
  setOAuthStateCookie
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MTZXWVW3.js";
4
4
  import {
5
5
  OAuthManager
6
- } from "./chunk-ER6LSA4M.js";
6
+ } from "./chunk-P7WHMKN5.js";
7
7
  import {
8
8
  OAUTH_STATE_COOKIE,
9
9
  clearOAuthStateCookie,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cache,
3
3
  geoCache
4
- } from "./chunk-SCAFDDJP.js";
4
+ } from "./chunk-BICSVLN7.js";
5
5
 
6
6
  // src/core/cache/cache-invalidation.ts
7
7
  var invalidateCache = {
@@ -12,7 +12,6 @@ import {
12
12
  // src/core/cache/inmemory-cache-manager.ts
13
13
  var InMemoryCacheManager = class _InMemoryCacheManager {
14
14
  constructor(prefix, config) {
15
- this.accessOrder = [];
16
15
  this.currentMemoryBytes = 0;
17
16
  this.cleanupTimer = null;
18
17
  this.prefix = prefix;
@@ -47,7 +46,6 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
47
46
  if (!entry) {
48
47
  this.metrics.misses++;
49
48
  this.updateHitRate();
50
- logger.debug(`[Cache:M] miss: ${fullKey}`);
51
49
  return null;
52
50
  }
53
51
  if (this.isExpired(entry)) {
@@ -55,17 +53,15 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
55
53
  this.metrics.misses++;
56
54
  this.metrics.expirations++;
57
55
  this.updateHitRate();
58
- logger.debug(`[Cache:M] miss (expired): ${fullKey}`);
59
56
  return null;
60
57
  }
61
58
  entry.accessedAt = Date.now();
62
- this.updateAccessOrder(fullKey);
59
+ if (this.config.evictionPolicy === "lru") {
60
+ this.cache.delete(fullKey);
61
+ this.cache.set(fullKey, entry);
62
+ }
63
63
  this.metrics.hits++;
64
64
  this.updateHitRate();
65
- logger.debug(`[Cache:M] hit: ${fullKey}`, {
66
- key: fullKey,
67
- prefix: this.prefix
68
- });
69
65
  return entry.value;
70
66
  }
71
67
  /**
@@ -81,7 +77,7 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
81
77
  const existingEntry = this.cache.get(fullKey);
82
78
  if (existingEntry) {
83
79
  this.currentMemoryBytes -= existingEntry.size;
84
- this.removeFromAccessOrder(fullKey);
80
+ this.cache.delete(fullKey);
85
81
  }
86
82
  const now = Date.now();
87
83
  const entry = {
@@ -92,7 +88,6 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
92
88
  createdAt: now
93
89
  };
94
90
  this.cache.set(fullKey, entry);
95
- this.accessOrder.push(fullKey);
96
91
  this.currentMemoryBytes += size;
97
92
  }
98
93
  /**
@@ -101,10 +96,6 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
101
96
  async delete(key) {
102
97
  const fullKey = this.getFullKey(key);
103
98
  this.deleteEntry(fullKey);
104
- logger.debug("[InMemoryCache] Cache deleted", {
105
- key: fullKey,
106
- prefix: this.prefix
107
- });
108
99
  }
109
100
  /**
110
101
  * 패턴 매칭으로 캐시 삭제
@@ -172,7 +163,6 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
172
163
  */
173
164
  clear() {
174
165
  this.cache.clear();
175
- this.accessOrder = [];
176
166
  this.currentMemoryBytes = 0;
177
167
  logger.info("[InMemoryCache] Cache cleared", { prefix: this.prefix });
178
168
  }
@@ -258,7 +248,6 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
258
248
  if (entry) {
259
249
  this.currentMemoryBytes -= entry.size;
260
250
  this.cache.delete(fullKey);
261
- this.removeFromAccessOrder(fullKey);
262
251
  }
263
252
  }
264
253
  /**
@@ -314,7 +303,7 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
314
303
  * LRU 교체: 가장 오래 접근되지 않은 항목 제거
315
304
  */
316
305
  evictLRU() {
317
- const lruKey = this.accessOrder.shift();
306
+ const lruKey = this.cache.keys().next().value;
318
307
  if (lruKey) {
319
308
  this.deleteEntry(lruKey);
320
309
  logger.debug("[InMemoryCache] LRU eviction", {
@@ -363,25 +352,6 @@ var InMemoryCacheManager = class _InMemoryCacheManager {
363
352
  });
364
353
  }
365
354
  }
366
- /**
367
- * 접근 순서 업데이트 (LRU용)
368
- */
369
- updateAccessOrder(key) {
370
- const index = this.accessOrder.indexOf(key);
371
- if (index !== -1) {
372
- this.accessOrder.splice(index, 1);
373
- }
374
- this.accessOrder.push(key);
375
- }
376
- /**
377
- * 접근 순서에서 제거
378
- */
379
- removeFromAccessOrder(key) {
380
- const index = this.accessOrder.indexOf(key);
381
- if (index !== -1) {
382
- this.accessOrder.splice(index, 1);
383
- }
384
- }
385
355
  /**
386
356
  * 히트율 업데이트
387
357
  */
@@ -0,0 +1,21 @@
1
+ import type { SqlDialect } from './types';
2
+ export interface DialectStrategy {
3
+ /** 1-based 파라미터 placeholder. postgres: $1,$2.. / mysql: ? */
4
+ placeholder(index: number): string;
5
+ /** 식별자 따옴표. postgres: "id" / mysql: `id` */
6
+ quoteId(id: string): string;
7
+ }
8
+ export declare function getDialect(dialect: SqlDialect): DialectStrategy;
9
+ /**
10
+ * placeholder 순번과 params 배열을 동기화해 누적하는 빌더.
11
+ * add()는 값을 저장하고 그 위치의 placeholder 문자열을 돌려준다.
12
+ */
13
+ export declare class ParamBuilder {
14
+ private dialect;
15
+ private _params;
16
+ constructor(dialect: DialectStrategy);
17
+ add(value: unknown): string;
18
+ get params(): unknown[];
19
+ }
20
+ /** 컬럼명 배열을 방언 따옴표로 감싸 ', ' 결합. */
21
+ export declare function columnList(columns: string[], dialect: DialectStrategy): string;
@@ -0,0 +1,11 @@
1
+ import {
2
+ ParamBuilder,
3
+ columnList,
4
+ getDialect
5
+ } from "../../../../chunk-2JUFL4KX.js";
6
+ import "../../../../chunk-N3ETBM74.js";
7
+ export {
8
+ ParamBuilder,
9
+ columnList,
10
+ getDialect
11
+ };
@@ -0,0 +1,17 @@
1
+ import type { EmailTokenRepository, EmailToken, TokenType } from '@withwiz/toolkit/core/auth/types';
2
+ import type { QueryExecutor, SqlAdapterConfig } from './types';
3
+ export declare class SqlEmailTokenRepository implements EmailTokenRepository {
4
+ private exec;
5
+ private config;
6
+ private dialect;
7
+ constructor(exec: QueryExecutor, config: SqlAdapterConfig);
8
+ private get cols();
9
+ private tableName;
10
+ private quotedTable;
11
+ private selectColumns;
12
+ create(email: string, token: string, type: TokenType, expiresAt: Date): Promise<EmailToken>;
13
+ findByEmailAndToken(email: string, token: string, type: TokenType): Promise<EmailToken | null>;
14
+ delete(email: string, token: string, type: TokenType): Promise<void>;
15
+ deleteExpired(): Promise<void>;
16
+ markAsUsed(id: string): Promise<void>;
17
+ }
@@ -0,0 +1,9 @@
1
+ import {
2
+ SqlEmailTokenRepository
3
+ } from "../../../../chunk-43XXILCX.js";
4
+ import "../../../../chunk-E4TKORMQ.js";
5
+ import "../../../../chunk-2JUFL4KX.js";
6
+ import "../../../../chunk-N3ETBM74.js";
7
+ export {
8
+ SqlEmailTokenRepository
9
+ };
@@ -0,0 +1,7 @@
1
+ export { SqlUserRepository } from './user-repository';
2
+ export { SqlOAuthAccountRepository } from './oauth-account-repository';
3
+ export { SqlEmailTokenRepository } from './email-token-repository';
4
+ export { getDialect, ParamBuilder, columnList } from './dialect';
5
+ export type { DialectStrategy } from './dialect';
6
+ export { resolveConfig } from './types';
7
+ export type { QueryExecutor, SqlDialect, SqlAdapterConfig, ResolvedSqlConfig, UserColumns, OAuthColumns, EmailTokenColumns, } from './types';
@@ -0,0 +1,27 @@
1
+ import {
2
+ SqlOAuthAccountRepository
3
+ } from "../../../../chunk-5VDT3ZB4.js";
4
+ import {
5
+ SqlUserRepository
6
+ } from "../../../../chunk-GSRAIDD7.js";
7
+ import {
8
+ SqlEmailTokenRepository
9
+ } from "../../../../chunk-43XXILCX.js";
10
+ import {
11
+ resolveConfig
12
+ } from "../../../../chunk-E4TKORMQ.js";
13
+ import {
14
+ ParamBuilder,
15
+ columnList,
16
+ getDialect
17
+ } from "../../../../chunk-2JUFL4KX.js";
18
+ import "../../../../chunk-N3ETBM74.js";
19
+ export {
20
+ ParamBuilder,
21
+ SqlEmailTokenRepository,
22
+ SqlOAuthAccountRepository,
23
+ SqlUserRepository,
24
+ columnList,
25
+ getDialect,
26
+ resolveConfig
27
+ };
@@ -0,0 +1,18 @@
1
+ import type { OAuthAccountRepository, OAuthAccount, CreateOAuthAccountData, UpdateOAuthAccountData } from '@withwiz/toolkit/core/auth/types';
2
+ import type { QueryExecutor, SqlAdapterConfig } from './types';
3
+ export declare class SqlOAuthAccountRepository implements OAuthAccountRepository {
4
+ private exec;
5
+ private config;
6
+ private dialect;
7
+ constructor(exec: QueryExecutor, config: SqlAdapterConfig);
8
+ private get table();
9
+ private get cols();
10
+ private selectColumns;
11
+ findByProvider(provider: string, providerAccountId: string): Promise<OAuthAccount | null>;
12
+ findByUserId(userId: string): Promise<OAuthAccount[]>;
13
+ create(data: CreateOAuthAccountData): Promise<OAuthAccount>;
14
+ update(id: string, data: UpdateOAuthAccountData): Promise<OAuthAccount>;
15
+ delete(id: string): Promise<void>;
16
+ private selectById;
17
+ private mapToOAuthAccount;
18
+ }
@@ -0,0 +1,9 @@
1
+ import {
2
+ SqlOAuthAccountRepository
3
+ } from "../../../../chunk-5VDT3ZB4.js";
4
+ import "../../../../chunk-E4TKORMQ.js";
5
+ import "../../../../chunk-2JUFL4KX.js";
6
+ import "../../../../chunk-N3ETBM74.js";
7
+ export {
8
+ SqlOAuthAccountRepository
9
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Raw SQL Auth Adapter — 공유 타입 & config 해석.
3
+ */
4
+ /** 실행할 SQL 방언. */
5
+ export type SqlDialect = 'postgres' | 'mysql';
6
+ /**
7
+ * 드라이버 독립 쿼리 실행기. 소비자가 자기 드라이버를 한 줄 wrapping 해 주입한다.
8
+ *
9
+ * @example
10
+ * // pg
11
+ * const exec = { query: (sql, p) => pool.query(sql, p).then((r) => r.rows) };
12
+ * // mysql2/promise
13
+ * const exec = { query: (sql, p) => pool.query(sql, p).then(([rows]) => rows) };
14
+ */
15
+ export interface QueryExecutor {
16
+ query(sql: string, params: unknown[]): Promise<Record<string, unknown>[]>;
17
+ }
18
+ export interface UserColumns {
19
+ id: string;
20
+ email: string;
21
+ name: string;
22
+ password: string;
23
+ role: string;
24
+ image: string;
25
+ emailVerified: string;
26
+ isActive: string;
27
+ createdAt: string;
28
+ updatedAt: string;
29
+ lastLoginAt: string;
30
+ }
31
+ export interface OAuthColumns {
32
+ id: string;
33
+ userId: string;
34
+ provider: string;
35
+ providerAccountId: string;
36
+ accessToken: string;
37
+ refreshToken: string;
38
+ expiresAt: string;
39
+ tokenType: string;
40
+ scope: string;
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ }
44
+ export interface EmailTokenColumns {
45
+ id: string;
46
+ email: string;
47
+ token: string;
48
+ expires: string;
49
+ used: string;
50
+ createdAt: string;
51
+ }
52
+ export interface SqlAdapterConfig {
53
+ dialect: SqlDialect;
54
+ tables?: {
55
+ user?: string;
56
+ oauthAccount?: string;
57
+ emailVerification?: string;
58
+ passwordReset?: string;
59
+ magicLink?: string;
60
+ };
61
+ userColumns?: Partial<UserColumns>;
62
+ oauthColumns?: Partial<OAuthColumns>;
63
+ emailTokenColumns?: Partial<EmailTokenColumns>;
64
+ }
65
+ export interface ResolvedSqlConfig {
66
+ dialect: SqlDialect;
67
+ tables: Required<NonNullable<SqlAdapterConfig['tables']>>;
68
+ userColumns: UserColumns;
69
+ oauthColumns: OAuthColumns;
70
+ emailTokenColumns: EmailTokenColumns;
71
+ }
72
+ /** SqlAdapterConfig를 기본값으로 채워 완전한 ResolvedSqlConfig로 해석한다. */
73
+ export declare function resolveConfig(config: SqlAdapterConfig): ResolvedSqlConfig;
@@ -0,0 +1,7 @@
1
+ import {
2
+ resolveConfig
3
+ } from "../../../../chunk-E4TKORMQ.js";
4
+ import "../../../../chunk-N3ETBM74.js";
5
+ export {
6
+ resolveConfig
7
+ };
@@ -0,0 +1,20 @@
1
+ import type { UserRepository, BaseUser, CreateUserData, UpdateUserData } from '@withwiz/toolkit/core/auth/types';
2
+ import type { QueryExecutor, SqlAdapterConfig } from './types';
3
+ export declare class SqlUserRepository implements UserRepository {
4
+ private exec;
5
+ private config;
6
+ private dialect;
7
+ constructor(exec: QueryExecutor, config: SqlAdapterConfig);
8
+ private get table();
9
+ private get cols();
10
+ /** password 제외 SELECT/매핑 대상 컬럼. */
11
+ private selectColumns;
12
+ findById(id: string): Promise<BaseUser | null>;
13
+ findByEmail(email: string): Promise<BaseUser | null>;
14
+ create(data: CreateUserData): Promise<BaseUser>;
15
+ update(id: string, data: UpdateUserData): Promise<BaseUser>;
16
+ delete(id: string): Promise<void>;
17
+ updateLastLoginAt(id: string): Promise<void>;
18
+ verifyEmail(email: string): Promise<void>;
19
+ private mapToBaseUser;
20
+ }
@@ -0,0 +1,9 @@
1
+ import {
2
+ SqlUserRepository
3
+ } from "../../../../chunk-GSRAIDD7.js";
4
+ import "../../../../chunk-E4TKORMQ.js";
5
+ import "../../../../chunk-2JUFL4KX.js";
6
+ import "../../../../chunk-N3ETBM74.js";
7
+ export {
8
+ SqlUserRepository
9
+ };
@@ -36,12 +36,8 @@ import {
36
36
  } from "../../chunk-5I3EQHR4.js";
37
37
  import {
38
38
  OAuthManager
39
- } from "../../chunk-ER6LSA4M.js";
39
+ } from "../../chunk-P7WHMKN5.js";
40
40
  import "../../chunk-CDALZTPN.js";
41
- import "../../chunk-GSSHHVHF.js";
42
- import {
43
- GitHubOAuthProvider
44
- } from "../../chunk-HIZ7USIF.js";
45
41
  import {
46
42
  GoogleOAuthProvider
47
43
  } from "../../chunk-GF3DKZIW.js";
@@ -49,11 +45,11 @@ import {
49
45
  KakaoOAuthProvider
50
46
  } from "../../chunk-65HVR74O.js";
51
47
  import "../../chunk-33RIHX7O.js";
52
- import "../../chunk-JLRMET4V.js";
48
+ import "../../chunk-GSSHHVHF.js";
53
49
  import {
54
- JWTManager,
55
- JWTService
56
- } from "../../chunk-LWHLB2Y6.js";
50
+ GitHubOAuthProvider
51
+ } from "../../chunk-HIZ7USIF.js";
52
+ import "../../chunk-JLRMET4V.js";
57
53
  import {
58
54
  TokenGenerator
59
55
  } from "../../chunk-ZZABL54F.js";
@@ -62,6 +58,10 @@ import {
62
58
  PasswordStrength,
63
59
  TokenType
64
60
  } from "../../chunk-GH3U4WRE.js";
61
+ import {
62
+ JWTManager,
63
+ JWTService
64
+ } from "../../chunk-LWHLB2Y6.js";
65
65
  import {
66
66
  AUTH_ERROR_CODES,
67
67
  AuthError,
@@ -1,13 +1,7 @@
1
1
  import {
2
2
  OAuthManager
3
- } from "../../../chunk-ER6LSA4M.js";
3
+ } from "../../../chunk-P7WHMKN5.js";
4
4
  import "../../../chunk-CDALZTPN.js";
5
- import {
6
- MicrosoftOAuthProvider
7
- } from "../../../chunk-GSSHHVHF.js";
8
- import {
9
- GitHubOAuthProvider
10
- } from "../../../chunk-HIZ7USIF.js";
11
5
  import {
12
6
  GoogleOAuthProvider
13
7
  } from "../../../chunk-GF3DKZIW.js";
@@ -17,6 +11,12 @@ import {
17
11
  import {
18
12
  MetaOAuthProvider
19
13
  } from "../../../chunk-33RIHX7O.js";
14
+ import {
15
+ MicrosoftOAuthProvider
16
+ } from "../../../chunk-GSSHHVHF.js";
17
+ import {
18
+ GitHubOAuthProvider
19
+ } from "../../../chunk-HIZ7USIF.js";
20
20
  import {
21
21
  OAUTH_STATE_COOKIE,
22
22
  clearOAuthStateCookie,
@@ -1,10 +1,4 @@
1
1
  import "../../../../chunk-CDALZTPN.js";
2
- import {
3
- MicrosoftOAuthProvider
4
- } from "../../../../chunk-GSSHHVHF.js";
5
- import {
6
- GitHubOAuthProvider
7
- } from "../../../../chunk-HIZ7USIF.js";
8
2
  import {
9
3
  GoogleOAuthProvider
10
4
  } from "../../../../chunk-GF3DKZIW.js";
@@ -14,6 +8,12 @@ import {
14
8
  import {
15
9
  MetaOAuthProvider
16
10
  } from "../../../../chunk-33RIHX7O.js";
11
+ import {
12
+ MicrosoftOAuthProvider
13
+ } from "../../../../chunk-GSSHHVHF.js";
14
+ import {
15
+ GitHubOAuthProvider
16
+ } from "../../../../chunk-HIZ7USIF.js";
17
17
  import "../../../../chunk-5GWGARXI.js";
18
18
  import "../../../../chunk-N3ETBM74.js";
19
19
  export {
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  LoginService
3
3
  } from "../../../chunk-TNDEYJEL.js";
4
- import {
5
- EmailVerificationService
6
- } from "../../../chunk-VWKZMGPJ.js";
7
4
  import {
8
5
  OAuthCallbackService
9
6
  } from "../../../chunk-MTZXWVW3.js";
@@ -13,12 +10,15 @@ import {
13
10
  import {
14
11
  RegisterService
15
12
  } from "../../../chunk-Y4ME3Q5K.js";
13
+ import {
14
+ EmailVerificationService
15
+ } from "../../../chunk-VWKZMGPJ.js";
16
16
  import {
17
17
  PasswordResetService
18
18
  } from "../../../chunk-75UDFONR.js";
19
- import "../../../chunk-LWHLB2Y6.js";
20
19
  import "../../../chunk-ZZABL54F.js";
21
20
  import "../../../chunk-GH3U4WRE.js";
21
+ import "../../../chunk-LWHLB2Y6.js";
22
22
  import "../../../chunk-5GWGARXI.js";
23
23
  import "../../../chunk-PRPMEHRE.js";
24
24
  import "../../../chunk-N3TCQ5BF.js";