@payez/next-mvp 4.4.6 → 4.4.7

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 (51) hide show
  1. package/dist/api-handlers/account/change-password.js +28 -6
  2. package/dist/auth/better-auth.d.ts +44 -14
  3. package/dist/auth/better-auth.js +92 -7
  4. package/dist/client/better-auth-client.d.ts +101 -956
  5. package/dist/config/env.d.ts +0 -2
  6. package/dist/config/env.js +0 -2
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +8 -1
  9. package/dist/lib/idp-client-config.js +8 -1
  10. package/dist/lib/never-in-response.d.ts +30 -0
  11. package/dist/lib/never-in-response.js +71 -0
  12. package/dist/lib/safe-error-response.d.ts +6 -6
  13. package/dist/lib/safe-error-response.js +6 -6
  14. package/dist/lib/two-factor-verify-failure.d.ts +36 -3
  15. package/dist/lib/two-factor-verify-failure.js +79 -2
  16. package/dist/middleware/create-middleware.d.ts +2 -0
  17. package/dist/middleware/create-middleware.js +36 -0
  18. package/dist/pages/login/page.js +5 -0
  19. package/dist/pages/verify-code/page.js +4 -2
  20. package/dist/routes/auth/settings.js +4 -1
  21. package/dist/server/auth.d.ts +36 -294
  22. package/dist/server/auth.js +22 -25
  23. package/dist/vibe/client.d.ts +132 -16
  24. package/dist/vibe/client.js +288 -82
  25. package/dist/vibe/document-unwrap.d.ts +50 -0
  26. package/dist/vibe/document-unwrap.js +78 -0
  27. package/dist/vibe/errors.d.ts +17 -0
  28. package/dist/vibe/errors.js +21 -1
  29. package/dist/vibe/generic.d.ts +2 -49
  30. package/dist/vibe/generic.js +17 -78
  31. package/dist/vibe/index.d.ts +1 -1
  32. package/dist/vibe/index.js +2 -1
  33. package/package.json +12 -2
  34. package/src/api-handlers/account/change-password.ts +31 -6
  35. package/src/auth/better-auth.ts +93 -8
  36. package/src/config/env.ts +0 -2
  37. package/src/index.ts +4 -0
  38. package/src/lib/idp-client-config.ts +8 -1
  39. package/src/lib/never-in-response.ts +64 -0
  40. package/src/lib/safe-error-response.ts +6 -6
  41. package/src/lib/two-factor-verify-failure.ts +86 -5
  42. package/src/middleware/create-middleware.ts +42 -0
  43. package/src/pages/login/page.tsx +4 -0
  44. package/src/pages/verify-code/page.tsx +4 -2
  45. package/src/routes/auth/settings.ts +5 -1
  46. package/src/server/auth.ts +23 -29
  47. package/src/vibe/client.ts +378 -91
  48. package/src/vibe/document-unwrap.ts +103 -0
  49. package/src/vibe/errors.ts +24 -0
  50. package/src/vibe/generic.ts +8 -100
  51. package/src/vibe/index.ts +1 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Vibe document wrapper + unwrapping.
