clearauth 0.3.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/LICENSE +21 -0
  3. package/README.md +417 -0
  4. package/dist/auth/handler.d.ts +38 -0
  5. package/dist/auth/handler.js +483 -0
  6. package/dist/auth/handler.js.map +1 -0
  7. package/dist/auth/login.d.ts +69 -0
  8. package/dist/auth/login.js +103 -0
  9. package/dist/auth/login.js.map +1 -0
  10. package/dist/auth/register.d.ts +72 -0
  11. package/dist/auth/register.js +122 -0
  12. package/dist/auth/register.js.map +1 -0
  13. package/dist/auth/reset-password.d.ts +106 -0
  14. package/dist/auth/reset-password.js +213 -0
  15. package/dist/auth/reset-password.js.map +1 -0
  16. package/dist/auth/utils.d.ts +58 -0
  17. package/dist/auth/utils.js +121 -0
  18. package/dist/auth/utils.js.map +1 -0
  19. package/dist/auth/verify-email.d.ts +70 -0
  20. package/dist/auth/verify-email.js +137 -0
  21. package/dist/auth/verify-email.js.map +1 -0
  22. package/dist/createMechAuth.d.ts +178 -0
  23. package/dist/createMechAuth.js +215 -0
  24. package/dist/createMechAuth.js.map +1 -0
  25. package/dist/database/schema.d.ts +135 -0
  26. package/dist/database/schema.js +37 -0
  27. package/dist/database/schema.js.map +1 -0
  28. package/dist/edge.d.ts +4 -0
  29. package/dist/edge.js +6 -0
  30. package/dist/edge.js.map +1 -0
  31. package/dist/errors.d.ts +25 -0
  32. package/dist/errors.js +44 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/handler.d.ts +100 -0
  35. package/dist/handler.js +213 -0
  36. package/dist/handler.js.map +1 -0
  37. package/dist/index.d.ts +22 -0
  38. package/dist/index.js +28 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/logger.d.ts +22 -0
  41. package/dist/logger.js +40 -0
  42. package/dist/logger.js.map +1 -0
  43. package/dist/mech-kysely.d.ts +22 -0
  44. package/dist/mech-kysely.js +88 -0
  45. package/dist/mech-kysely.js.map +1 -0
  46. package/dist/mech-sql-client.d.ts +85 -0
  47. package/dist/mech-sql-client.js +155 -0
  48. package/dist/mech-sql-client.js.map +1 -0
  49. package/dist/node.d.ts +4 -0
  50. package/dist/node.js +10 -0
  51. package/dist/node.js.map +1 -0
  52. package/dist/oauth/arctic-providers.d.ts +60 -0
  53. package/dist/oauth/arctic-providers.js +94 -0
  54. package/dist/oauth/arctic-providers.js.map +1 -0
  55. package/dist/oauth/callbacks.d.ts +155 -0
  56. package/dist/oauth/callbacks.js +286 -0
  57. package/dist/oauth/callbacks.js.map +1 -0
  58. package/dist/oauth/github.d.ts +47 -0
  59. package/dist/oauth/github.js +136 -0
  60. package/dist/oauth/github.js.map +1 -0
  61. package/dist/oauth/google.d.ts +49 -0
  62. package/dist/oauth/google.js +104 -0
  63. package/dist/oauth/google.js.map +1 -0
  64. package/dist/oauth/handler.d.ts +31 -0
  65. package/dist/oauth/handler.js +277 -0
  66. package/dist/oauth/handler.js.map +1 -0
  67. package/dist/password-hasher-argon2.d.ts +7 -0
  68. package/dist/password-hasher-argon2.js +16 -0
  69. package/dist/password-hasher-argon2.js.map +1 -0
  70. package/dist/password-hasher.d.ts +12 -0
  71. package/dist/password-hasher.js +115 -0
  72. package/dist/password-hasher.js.map +1 -0
  73. package/dist/react.d.ts +152 -0
  74. package/dist/react.js +296 -0
  75. package/dist/react.js.map +1 -0
  76. package/dist/types.d.ts +190 -0
  77. package/dist/types.js +7 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/utils/cors.d.ts +65 -0
  80. package/dist/utils/cors.js +152 -0
  81. package/dist/utils/cors.js.map +1 -0
  82. package/dist/utils/normalize-auth-path.d.ts +1 -0
  83. package/dist/utils/normalize-auth-path.js +8 -0
  84. package/dist/utils/normalize-auth-path.js.map +1 -0
  85. package/dist/validation.d.ts +23 -0
  86. package/dist/validation.js +70 -0
  87. package/dist/validation.js.map +1 -0
  88. package/package.json +93 -0
