@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.
- package/dist/api-handlers/account/change-password.js +28 -6
- package/dist/auth/better-auth.d.ts +44 -14
- package/dist/auth/better-auth.js +92 -7
- package/dist/client/better-auth-client.d.ts +101 -956
- package/dist/config/env.d.ts +0 -2
- package/dist/config/env.js +0 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -1
- package/dist/lib/idp-client-config.js +8 -1
- package/dist/lib/never-in-response.d.ts +30 -0
- package/dist/lib/never-in-response.js +71 -0
- package/dist/lib/safe-error-response.d.ts +6 -6
- package/dist/lib/safe-error-response.js +6 -6
- package/dist/lib/two-factor-verify-failure.d.ts +36 -3
- package/dist/lib/two-factor-verify-failure.js +79 -2
- package/dist/middleware/create-middleware.d.ts +2 -0
- package/dist/middleware/create-middleware.js +36 -0
- package/dist/pages/login/page.js +5 -0
- package/dist/pages/verify-code/page.js +4 -2
- package/dist/routes/auth/settings.js +4 -1
- package/dist/server/auth.d.ts +36 -294
- package/dist/server/auth.js +22 -25
- package/dist/vibe/client.d.ts +132 -16
- package/dist/vibe/client.js +288 -82
- package/dist/vibe/document-unwrap.d.ts +50 -0
- package/dist/vibe/document-unwrap.js +78 -0
- package/dist/vibe/errors.d.ts +17 -0
- package/dist/vibe/errors.js +21 -1
- package/dist/vibe/generic.d.ts +2 -49
- package/dist/vibe/generic.js +17 -78
- package/dist/vibe/index.d.ts +1 -1
- package/dist/vibe/index.js +2 -1
- package/package.json +12 -2
- package/src/api-handlers/account/change-password.ts +31 -6
- package/src/auth/better-auth.ts +93 -8
- package/src/config/env.ts +0 -2
- package/src/index.ts +4 -0
- package/src/lib/idp-client-config.ts +8 -1
- package/src/lib/never-in-response.ts +64 -0
- package/src/lib/safe-error-response.ts +6 -6
- package/src/lib/two-factor-verify-failure.ts +86 -5
- package/src/middleware/create-middleware.ts +42 -0
- package/src/pages/login/page.tsx +4 -0
- package/src/pages/verify-code/page.tsx +4 -2
- package/src/routes/auth/settings.ts +5 -1
- package/src/server/auth.ts +23 -29
- package/src/vibe/client.ts +378 -91
- package/src/vibe/document-unwrap.ts +103 -0
- package/src/vibe/errors.ts +24 -0
- package/src/vibe/generic.ts +8 -100
- 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
|
+
}
|
package/src/vibe/errors.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/vibe/generic.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
135
|
-
|
|
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
|