3
+ *
4
+ * PAY-1767: extracted from generic.ts into its own module so the typed client (client.ts) can unwrap
5
+ * reads WITHOUT importing generic.ts - generic.ts imports client.ts, so a shared helper there would be
6
+ * a cycle. This module imports nothing from the vibe client.
7
+ *
8
+ * Vibe stores a row's own fields as a JSON STRING under the wrapper's `data` field, alongside storage
9
+ * columns (document_id, owner, timestamps). A caller that renders `response.data` directly sees the
10
+ * wrapper, so `row.name` is undefined. unwrapVibeDocument flattens the row out and keeps the storage
11
+ * document_id as `_vibe_doc_id` for update/delete paths.
12
+ */
13
+
14
+ /** Vibe document wrapper structure. Vibe stores actual table data as a JSON string in the 'data' field. */
15
+ export interface VibeDocumentWrapper {
16
+ document_id: number;
17
+ client_id?: number;
18
+ user_id?: number;
19
+ collection?: string;
20
+ table_name?: string;
21
+ data: string | Record<string, unknown>;
22
+ collection_schema_id?: number;
23
+ created_at?: string;
24
+ created_by?: number;
25
+ updated_at?: string | null;
26
+ updated_by?: number | null;
27
+ deleted_at?: string | null;
28
+ }
29
+
30
+ /**
31
+ * Unwrap a Vibe document response.
32
+ *
33
+ * @param doc - Raw Vibe document (wrapper format)
34
+ * @returns Unwrapped document with schema fields only; storage document_id preserved as `_vibe_doc_id`
35
+ * for update/delete paths. See PayEz-Core/docs/vibe-primary-key-standard.md
36
+ *
37
+ * @example
38
+ * const raw = { document_id: 123, data: '{"user_id":15,"name":"John"}' };
39
+ * unwrapVibeDocument(raw); // => { user_id: 15, name: 'John', _vibe_doc_id: 123 }
40
+ */
41
+ export function unwrapVibeDocument<T extends object = Record<string, unknown>>(
42
+ doc: VibeDocumentWrapper | Record<string, unknown> | null | undefined
43
+ ): (T & { _vibe_doc_id?: number }) | null {
44
+ if (!doc) return null;
45
+
46
+ // Handle case where doc is already unwrapped (has schema fields directly)
47
+ if (!('document_id' in doc) && !('data' in doc)) {
48
+ return doc as T & { _vibe_doc_id?: number };
49
+ }
50
+
51
+ const wrapper = doc as VibeDocumentWrapper;
52
+ let parsedData: Record<string, unknown> = {};
53
+
54
+ if (typeof wrapper.data === 'string') {
55
+ try {
56
+ parsedData = JSON.parse(wrapper.data);
57
+ } catch {
58
+ console.warn('[vibe-document] Failed to parse document data JSON:', wrapper.data);
59
+ parsedData = {};
60
+ }
61
+ } else if (typeof wrapper.data === 'object' && wrapper.data !== null) {
62
+ parsedData = wrapper.data;
63
+ }
64
+
65
+ // Preserve document_id as _vibe_doc_id for Vibe API update/delete paths only
66
+ const documentId = wrapper.document_id ?? (doc as { document_id?: number }).document_id;
67
+ if (documentId != null) {
68
+ parsedData._vibe_doc_id = documentId;
69
+ }
70
+
71
+ return parsedData as T & { _vibe_doc_id?: number };
72
+ }
73
+
74
+ /**
75
+ * Extract and unwrap an array of documents from a Vibe response.
76
+ *
77
+ * @param responseData - Raw Vibe API response ({ data: [...] }, { items: [...] }, { documents: [...] } or a bare array)
78
+ * @returns Array of unwrapped documents
79
+ */
80
+ export function extractVibeDocuments<T extends Record<string, unknown> = Record<string, unknown>>(
81
+ responseData: unknown
82
+ ): Array<T & { _vibe_doc_id?: number }> {
83
+ if (!responseData || typeof responseData !== 'object') {
84
+ return [];
85
+ }
86
+
87
+ const data = responseData as Record<string, unknown>;
88
+
89
+ // Try common response shapes
90
+ const docs =
91
+ data.data ??
92
+ data.items ??
93
+ data.documents ??
94
+ (Array.isArray(responseData) ? responseData : null);
95
+
96
+ if (!Array.isArray(docs)) {
97
+ return [];
98
+ }
99
+
100
+ return docs
101
+ .map((doc) => unwrapVibeDocument<T>(doc))
102
+ .filter((d): d is T & { _vibe_doc_id?: number } => d !== null);
103
+ }
@@ -183,3 +183,27 @@ export class VibeServiceError extends VibeError {
183
183
  this.name = 'VibeServiceError';
184
184
  }
185
185
  }