@@ -0,0 +1,155 @@
1
+ import { ClearAuthSqlError, ClearAuthNetworkError, ClearAuthTimeoutError, ClearAuthRateLimitError, } from "./errors.js";
2
+ import { getDefaultLogger } from "./logger.js";
3
+ import { validateUrl, validateUuid, validateNonEmpty, validatePositive, validateRange } from "./validation.js";
4
+ /**
5
+ * HTTP client for Mech Storage PostgreSQL API
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const client = new MechSqlClient()
10
+ * const { rows } = await client.execute("SELECT * FROM users WHERE id = $1", [123])
11
+ * ```
12
+ */
13
+ export class MechSqlClient {
14
+ constructor(config) {
15
+ // Resolve values with smart defaults
16
+ this.baseUrl = config.baseUrl ?? "https://storage.mechdna.net";
17
+ this.appId = config.appId;
18
+ // appSchemaId defaults to appId if not explicitly provided (most common case)
19
+ this.appSchemaId = config.appSchemaId ?? this.appId;
20
+ this.apiKey = config.apiKey;
21
+ this.timeout = config.timeout ?? 30000;
22
+ this.logger = config.logger ?? getDefaultLogger();
23
+ this.maxRetries = config.maxRetries ?? 2;
24
+ // Validate configuration
25
+ validateUrl(this.baseUrl, "baseUrl");
26
+ validateNonEmpty(this.appId, "appId");
27
+ validateUuid(this.appId, "appId");
28
+ validateNonEmpty(this.appSchemaId, "appSchemaId");
29
+ validateUuid(this.appSchemaId, "appSchemaId");
30
+ validateNonEmpty(this.apiKey, "apiKey");
31
+ validatePositive(this.timeout, "timeout");
32
+ validateRange(this.maxRetries, 0, 5, "maxRetries");
33
+ this.logger.debug("MechSqlClient initialized", {
34
+ baseUrl: this.baseUrl,
35
+ appId: this.appId,
36
+ timeout: this.timeout,
37
+ maxRetries: this.maxRetries
38
+ });
39
+ }
40
+ /**
41
+ * Execute a SQL query against Mech Storage
42
+ *
43
+ * @param sql - SQL query string (use $1, $2, etc. for parameters)
44
+ * @param params - Query parameters
45
+ * @returns Object with rows and rowCount
46
+ * @throws ClearAuthSqlError, ClearAuthNetworkError, ClearAuthTimeoutError, ClearAuthRateLimitError
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * const { rows } = await client.execute(
51
+ * "SELECT * FROM users WHERE email = $1",
52
+ * ["user@example.com"]
53
+ * )
54
+ * ```
55
+ */
56
+ async execute(sql, params = []) {
57
+ return this.executeWithRetry(sql, params, 0);
58
+ }
59
+ async executeWithRetry(sql, params, attempt) {
60
+ try {
61
+ return await this.executeOnce(sql, params);
62
+ }
63
+ catch (err) {
64
+ if (attempt < this.maxRetries && this.isRetryable(err)) {
65
+ const delay = Math.pow(2, attempt) * 100; // exponential backoff
66
+ this.logger.warn(`Query failed, retrying in ${delay}ms (attempt ${attempt + 1}/${this.maxRetries})`, {
67
+ error: err.message,
68
+ attempt
69
+ });
70
+ await new Promise((resolve) => setTimeout(resolve, delay));
71
+ return this.executeWithRetry(sql, params, attempt + 1);
72
+ }
73
+ throw err;
74
+ }
75
+ }
76
+ async executeOnce(sql, params) {
77
+ const url = `${this.baseUrl.replace(/\/$/, "")}/api/apps/${this.appId}/postgresql/query`;
78
+ this.logger.debug("Executing SQL query", {
79
+ url,
80
+ paramCount: params.length,
81
+ sqlLength: sql.length
82
+ });
83
+ const controller = new AbortController();
84
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
85
+ try {
86
+ const res = await fetch(url, {
87
+ method: "POST",
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ "X-API-Key": this.apiKey,
91
+ "X-App-ID": this.appSchemaId
92
+ },
93
+ body: JSON.stringify({ sql, params }),
94
+ signal: controller.signal
95
+ });
96
+ // Handle rate limiting
97
+ if (res.status === 429) {
98
+ const retryAfter = parseInt(res.headers.get("Retry-After") ?? "60", 10) * 1000;
99
+ this.logger.warn("Rate limited by Mech Storage", { retryAfter });
100
+ throw new ClearAuthRateLimitError(retryAfter, { statusCode: 429 });
101
+ }
102
+ if (!res.ok) {
103
+ const text = await res.text();
104
+ this.logger.error("HTTP error from Mech Storage", {
105
+ status: res.status,
106
+ statusText: res.statusText,
107
+ responseLength: text.length
108
+ });
109
+ throw new ClearAuthNetworkError(`HTTP ${res.status}: ${res.statusText}`, res.status, {
110
+ responseText: text.substring(0, 500) // truncate for logging
111
+ });
112
+ }
113
+ const json = await res.json();
114
+ if (json.success === false) {
115
+ this.logger.error("Mech Storage returned error", {
116
+ code: json.error?.code,
117
+ message: json.error?.message
118
+ });
119
+ throw new ClearAuthSqlError(json.error?.message ?? "Unknown error", {
120
+ code: json.error?.code,
121
+ hints: json.error?.hints
122
+ });
123
+ }
124
+ const rows = (json.rows ?? []);
125
+ const rowCount = json.rowCount ?? rows.length;
126
+ this.logger.debug("Query executed successfully", {
127
+ rowCount,
128
+ rowsReturned: rows.length
129
+ });
130
+ return { rows, rowCount };
131
+ }
132
+ catch (err) {
133
+ if (err instanceof DOMException && err.name === "AbortError") {
134
+ this.logger.error("Query timeout", { timeout: this.timeout });
135
+ throw new ClearAuthTimeoutError(`Query timed out after ${this.timeout}ms`, {
136
+ timeout: this.timeout
137
+ });
138
+ }
139
+ throw err;
140
+ }
141
+ finally {
142
+ clearTimeout(timeoutId);
143
+ }
144
+ }
145
+ isRetryable(err) {
146
+ if (err instanceof ClearAuthRateLimitError)
147
+ return true;
148
+ if (err instanceof ClearAuthTimeoutError)
149
+ return true;
150
+ if (err instanceof ClearAuthNetworkError && err.statusCode && err.statusCode >= 500)
151
+ return true;
152
+ return false;
153
+ }
154
+ }
155
+ //# sourceMappingURL=mech-sql-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mech-sql-client.js","sourceRoot":"","sources":["../src/mech-sql-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAU,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AA8C9G;;;;;;;;GAQG;AACH,MAAM,OAAO,aAAa;IASxB,YAAY,MAA2B;QACrC,qCAAqC;QACrC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,6BAA6B,CAAA;QAC9D,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;QACzB,8EAA8E;QAC9E,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAA;QACnD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,KAAK,CAAA;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAA;QACjD,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,CAAC,CAAA;QAExC,yBAAyB;QACzB,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QACpC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACrC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACjC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;QACjD,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;QAC7C,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACvC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QACzC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAA;QAElD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE;YAC7C,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,OAAO,CAAc,GAAW,EAAE,SAA6B,EAAE;QACrE,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC9C,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,GAAW,EACX,MAA0B,EAC1B,OAAe;QAEf,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,WAAW,CAAI,GAAG,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,OAAO,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,GAAG,CAAA,CAAC,sBAAsB;gBAC/D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,KAAK,eAAe,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,GAAG,EAAE;oBACnG,KAAK,EAAG,GAAa,CAAC,OAAO;oBAC7B,OAAO;iBACR,CAAC,CAAA;gBACF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;gBAC1D,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,CAAA;YACxD,CAAC;YACD,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW,CAAc,GAAW,EAAE,MAA0B;QAC5E,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,IAAI,CAAC,KAAK,mBAAmB,CAAA;QAExF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE;YACvC,GAAG;YACH,UAAU,EAAE,MAAM,CAAC,MAAM;YACzB,SAAS,EAAE,GAAG,CAAC,MAAM;SACtB,CAAC,CAAA;QAEF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAEpE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;oBACxB,UAAU,EAAE,IAAI,CAAC,WAAW;iBAC7B;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;gBACrC,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAA;YAEF,uBAAuB;YACvB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAA;gBAC9E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;gBAChE,MAAM,IAAI,uBAAuB,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAA;YACpE,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;gBAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE;oBAChD,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,cAAc,EAAE,IAAI,CAAC,MAAM;iBAC5B,CAAC,CAAA;gBACF,MAAM,IAAI,qBAAqB,CAAC,QAAQ,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE;oBACnF,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,uBAAuB;iBAC7D,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,IAAI,GAAoB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAE9C,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI;oBACtB,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO;iBAC7B,CAAC,CAAA;gBACF,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE;oBAClE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI;oBACtB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK;iBACzB,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAQ,CAAA;YACrC,MAAM,QAAQ,GAAW,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAA;YAErD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE;gBAC/C,QAAQ;gBACR,YAAY,EAAE,IAAI,CAAC,MAAM;aAC1B,CAAC,CAAA;YAEF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC7D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;gBAC7D,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,IAAI,CAAC,OAAO,IAAI,EAAE;oBACzE,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC,CAAA;YACJ,CAAC;YACD,MAAM,GAAG,CAAA;QACX,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,SAAS,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAAY;QAC9B,IAAI,GAAG,YAAY,uBAAuB;YAAE,OAAO,IAAI,CAAA;QACvD,IAAI,GAAG,YAAY,qBAAqB;YAAE,OAAO,IAAI,CAAA;QACrD,IAAI,GAAG,YAAY,qBAAqB,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG;YAAE,OAAO,IAAI,CAAA;QAChG,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { CreateClearAuthOptions } from "./createMechAuth.js";
2
+ export declare function createClearAuthNode(options: CreateClearAuthOptions): import("./types.js").ClearAuthConfig;
3
+ export { defaultSessionConfig, longSessionConfig, shortSessionConfig } from "./createMechAuth.js";
4
+ export type { ClearAuthConfig } from "./types.js";
package/dist/node.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createClearAuth } from "./createMechAuth.js";
2
+ import { createArgon2idPasswordHasher } from "./password-hasher-argon2.js";
3
+ export function createClearAuthNode(options) {
4
+ return createClearAuth({
5
+ ...options,
6
+ passwordHasher: options.passwordHasher ?? createArgon2idPasswordHasher(),
7
+ });
8
+ }
9
+ export { defaultSessionConfig, longSessionConfig, shortSessionConfig } from "./createMechAuth.js";
10
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAA;AAE1E,MAAM,UAAU,mBAAmB,CAAC,OAA+B;IACjE,OAAO,eAAe,CAAC;QACrB,GAAG,OAAO;QACV,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,4BAA4B,EAAE;KACzE,CAAC,CAAA;AACJ,CAAC;AAED,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Arctic OAuth Provider Factory
3
+ *
4
+ * Creates Arctic OAuth provider instances for GitHub and Google authentication.
5
+ * Arctic is a lightweight OAuth library that works across all JavaScript runtimes
6
+ * including Cloudflare Workers.
7
+ *
8
+ * @see https://arcticjs.dev/
9
+ */
10
+ import { GitHub, Google } from 'arctic';
11
+ import type { ClearAuthConfig } from '../types.js';
12
+ /**
13
+ * Create GitHub OAuth provider instance
14
+ *
15
+ * @param config - ClearAuth configuration
16
+ * @returns Arctic GitHub provider instance
17
+ * @throws Error if GitHub OAuth is not configured
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const github = createGitHubProvider(config)
22
+ * const url = await github.createAuthorizationURL(state, { scopes: ['user:email'] })
23
+ * ```
24
+ */
25
+ export declare function createGitHubProvider(config: ClearAuthConfig): GitHub;
26
+ /**
27
+ * Create Google OAuth provider instance
28
+ *
29
+ * @param config - ClearAuth configuration
30
+ * @returns Arctic Google provider instance
31
+ * @throws Error if Google OAuth is not configured
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const google = createGoogleProvider(config)
36
+ * const url = await google.createAuthorizationURL(state, codeVerifier, { scopes: ['email', 'profile'] })
37
+ * ```
38
+ */
39
+ export declare function createGoogleProvider(config: ClearAuthConfig): Google;
40
+ /**
41
+ * Get configured OAuth providers
42
+ *
43
+ * Returns a map of provider names to Arctic provider instances.
44
+ * Only includes providers that are configured.
45
+ *
46
+ * @param config - ClearAuth configuration
47
+ * @returns Map of provider names to Arctic provider instances
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const providers = getConfiguredProviders(config)
52
+ * if (providers.github) {
53
+ * // GitHub is configured
54
+ * }
55
+ * ```
56
+ */
57
+ export declare function getConfiguredProviders(config: ClearAuthConfig): {
58
+ github?: GitHub;
59
+ google?: Google;
60
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Arctic OAuth Provider Factory
3
+ *
4
+ * Creates Arctic OAuth provider instances for GitHub and Google authentication.
5
+ * Arctic is a lightweight OAuth library that works across all JavaScript runtimes
6
+ * including Cloudflare Workers.
7
+ *
8
+ * @see https://arcticjs.dev/
9
+ */
10
+ import { GitHub, Google } from 'arctic';
11
+ /**
12
+ * Create GitHub OAuth provider instance
13
+ *
14
+ * @param config - ClearAuth configuration
15
+ * @returns Arctic GitHub provider instance
16
+ * @throws Error if GitHub OAuth is not configured
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const github = createGitHubProvider(config)
21
+ * const url = await github.createAuthorizationURL(state, { scopes: ['user:email'] })
22
+ * ```
23
+ */
24
+ export function createGitHubProvider(config) {
25
+ if (!config.oauth?.github) {
26
+ throw new Error('GitHub OAuth is not configured');
27
+ }
28
+ const { clientId, clientSecret, redirectUri } = config.oauth.github;
29
+ if (!clientId || !clientSecret || !redirectUri) {
30
+ throw new Error('GitHub OAuth configuration is incomplete (missing clientId, clientSecret, or redirectUri)');
31
+ }
32
+ return new GitHub(clientId, clientSecret, redirectUri);
33
+ }
34
+ /**
35
+ * Create Google OAuth provider instance
36
+ *
37
+ * @param config - ClearAuth configuration
38
+ * @returns Arctic Google provider instance
39
+ * @throws Error if Google OAuth is not configured
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * const google = createGoogleProvider(config)
44
+ * const url = await google.createAuthorizationURL(state, codeVerifier, { scopes: ['email', 'profile'] })
45
+ * ```
46
+ */
47
+ export function createGoogleProvider(config) {
48
+ if (!config.oauth?.google) {
49
+ throw new Error('Google OAuth is not configured');
50
+ }
51
+ const { clientId, clientSecret, redirectUri } = config.oauth.google;
52
+ if (!clientId || !clientSecret || !redirectUri) {
53
+ throw new Error('Google OAuth configuration is incomplete (missing clientId, clientSecret, or redirectUri)');
54
+ }
55
+ return new Google(clientId, clientSecret, redirectUri);
56
+ }
57
+ /**
58
+ * Get configured OAuth providers
59
+ *
60
+ * Returns a map of provider names to Arctic provider instances.
61
+ * Only includes providers that are configured.
62
+ *
63
+ * @param config - ClearAuth configuration
64
+ * @returns Map of provider names to Arctic provider instances
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const providers = getConfiguredProviders(config)
69
+ * if (providers.github) {
70
+ * // GitHub is configured
71
+ * }
72
+ * ```
73
+ */
74
+ export function getConfiguredProviders(config) {
75
+ const providers = {};
76
+ if (config.oauth?.github) {
77
+ try {
78
+ providers.github = createGitHubProvider(config);
79
+ }
80
+ catch (err) {
81
+ console.error('Failed to create GitHub provider:', err);
82
+ }
83
+ }
84
+ if (config.oauth?.google) {
85
+ try {
86
+ providers.google = createGoogleProvider(config);
87
+ }
88
+ catch (err) {
89
+ console.error('Failed to create Google provider:', err);
90
+ }
91
+ }
92
+ return providers;
93
+ }
94
+ //# sourceMappingURL=arctic-providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arctic-providers.js","sourceRoot":"","sources":["../../src/oauth/arctic-providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAGvC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAuB;IAC1D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;IACnD,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA;IAEnE,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAA;IAC9G,CAAC;IAED,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAC,CAAA;AACxD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAuB;IAC1D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;IACnD,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA;IAEnE,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAA;IAC9G,CAAC;IAED,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAC,CAAA;AACxD,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAuB;IAI5D,MAAM,SAAS,GAAyC,EAAE,CAAA;IAE1D,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,SAAS,CAAC,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,SAAS,CAAC,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * OAuth Callback Utilities
3
+ *
4
+ * Shared logic for OAuth callback handling including:
5
+ * - State parameter validation (CSRF protection)
6
+ * - User upsert (create or update user by OAuth provider ID)
7
+ * - Session creation after successful OAuth
8
+ * - Error handling
9
+ */
10
+ import type { Kysely } from 'kysely';
11
+ import type { Database, User } from '../database/schema.js';
12
+ import type { OAuthUserProfile, RequestContext } from '../types.js';
13
+ /**
14
+ * Upsert user from OAuth profile
15
+ *
16
+ * Creates a new user or updates an existing user based on the OAuth provider ID.
17
+ * Uses github_id or google_id column to identify existing users.
18
+ *
19
+ * @param db - Kysely database instance
20
+ * @param provider - OAuth provider name ('github' or 'google')
21
+ * @param profile - Normalized OAuth user profile
22
+ * @returns User record from database
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const user = await upsertOAuthUser(db, 'github', profile)
27
+ * ```
28
+ */
29
+ export declare function upsertOAuthUser(db: Kysely<Database>, provider: 'github' | 'google', profile: OAuthUserProfile): Promise<User>;
30
+ /**
31
+ * Create session for user
32
+ *
33
+ * Creates a new session record in the database and returns the session ID.
34
+ * Sessions expire after the configured duration (default: 30 days).
35
+ *
36
+ * @param db - Kysely database instance
37
+ * @param userId - User ID to create session for
38
+ * @param expiresInSeconds - Session expiration time in seconds (default: 2592000 = 30 days)
39
+ * @param context - Optional request context (IP address, user agent)
40
+ * @returns Session ID
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * const sessionId = await createSession(db, user.id, 2592000, { ipAddress, userAgent })
45
+ * ```
46
+ */
47
+ export declare function createSession(db: Kysely<Database>, userId: string, expiresInSeconds?: number, // 30 days
48
+ context?: RequestContext): Promise<string>;
49
+ /**
50
+ * Validate session
51
+ *
52
+ * Checks if a session exists and is not expired.
53
+ *
54
+ * @param db - Kysely database instance
55
+ * @param sessionId - Session ID to validate
56
+ * @returns User if session is valid, null otherwise
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const user = await validateSession(db, sessionId)
61
+ * if (!user) {
62
+ * return new Response('Unauthorized', { status: 401 })
63
+ * }
64
+ * ```
65
+ */
66
+ export declare function validateSession(db: Kysely<Database>, sessionId: string): Promise<User | null>;
67
+ /**
68
+ * Delete session (logout)
69
+ *
70
+ * Removes a session from the database.
71
+ *
72
+ * @param db - Kysely database instance
73
+ * @param sessionId - Session ID to delete
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * await deleteSession(db, sessionId)
78
+ * ```
79
+ */
80
+ export declare function deleteSession(db: Kysely<Database>, sessionId: string): Promise<void>;
81
+ /**
82
+ * Delete all sessions for a user
83
+ *
84
+ * Removes all sessions for a specific user (useful for password changes, etc.)
85
+ *
86
+ * @param db - Kysely database instance
87
+ * @param userId - User ID to delete sessions for
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * await deleteAllUserSessions(db, userId)
92
+ * ```
93
+ */
94
+ export declare function deleteAllUserSessions(db: Kysely<Database>, userId: string): Promise<void>;
95
+ /**
96
+ * Clean up expired sessions
97
+ *
98
+ * Removes all expired sessions from the database.
99
+ * This should be run periodically as a background job.
100
+ *
101
+ * @param db - Kysely database instance
102
+ * @returns Number of sessions deleted
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * const deleted = await cleanupExpiredSessions(db)
107
+ * console.log(`Cleaned up ${deleted} expired sessions`)
108
+ * ```
109
+ */
110
+ export declare function cleanupExpiredSessions(db: Kysely<Database>): Promise<number>;
111
+ /**
112
+ * Parse cookie header
113
+ *
114
+ * Parses the Cookie header and returns a map of cookie names to values.
115
+ *
116
+ * @param cookieHeader - Cookie header string
117
+ * @returns Map of cookie names to values
118
+ *
119
+ * @internal
120
+ */
121
+ export declare function parseCookies(cookieHeader: string): Record<string, string>;
122
+ /**
123
+ * Create cookie header
124
+ *
125
+ * Creates a Set-Cookie header string with appropriate security attributes.
126
+ *
127
+ * @param name - Cookie name
128
+ * @param value - Cookie value
129
+ * @param options - Cookie options
130
+ * @returns Set-Cookie header string
131
+ *
132
+ * @internal
133
+ */
134
+ export declare function createCookieHeader(name: string, value: string, options?: {
135
+ httpOnly?: boolean;
136
+ secure?: boolean;
137
+ sameSite?: 'strict' | 'lax' | 'none';
138
+ path?: string;
139
+ maxAge?: number;
140
+ expires?: Date;
141
+ }): string;
142
+ /**
143
+ * Create delete cookie header
144
+ *
145
+ * Creates a Set-Cookie header that deletes a cookie.
146
+ *
147
+ * @param name - Cookie name
148
+ * @param options - Cookie options (path, etc.)
149
+ * @returns Set-Cookie header string
150
+ *
151
+ * @internal
152
+ */
153
+ export declare function createDeleteCookieHeader(name: string, options?: {
154
+ path?: string;
155
+ }): string;