186
+
187
+ /**
188
+ * PAY-1767 (NightHawk 64534): thrown when a NON-ATOMIC `createMany` fails part-way. It CARRIES what was
189
+ * already created, so the caller can reconcile instead of guessing whether k-1 rows persisted. This is the
190
+ * point of the class: a partial write whose extent is invisible is the hazard, not the partial write itself.
191
+ */
192
+ export class VibeBatchCreateError extends VibeError {
193
+ /** How many records were created before the failure. */
194
+ public readonly createdCount: number;
195
+ /** The document ids that were created before the failure. */
196
+ public readonly createdIds: Array<number | string>;
197
+
198
+ constructor(
199
+ message: string,
200
+ details: { createdCount: number; createdIds: Array<number | string>; failedIndex: number; total: number },
201
+ cause?: unknown,
202
+ ) {
203
+ super(message, 'BATCH_PARTIAL_FAILURE', 500, details);
204
+ this.name = 'VibeBatchCreateError';
205
+ this.createdCount = details.createdCount;
206
+ this.createdIds = details.createdIds;
207
+ if (cause !== undefined) (this as { cause?: unknown }).cause = cause;
208
+ }
209
+ }
@@ -72,109 +72,17 @@ export function vibeGridPath(collection: string, table: string): string {
72
72
 
73
73
  // -----------------------------------------------------------------------------
74
74
  // DOCUMENT UNWRAPPING
75
+ //
76
+ // PAY-1767: the wrapper type and the two helpers MOVED to ./document-unwrap, so the typed client
77
+ // (client.ts) can unwrap reads without importing this module (which imports client.ts). Re-exported
78
+ // here so every existing `from './generic'` / package import keeps working unchanged.
75
79
  // -----------------------------------------------------------------------------
76
80
 
77
- /**
78
- * Vibe document wrapper structure.
79
- * Vibe stores actual table data as JSON string in the 'data' field.
80
- */
81
- export interface VibeDocumentWrapper {
82
- document_id: number;
83
- client_id?: number;
84
- user_id?: number;
85
- collection?: string;
86
- table_name?: string;
87
- data: string | Record<string, unknown>;
88
- collection_schema_id?: number;
89
- created_at?: string;
90
- created_by?: number;
91
- updated_at?: string | null;
92
- updated_by?: number | null;
93
- deleted_at?: string | null;
94
- }
95
-
96
- /**
97
- * Unwrap a Vibe document response.
98
- * Vibe returns documents with a wrapper where actual data is a JSON string.
99
- *
100
- * @param doc - Raw Vibe document (wrapper format)
101
- * @returns Unwrapped document with schema fields only.
102
- * Storage-layer document_id preserved as _vibe_doc_id for update/delete paths.
103
- * See PayEz-Core/docs/vibe-primary-key-standard.md
104
- *
105
- * @example
106
- * const raw = { document_id: 123, data: '{"user_id":15,"name":"John","email":"john@example.com"}' };
107
- * const unwrapped = unwrapVibeDocument(raw);
108
- * // => { user_id: 15, name: 'John', email: 'john@example.com', _vibe_doc_id: 123 }
109
- */
110
- export function unwrapVibeDocument<T extends Record<string, unknown> = Record<string, unknown>>(
111
- doc: VibeDocumentWrapper | Record<string, unknown> | null | undefined
112
- ): (T & { _vibe_doc_id?: number }) | null {
113
- if (!doc) return null;
114
-
115
- // Handle case where doc is already unwrapped (has schema fields directly)
116
- if (!('document_id' in doc) && !('data' in doc)) {
117
- return doc as T & { _vibe_doc_id?: number };
118
- }
119
-
120
- const wrapper = doc as VibeDocumentWrapper;
121
- let parsedData: Record<string, unknown> = {};
122
-
123
- if (typeof wrapper.data === 'string') {
124
- try {
125
- parsedData = JSON.parse(wrapper.data);
126
- } catch {
127
- console.warn('[vibe-generic] Failed to parse document data JSON:', wrapper.data);
128
- parsedData = {};
129
- }
130
- } else if (typeof wrapper.data === 'object' && wrapper.data !== null) {
131
- parsedData = wrapper.data;
132
- }
81
+ export { unwrapVibeDocument, extractVibeDocuments } from './document-unwrap';
82
+ export type { VibeDocumentWrapper } from './document-unwrap';
133
83
 
134
- // Preserve document_id as _vibe_doc_id for Vibe API update/delete paths only
135
- const documentId = wrapper.document_id ?? (doc as any).document_id;
136
- if (documentId != null) {
137
- parsedData._vibe_doc_id = documentId;
138
- }
139
-
140
- return parsedData as T & { _vibe_doc_id?: number };
141
- }
142
-
143
- /**
144
- * Extract and unwrap array of documents from Vibe response.
145
- *
146
- * @param responseData - Raw Vibe API response
147
- * @returns Array of unwrapped documents
148
- *
149
- * @example
150
- * const response = await fetch('/api/vibe/data/ideal_resume/resumes');
151
- * const data = await response.json();
152
- * const resumes = extractVibeDocuments(data);
153
- */
154
- export function extractVibeDocuments<T extends Record<string, unknown> = Record<string, unknown>>(
155
- responseData: unknown
156
- ): Array<T & { _vibe_doc_id?: number }> {
157
- if (!responseData || typeof responseData !== 'object') {
158
- return [];
159
- }
160
-
161
- const data = responseData as Record<string, unknown>;
162
-
163
- // Try common response shapes
164
- const docs =
165
- data.data ??
166
- data.items ??
167
- data.documents ??
168
- (Array.isArray(responseData) ? responseData : null);
169
-
170
- if (!Array.isArray(docs)) {
171
- return [];
172
- }
173
-
174
- return docs
175
- .map((doc) => unwrapVibeDocument<T>(doc))
176
- .filter((d): d is T & { _vibe_doc_id?: number } => d !== null);
177
- }
84
+ import { unwrapVibeDocument, extractVibeDocuments } from './document-unwrap';
85
+ import type { VibeDocumentWrapper } from './document-unwrap';
178
86
 
179
87
  // -----------------------------------------------------------------------------
180
88
  // GENERIC TABLE DELEGATE
package/src/vibe/index.ts CHANGED
@@ -89,6 +89,7 @@ export {
89
89
  VibeRateLimitError,
90
90
  VibeConflictError,
91
91
  VibeServiceError,
92
+ VibeBatchCreateError,
92
93
  } from './errors';
93
94
 
94
95
  // Session management exports