@harperfast/harper-pro 5.0.0-alpha.9 → 5.0.0-beta.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.
- package/core/.dockerignore +9 -0
- package/core/.git-blame-ignore-revs +2 -0
- package/core/.github/workflows/create-release.yaml +4 -4
- package/core/.github/workflows/integration-tests.yml +12 -10
- package/core/.github/workflows/notify-release-published.yaml +1 -1
- package/core/.github/workflows/publish-docker.yaml +2 -2
- package/core/.github/workflows/publish-npm.yaml +4 -4
- package/core/CONTRIBUTING.md +1 -1
- package/core/Dockerfile +62 -0
- package/core/build-tools/build-studio.sh +12 -0
- package/core/build-tools/build.sh +22 -0
- package/core/build-tools/download-prebuilds.js +13 -0
- package/core/components/Logger.ts +14 -0
- package/core/components/Scope.ts +35 -11
- package/core/components/componentLoader.ts +27 -10
- package/core/components/operations.js +10 -2
- package/core/config/configUtils.js +1 -1
- package/core/dataLayer/CreateTableObject.js +2 -2
- package/core/dataLayer/schema.js +7 -5
- package/core/dataLayer/schemaDescribe.js +1 -1
- package/core/index.d.ts +11 -6
- package/core/index.js +2 -0
- package/core/integrationTests/README.md +24 -0
- package/core/integrationTests/apiTests/tests/10_otherRoleTests.mjs +6 -6
- package/core/integrationTests/apiTests/tests/12_configuration.mjs +1 -1
- package/core/integrationTests/apiTests/tests/14_tokenAuth.mjs +2 -2
- package/core/integrationTests/apiTests/tests/16_terminologyUpdates.mjs +4 -4
- package/core/integrationTests/apiTests/tests/1_environmentSetup.mjs +1 -1
- package/core/integrationTests/apiTests/tests/2_dataLoad.mjs +4 -4
- package/core/integrationTests/apiTests/tests/3_sqlTests.mjs +3 -3
- package/core/integrationTests/apiTests/tests/4_noSqlTests.mjs +12 -12
- package/core/integrationTests/apiTests/tests/5_noSqlRoleTesting.mjs +8 -8
- package/core/integrationTests/apiTests/tests/7_jobsAndJobRoleTesting.mjs +10 -12
- package/core/integrationTests/apiTests/tests/8_deleteTests.mjs +8 -8
- package/core/integrationTests/apiTests/tests/9_transactions.mjs +2 -2
- package/core/integrationTests/apiTests/utils/search.mjs +1 -1
- package/core/integrationTests/apiTests/utils/table.mjs +1 -1
- package/core/integrationTests/server/operation-user-rbac.test.ts +1 -1
- package/core/integrationTests/server/operations-server.test.ts +1 -1
- package/core/integrationTests/server/storage-reclamation.test.ts +1 -1
- package/core/integrationTests/utils/README.md +1 -15
- package/core/integrationTests/utils/harperLifecycle.ts +33 -21
- package/core/package.json +23 -5
- package/core/resources/ResourceInterface.ts +1 -1
- package/core/resources/Table.ts +26 -11
- package/core/resources/analytics/read.ts +33 -26
- package/core/resources/analytics/write.ts +3 -7
- package/core/resources/databases.ts +29 -18
- package/core/resources/search.ts +10 -5
- package/core/security/auth.ts +1 -1
- package/core/security/jsLoader.ts +302 -83
- package/core/security/keys.js +11 -12
- package/core/security/user.ts +3 -3
- package/core/server/REST.ts +18 -2
- package/core/server/Server.ts +2 -1
- package/core/server/fastifyRoutes.ts +1 -0
- package/core/server/http.ts +13 -9
- package/core/server/loadRootComponents.js +1 -0
- package/core/server/operationsServer.ts +2 -1
- package/core/server/threads/manageThreads.js +49 -35
- package/core/static/defaultConfig.yaml +3 -0
- package/core/unitTests/apiTests/RESTProperties-test.mjs +2 -2
- package/core/unitTests/apiTests/basicREST-test.mjs +2 -2
- package/core/unitTests/components/Scope.test.js +54 -16
- package/core/unitTests/components/fixtures/testJSWithDeps/child-dir/circular.js +4 -0
- package/core/unitTests/components/fixtures/testJSWithDeps/child-dir/in-child-dir.js +4 -0
- package/core/unitTests/components/fixtures/testJSWithDeps/child-dir/typestrip.ts +2 -0
- package/core/unitTests/components/fixtures/testJSWithDeps/resources.js +43 -0
- package/core/unitTests/components/fixtures/testJSWithDeps/test-child-process.js +18 -0
- package/core/unitTests/components/globalIsolation.test.js +87 -1
- package/core/unitTests/config/configUtils.test.js +1 -260
- package/core/unitTests/resources/query.test.js +16 -1
- package/core/unitTests/resources/vectorIndex.test.js +1 -1
- package/core/unitTests/server/fastifyRoutes/operations.test.js +1 -1
- package/core/unitTests/testUtils.js +0 -17
- package/core/utility/hdbTerms.ts +3 -0
- package/core/utility/installation.ts +2 -5
- package/core/utility/lmdb/commonUtility.js +21 -10
- package/dist/core/{resources/ResourceInterfaceV2.js → components/Logger.js} +1 -1
- package/dist/core/components/Logger.js.map +1 -0
- package/dist/core/components/Scope.js +18 -10
- package/dist/core/components/Scope.js.map +1 -1
- package/dist/core/components/componentLoader.js +17 -10
- package/dist/core/components/componentLoader.js.map +1 -1
- package/dist/core/components/operations.js +2 -2
- package/dist/core/components/operations.js.map +1 -1
- package/dist/core/config/configUtils.js +1 -1
- package/dist/core/config/configUtils.js.map +1 -1
- package/dist/core/dataLayer/CreateTableObject.js +2 -2
- package/dist/core/dataLayer/CreateTableObject.js.map +1 -1
- package/dist/core/dataLayer/schema.js +6 -5
- package/dist/core/dataLayer/schema.js.map +1 -1
- package/dist/core/dataLayer/schemaDescribe.js +1 -1
- package/dist/core/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/resources/Table.js +12 -4
- package/dist/core/resources/Table.js.map +1 -1
- package/dist/core/resources/analytics/read.js +32 -22
- package/dist/core/resources/analytics/read.js.map +1 -1
- package/dist/core/resources/analytics/write.js +3 -6
- package/dist/core/resources/analytics/write.js.map +1 -1
- package/dist/core/resources/databases.js +22 -19
- package/dist/core/resources/databases.js.map +1 -1
- package/dist/core/resources/search.js +11 -5
- package/dist/core/resources/search.js.map +1 -1
- package/dist/core/security/auth.js +1 -1
- package/dist/core/security/auth.js.map +1 -1
- package/dist/core/security/jsLoader.js +265 -73
- package/dist/core/security/jsLoader.js.map +1 -1
- package/dist/core/security/keys.js +11 -12
- package/dist/core/security/keys.js.map +1 -1
- package/dist/core/security/user.js +3 -3
- package/dist/core/security/user.js.map +1 -1
- package/dist/core/server/REST.js +16 -2
- package/dist/core/server/REST.js.map +1 -1
- package/dist/core/server/Server.js.map +1 -1
- package/dist/core/server/fastifyRoutes.js +2 -0
- package/dist/core/server/fastifyRoutes.js.map +1 -1
- package/dist/core/server/http.js +12 -6
- package/dist/core/server/http.js.map +1 -1
- package/dist/core/server/loadRootComponents.js +1 -0
- package/dist/core/server/loadRootComponents.js.map +1 -1
- package/dist/core/server/operationsServer.js +3 -1
- package/dist/core/server/operationsServer.js.map +1 -1
- package/dist/core/server/threads/manageThreads.js +50 -35
- package/dist/core/server/threads/manageThreads.js.map +1 -1
- package/dist/core/utility/hdbTerms.js +3 -0
- package/dist/core/utility/hdbTerms.js.map +1 -1
- package/dist/core/utility/installation.js.map +1 -1
- package/dist/core/utility/lmdb/commonUtility.js +20 -13
- package/dist/core/utility/lmdb/commonUtility.js.map +1 -1
- package/dist/licensing/usageLicensing.js.map +1 -1
- package/dist/replication/knownNodes.js +5 -37
- package/dist/replication/knownNodes.js.map +1 -1
- package/dist/replication/nodeIdMapping.js +2 -35
- package/dist/replication/nodeIdMapping.js.map +1 -1
- package/dist/replication/replicationConnection.js +15 -6
- package/dist/replication/replicationConnection.js.map +1 -1
- package/dist/replication/replicator.js +3 -2
- package/dist/replication/replicator.js.map +1 -1
- package/dist/replication/setNode.js +1 -1
- package/dist/replication/setNode.js.map +1 -1
- package/dist/security/certificate.js.map +1 -1
- package/licensing/usageLicensing.ts +3 -2
- package/npm-shrinkwrap.json +303 -282
- package/package.json +4 -3
- package/replication/knownNodes.ts +3 -2
- package/replication/nodeIdMapping.ts +1 -1
- package/replication/replicationConnection.ts +33 -8
- package/replication/replicator.ts +7 -2
- package/replication/setNode.ts +1 -1
- package/security/certificate.ts +2 -1
- package/studio/web/assets/{index-v3wIpSYx.js → index-CWN9Wp5V.js} +2 -2
- package/studio/web/assets/{index-v3wIpSYx.js.map → index-CWN9Wp5V.js.map} +1 -1
- package/studio/web/assets/{index-ChCctErQ.js → index-CzghSAn2.js} +2 -2
- package/studio/web/assets/{index-ChCctErQ.js.map → index-CzghSAn2.js.map} +1 -1
- package/studio/web/assets/{index-Qu8D43wo.js → index-DMDhGP7N.js} +5 -5
- package/studio/web/assets/{index-Qu8D43wo.js.map → index-DMDhGP7N.js.map} +1 -1
- package/studio/web/assets/{index.lazy-tVSPM7bX.js → index.lazy-C-yDTGUy.js} +2 -2
- package/studio/web/assets/{index.lazy-tVSPM7bX.js.map → index.lazy-C-yDTGUy.js.map} +1 -1
- package/studio/web/assets/{profiler-C9as4sv-.js → profiler-0fZAOscv.js} +2 -2
- package/studio/web/assets/{profiler-C9as4sv-.js.map → profiler-0fZAOscv.js.map} +1 -1
- package/studio/web/assets/{react-redux-RRIhZnM6.js → react-redux-BIxqK8O6.js} +2 -2
- package/studio/web/assets/{react-redux-RRIhZnM6.js.map → react-redux-BIxqK8O6.js.map} +1 -1
- package/studio/web/assets/{startRecording-DYa4zCXV.js → startRecording-Ca3Gf2MY.js} +2 -2
- package/studio/web/assets/{startRecording-DYa4zCXV.js.map → startRecording-Ca3Gf2MY.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/core/resources/ResourceInterfaceV2.ts +0 -53
- package/core/resources/ResourceV2.ts +0 -67
- package/core/resources/analytics/profile.ts +0 -109
- package/core/unitTests/apiTests/analytics-test.mjs +0 -38
- package/core/v1.d.ts +0 -47
- package/core/v1.js +0 -38
- package/core/v2.d.ts +0 -47
- package/core/v2.js +0 -38
- package/dist/core/resources/ResourceInterfaceV2.js.map +0 -1
- package/dist/core/resources/ResourceV2.js +0 -27
- package/dist/core/resources/ResourceV2.js.map +0 -1
- package/dist/core/resources/analytics/profile.js +0 -144
- package/dist/core/resources/analytics/profile.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harperfast/harper-pro",
|
|
3
|
-
"version": "5.0.0-
|
|
3
|
+
"version": "5.0.0-beta.2",
|
|
4
4
|
"description": "Harper is a distributed database, caching service, streaming broker, and application development platform focused on performance and ease of use.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"@fastify/cors": "~9.0.1",
|
|
81
81
|
"@fastify/static": "~7.0.4",
|
|
82
82
|
"@harperfast/extended-iterable": "^1.0.1",
|
|
83
|
-
"@harperfast/rocksdb-js": "^0.1.
|
|
83
|
+
"@harperfast/rocksdb-js": "^0.1.12",
|
|
84
84
|
"@turf/area": "6.5.0",
|
|
85
85
|
"@turf/boolean-contains": "6.5.0",
|
|
86
86
|
"@turf/boolean-disjoint": "6.5.0",
|
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
"@turf/helpers": "6.5.0",
|
|
92
92
|
"@turf/length": "6.5.0",
|
|
93
93
|
"alasql": "4.6.6",
|
|
94
|
+
"amaro": "^1.1.8",
|
|
94
95
|
"argon2": "0.44.0",
|
|
95
96
|
"asn1js": "3.0.7",
|
|
96
97
|
"cbor-x": "1.6.4",
|
|
@@ -115,7 +116,7 @@
|
|
|
115
116
|
"json2csv": "5.0.7",
|
|
116
117
|
"jsonata": "1.8.7",
|
|
117
118
|
"jsonwebtoken": "9.0.3",
|
|
118
|
-
"lmdb": "3.5.
|
|
119
|
+
"lmdb": "3.5.2",
|
|
119
120
|
"lodash": "4.17.21",
|
|
120
121
|
"mathjs": "11.12.0",
|
|
121
122
|
"micromatch": "^4.0.8",
|
|
@@ -10,7 +10,7 @@ import { isMainThread } from 'worker_threads';
|
|
|
10
10
|
import { ClientError } from '../core/utility/errors/hdbError.js';
|
|
11
11
|
import env from '../core/utility/environment/environmentManager.js';
|
|
12
12
|
import { CONFIG_PARAMS } from '../core/utility/hdbTerms.ts';
|
|
13
|
-
import
|
|
13
|
+
import { logger } from '../core/utility/logging/logger.ts';
|
|
14
14
|
|
|
15
15
|
let hdbNodeTable;
|
|
16
16
|
server.nodes = [];
|
|
@@ -110,7 +110,7 @@ export function subscribeToNodeUpdates(listener: (node: any, id: string) => void
|
|
|
110
110
|
server.shards = new Map();
|
|
111
111
|
|
|
112
112
|
for (let entry of getHDBNodeTable().primaryStore.getRange({})) {
|
|
113
|
-
const { value: node } = entry;
|
|
113
|
+
const { value: node, key } = entry;
|
|
114
114
|
server.nodes.push(node);
|
|
115
115
|
if (node.shard != undefined) {
|
|
116
116
|
let nodesForShard = server.shards.get(node.shard);
|
|
@@ -119,6 +119,7 @@ export function subscribeToNodeUpdates(listener: (node: any, id: string) => void
|
|
|
119
119
|
}
|
|
120
120
|
nodesForShard.push(node);
|
|
121
121
|
}
|
|
122
|
+
listener(node, key);
|
|
122
123
|
}
|
|
123
124
|
logger.debug?.(
|
|
124
125
|
'Known nodes at startup',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This module is responsible for managing the mapping of node/host names to node ids.
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
4
|
+
import { logger } from '../core/utility/logging/logger.ts';
|
|
5
5
|
import { lastTimeInAuditStore } from './replicator.ts';
|
|
6
6
|
import { getThisNodeName } from '../core/server/nodeName.ts';
|
|
7
7
|
import { pack, unpack } from 'msgpackr';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Logger } from '../core/utility/logging/logger.ts';
|
|
1
2
|
import {
|
|
2
3
|
getDatabases,
|
|
3
4
|
databases,
|
|
@@ -51,7 +52,7 @@ import {
|
|
|
51
52
|
} from '../core/resources/blob.ts';
|
|
52
53
|
import { PassThrough } from 'node:stream';
|
|
53
54
|
import { getLastVersion } from 'lmdb';
|
|
54
|
-
const logger = forComponent('replication').conditional;
|
|
55
|
+
const logger = forComponent('replication').conditional as Logger;
|
|
55
56
|
|
|
56
57
|
// these are the codes we use for the different commands
|
|
57
58
|
const SUBSCRIPTION_REQUEST = 129;
|
|
@@ -121,10 +122,9 @@ export async function createWebSocket(
|
|
|
121
122
|
if (url == null) {
|
|
122
123
|
throw new TypeError(`Invalid URL: Expected a string URL for node "${node_name}" but received ${url}`);
|
|
123
124
|
}
|
|
124
|
-
|
|
125
125
|
if (url.includes('wss://')) {
|
|
126
126
|
if (!secureContexts) {
|
|
127
|
-
const SNICallback = createTLSSelector('
|
|
127
|
+
const SNICallback = createTLSSelector('replication');
|
|
128
128
|
const secureTarget = {
|
|
129
129
|
secureContexts: null,
|
|
130
130
|
};
|
|
@@ -133,10 +133,22 @@ export async function createWebSocket(
|
|
|
133
133
|
}
|
|
134
134
|
secureContext = secureContexts.get(node_name);
|
|
135
135
|
if (secureContext) {
|
|
136
|
-
logger.debug?.(
|
|
136
|
+
logger.debug?.(
|
|
137
|
+
'Creating web socket for URL',
|
|
138
|
+
url,
|
|
139
|
+
'with certificate named:',
|
|
140
|
+
secureContext.name,
|
|
141
|
+
'is_self_signed',
|
|
142
|
+
secureContext.is_self_signed
|
|
143
|
+
);
|
|
137
144
|
}
|
|
138
145
|
if (!secureContext && rejectUnauthorized !== false) {
|
|
139
|
-
throw new Error(
|
|
146
|
+
throw new Error(
|
|
147
|
+
'Unable to find a valid certificate to use for replication to connect to ' +
|
|
148
|
+
url +
|
|
149
|
+
' available:' +
|
|
150
|
+
Array.from(secureContexts.keys())
|
|
151
|
+
);
|
|
140
152
|
}
|
|
141
153
|
}
|
|
142
154
|
const headers = {};
|
|
@@ -698,7 +710,12 @@ export function replicateOverWS(ws: WebSocket, options: any, authorization: Prom
|
|
|
698
710
|
remoteNodeIds: receivingDataFromNodeIds,
|
|
699
711
|
});
|
|
700
712
|
getSharedStatus();
|
|
701
|
-
replicationSharedStatus[RECEIVED_VERSION_POSITION] =
|
|
713
|
+
replicationSharedStatus[RECEIVED_VERSION_POSITION] = Math.max(
|
|
714
|
+
// ensure monotonicity
|
|
715
|
+
lastSequenceIdReceived,
|
|
716
|
+
replicationSharedStatus[RECEIVED_VERSION_POSITION]
|
|
717
|
+
);
|
|
718
|
+
|
|
702
719
|
replicationSharedStatus[RECEIVED_TIME_POSITION] = Date.now();
|
|
703
720
|
replicationSharedStatus[RECEIVING_STATUS_POSITION] = RECEIVING_STATUS_WAITING;
|
|
704
721
|
break;
|
|
@@ -1487,7 +1504,11 @@ export function replicateOverWS(ws: WebSocket, options: any, authorization: Prom
|
|
|
1487
1504
|
// this is an empty txn ending, but need to record the timestamps
|
|
1488
1505
|
decoder.position++;
|
|
1489
1506
|
lastSequenceIdReceived = sequenceIdReceived = decoder.readFloat64();
|
|
1490
|
-
replicationSharedStatus[RECEIVED_VERSION_POSITION] =
|
|
1507
|
+
replicationSharedStatus[RECEIVED_VERSION_POSITION] = Math.max(
|
|
1508
|
+
// ensure monotonicity
|
|
1509
|
+
lastSequenceIdReceived,
|
|
1510
|
+
replicationSharedStatus[RECEIVED_VERSION_POSITION]
|
|
1511
|
+
);
|
|
1491
1512
|
replicationSharedStatus[RECEIVED_TIME_POSITION] = Date.now();
|
|
1492
1513
|
replicationSharedStatus[RECEIVING_STATUS_POSITION] = RECEIVING_STATUS_WAITING;
|
|
1493
1514
|
tableSubscriptionToReplicator.send({
|
|
@@ -1555,7 +1576,11 @@ export function replicateOverWS(ws: WebSocket, options: any, authorization: Prom
|
|
|
1555
1576
|
'nodeId',
|
|
1556
1577
|
event.nodeId
|
|
1557
1578
|
);
|
|
1558
|
-
replicationSharedStatus[RECEIVED_VERSION_POSITION] =
|
|
1579
|
+
replicationSharedStatus[RECEIVED_VERSION_POSITION] = Math.max(
|
|
1580
|
+
// ensure monotonicity
|
|
1581
|
+
auditRecord.version,
|
|
1582
|
+
replicationSharedStatus[RECEIVED_VERSION_POSITION]
|
|
1583
|
+
);
|
|
1559
1584
|
replicationSharedStatus[RECEIVED_TIME_POSITION] = Date.now();
|
|
1560
1585
|
replicationSharedStatus[RECEIVING_STATUS_POSITION] = RECEIVING_STATUS_RECEIVING;
|
|
1561
1586
|
|
|
@@ -150,7 +150,11 @@ export function start(options) {
|
|
|
150
150
|
} else {
|
|
151
151
|
logger.error(
|
|
152
152
|
`Incoming client connection from ${request.peerCertificate?.subjectaltname ?? request.ip} did not have valid certificate, you may need turn on enableRootCAs in the config if you are using a publicly signed certificate, or add the CA to the server's trusted CAs`,
|
|
153
|
-
authorizationError
|
|
153
|
+
authorizationError,
|
|
154
|
+
'certificate issuer',
|
|
155
|
+
request.peerCertificate.issuer,
|
|
156
|
+
'did not match any available CAs',
|
|
157
|
+
Array.from(Array.from(wsServers[0].secureContexts.values())[0].options.availableCAs.keys())
|
|
154
158
|
);
|
|
155
159
|
}
|
|
156
160
|
}
|
|
@@ -265,6 +269,7 @@ export function start(options) {
|
|
|
265
269
|
export function monitorNodeCAs(listener: () => void) {
|
|
266
270
|
let lastCaCount = 0;
|
|
267
271
|
subscribeToNodeUpdates((node) => {
|
|
272
|
+
logger.debug('Adding node CA', node?.ca?.slice(0, 60));
|
|
268
273
|
if (node?.ca) {
|
|
269
274
|
// we only care about nodes that have a CA
|
|
270
275
|
replicationCertificateAuthorities.add(node.ca);
|
|
@@ -639,7 +644,7 @@ export function lastTimeInAuditStore(auditStore: Database) {
|
|
|
639
644
|
|
|
640
645
|
export async function replicateOperation(req) {
|
|
641
646
|
const response = { message: '' };
|
|
642
|
-
if (req.replicated) {
|
|
647
|
+
if (req.replicated !== false) {
|
|
643
648
|
req.replicated = false; // don't send a replicated flag to the nodes we are sending to
|
|
644
649
|
logger.trace?.(
|
|
645
650
|
'Replicating operation',
|
package/replication/setNode.ts
CHANGED
|
@@ -153,7 +153,7 @@ export async function setNode(req: any) {
|
|
|
153
153
|
if (targetNodeResponse.certificate) {
|
|
154
154
|
await setCertTable({
|
|
155
155
|
name: getThisNodeName(),
|
|
156
|
-
uses: ['https', 'operations', 'wss'],
|
|
156
|
+
uses: ['https', 'operations', 'wss', 'replication'],
|
|
157
157
|
certificate: targetNodeResponse.certificate,
|
|
158
158
|
private_key_name: rep?.options?.key_file,
|
|
159
159
|
is_authority: false,
|
package/security/certificate.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Logger } from '../core/utility/logging/logger.ts';
|
|
1
2
|
import Joi from 'joi';
|
|
2
3
|
import forge from 'node-forge';
|
|
3
4
|
import { access, constants, readFile, writeFile, unlink } from 'node:fs/promises';
|
|
@@ -25,7 +26,7 @@ import { server } from '../core/server/Server.ts';
|
|
|
25
26
|
import { replicateOperation } from '../replication/replicator.ts';
|
|
26
27
|
|
|
27
28
|
const { forComponent } = harperLogger;
|
|
28
|
-
const logger = forComponent('certificate').conditional;
|
|
29
|
+
const logger = forComponent('certificate').conditional as Logger;
|
|
29
30
|
const pki = forge.pki;
|
|
30
31
|
const CERT_VALIDITY_DAYS = 3650;
|
|
31
32
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{$ as useMutation,a0 as apiClient,a1 as object,a2 as string,a3 as useRouter,a4 as useNavigate,a5 as useCloudAuth,a6 as useForm,a7 as a,a8 as reactExports,a9 as authStore,aa as OverallAppSignIn,ab as toast,ac as logoutOnSuccess,ad as jsxRuntimeExports,ae as Form,af as FormField,ag as FormItem,ah as FormLabel,ai as FormControl,aj as Input,ak as FormMessage,al as Button,am as Save}from"./index-
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{$ as useMutation,a0 as apiClient,a1 as object,a2 as string,a3 as useRouter,a4 as useNavigate,a5 as useCloudAuth,a6 as useForm,a7 as a,a8 as reactExports,a9 as authStore,aa as OverallAppSignIn,ab as toast,ac as logoutOnSuccess,ad as jsxRuntimeExports,ae as Form,af as FormField,ag as FormItem,ah as FormLabel,ai as FormControl,aj as Input,ak as FormMessage,al as Button,am as Save}from"./index-DMDhGP7N.js";async function onUpdateUser(formData){const{id,newPassword,confirmNewPassword,...otherFields}=formData,userData={...otherFields};newPassword&&newPassword===confirmNewPassword&&(userData.password=newPassword);const{data}=await apiClient.patch(`/User/${id}`,userData);return data}__name(onUpdateUser,"onUpdateUser");function useUpdateUserMutation(){return useMutation({mutationFn:__name(formData=>onUpdateUser(formData),"mutationFn")})}__name(useUpdateUserMutation,"useUpdateUserMutation");const UpdateUserSchema=object({id:string(),firstname:string({error:"Please enter your first name."}).min(2,{error:"First name is required."}).max(50,{error:"First name must be less than 50 characters."}),lastname:string({error:"Please enter your last name."}).min(2,{error:"Last name is required."}).max(50,{error:"Last name must be less than 50 characters."}),newPassword:string({error:"Please enter your new password."}).min(8,{error:"Password must be 8 characters or more."}).or(string().max(0)),confirmNewPassword:string().optional()}).refine(data=>data.newPassword===data.confirmNewPassword,{error:"Passwords do not match",path:["confirmNewPassword"]});function ProfileIndex(){const router=useRouter(),navigate=useNavigate(),{user}=useCloudAuth(),methods=useForm({resolver:a(UpdateUserSchema),defaultValues:{confirmNewPassword:"",firstname:user?.firstname||"",id:user?.id||"",lastname:user?.lastname||"",newPassword:""}}),{control,handleSubmit,reset,formState:{defaultValues,isDirty,isValid}}=methods,{mutate:updateUser,isPending:isUpdatePending}=useUpdateUserMutation(),onSubmitClick=reactExports.useCallback(async formData=>{formData&&updateUser(formData,{onSuccess:__name(data=>{reset({...defaultValues,...data}),authStore.updateUserForEntity(OverallAppSignIn,data),formData.newPassword?(toast.success("Profile updated successfully!",{description:"Please sign in with your new password."}),logoutOnSuccess(),navigate({to:"/sign-in"}),router.invalidate()):toast.success("Profile updated successfully!")},"onSuccess")})},[defaultValues,navigate,reset,router,updateUser]);return jsxRuntimeExports.jsxs("div",{className:"mt-20 px-4 pt-4 md:px-12",children:[jsxRuntimeExports.jsx("h2",{className:"text-2xl font-light",children:"Profile"}),jsxRuntimeExports.jsx(Form,{...methods,children:jsxRuntimeExports.jsxs("form",{id:"profile-edit-form",name:"profile-edit-form",onSubmit:handleSubmit(onSubmitClick),className:"grid gap-4 my-4",children:[jsxRuntimeExports.jsx(FormField,{control,name:"firstname",render:__name(({field})=>jsxRuntimeExports.jsxs(FormItem,{children:[jsxRuntimeExports.jsx(FormLabel,{className:"pb-1",children:"First Name"}),jsxRuntimeExports.jsx(FormControl,{children:jsxRuntimeExports.jsx(Input,{type:"text",className:"bg-purple-400 border-purple-400 dark:bg-black dark:border-black",autoCapitalize:"words",...field})}),jsxRuntimeExports.jsx(FormMessage,{})]}),"render")}),jsxRuntimeExports.jsx(FormField,{control,name:"lastname",render:__name(({field})=>jsxRuntimeExports.jsxs(FormItem,{children:[jsxRuntimeExports.jsx(FormLabel,{className:"pb-1",children:"Last Name"}),jsxRuntimeExports.jsx(FormControl,{children:jsxRuntimeExports.jsx(Input,{type:"text",className:"bg-purple-400 border-purple-400 dark:bg-black dark:border-black",autoCapitalize:"words",...field})}),jsxRuntimeExports.jsx(FormMessage,{})]}),"render")}),jsxRuntimeExports.jsx(FormLabel,{className:"pb-1",children:"Email"}),jsxRuntimeExports.jsx(FormControl,{children:jsxRuntimeExports.jsx(Input,{type:"email",enterKeyHint:"next",autoComplete:"email",autoCapitalize:"none",value:user?.email||"",disabled:!0,readOnly:!0})}),jsxRuntimeExports.jsx(FormField,{control,name:"newPassword",render:__name(({field})=>jsxRuntimeExports.jsxs(FormItem,{children:[jsxRuntimeExports.jsx(FormLabel,{className:"pb-1",children:"New Password"}),jsxRuntimeExports.jsx(FormControl,{children:jsxRuntimeExports.jsx(Input,{type:"password",placeholder:"Optional",className:"bg-purple-400 border-purple-400 dark:bg-black dark:border-black",autoComplete:"new-password",autoCapitalize:"none",...field})}),jsxRuntimeExports.jsx(FormMessage,{})]}),"render")}),jsxRuntimeExports.jsx(FormField,{control,name:"confirmNewPassword",render:__name(({field})=>jsxRuntimeExports.jsxs(FormItem,{children:[jsxRuntimeExports.jsx(FormLabel,{className:"pb-1",children:"Confirm New Password"}),jsxRuntimeExports.jsx(FormControl,{children:jsxRuntimeExports.jsx(Input,{type:"password",className:"bg-purple-400 border-purple-400 dark:bg-black dark:border-black",autoComplete:"new-password",autoCapitalize:"none",...field})}),jsxRuntimeExports.jsx(FormMessage,{})]}),"render")}),jsxRuntimeExports.jsx("div",{className:"flex justify-between w-full",children:jsxRuntimeExports.jsxs(Button,{type:"submit",variant:"submit",className:"rounded-full",disabled:isUpdatePending||!isDirty||!isValid,children:[jsxRuntimeExports.jsx(Save,{})," Update Profile"]})})]})})]})}__name(ProfileIndex,"ProfileIndex");export{ProfileIndex};
|
|
2
|
+
//# sourceMappingURL=index-CWN9Wp5V.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-v3wIpSYx.js","sources":["../../src/features/profile/mutations/updateUserMutation.ts","../../src/features/profile/mutations/updateUserSchema.ts","../../src/features/profile/index.tsx"],"sourcesContent":["import { apiClient } from '@/config/apiClient';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { User } from '@/integrations/api/api.patch';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nasync function onUpdateUser(formData: z.infer<typeof UpdateUserSchema>) {\n\tconst { id, newPassword, confirmNewPassword, ...otherFields } = formData;\n\tconst userData: Partial<SchemaUser & { password: string }> = {\n\t\t...otherFields,\n\t};\n\tif (newPassword && newPassword === confirmNewPassword) {\n\t\tuserData.password = newPassword;\n\t}\n\tconst { data } = await apiClient.patch(`/User/${id}` as '/User/{id}', userData);\n\treturn data as Partial<User>;\n}\n\nexport function useUpdateUserMutation() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof UpdateUserSchema>) => onUpdateUser(formData),\n\t});\n}\n","import { z } from 'zod';\n\nexport const UpdateUserSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tfirstname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your first name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'First name is required.' })\n\t\t\t.max(50, { error: 'First name must be less than 50 characters.' }),\n\t\tlastname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your last name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'Last name is required.' })\n\t\t\t.max(50, { error: 'Last name must be less than 50 characters.' }),\n\t\tnewPassword: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your new password.',\n\t\t\t})\n\t\t\t.min(8, { error: 'Password must be 8 characters or more.' })\n\t\t\t.or(z.string().max(0)),\n\t\tconfirmNewPassword: z\n\t\t\t.string()\n\t\t\t.optional(),\n\t})\n\t.refine((data) => data.newPassword === data.confirmNewPassword, {\n\t\terror: 'Passwords do not match',\n\t\tpath: ['confirmNewPassword'],\n\t});\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { logoutOnSuccess } from '@/features/auth/handlers/logoutOnSuccess';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useUpdateUserMutation } from '@/features/profile/mutations/updateUserMutation';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useNavigate, useRouter } from '@tanstack/react-router';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function ProfileIndex() {\n\tconst router = useRouter();\n\tconst navigate = useNavigate();\n\tconst { user } = useCloudAuth();\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(UpdateUserSchema),\n\t\tdefaultValues: {\n\t\t\tconfirmNewPassword: '',\n\t\t\tfirstname: user?.firstname || '',\n\t\t\tid: user?.id || '',\n\t\t\tlastname: user?.lastname || '',\n\t\t\tnewPassword: '',\n\t\t},\n\t});\n\tconst { control, handleSubmit, reset, formState: { defaultValues, isDirty, isValid } } = methods;\n\tconst { mutate: updateUser, isPending: isUpdatePending } = useUpdateUserMutation();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof UpdateUserSchema>) => {\n\t\t\tif (formData) {\n\t\t\t\tupdateUser(formData, {\n\t\t\t\t\tonSuccess: (data) => {\n\t\t\t\t\t\treset({\n\t\t\t\t\t\t\t...defaultValues,\n\t\t\t\t\t\t\t...data,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tauthStore.updateUserForEntity(OverallAppSignIn, data);\n\t\t\t\t\t\tif (formData.newPassword) {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!', {\n\t\t\t\t\t\t\t\tdescription: 'Please sign in with your new password.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tlogoutOnSuccess();\n\t\t\t\t\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t\t\t\t\t\tvoid router.invalidate();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!');\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[defaultValues, navigate, reset, router, updateUser],\n\t);\n\n\treturn (\n\t\t<div className=\"mt-20 px-4 pt-4 md:px-12\">\n\t\t\t<h2 className=\"text-2xl font-light\">Profile</h2>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"profile-edit-form\"\n\t\t\t\t\tname=\"profile-edit-form\"\n\t\t\t\t\tonSubmit={handleSubmit(onSubmitClick)}\n\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"firstname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">First Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"lastname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Last Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormLabel className=\"pb-1\">Email</FormLabel>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\tvalue={user?.email || ''}\n\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"newPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"Optional\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"confirmNewPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tdisabled={isUpdatePending || !isDirty || !isValid}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save /> Update Profile\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n"],"names":["z.object","z.string","zodResolver","useCallback","jsxs","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CWN9Wp5V.js","sources":["../../src/features/profile/mutations/updateUserMutation.ts","../../src/features/profile/mutations/updateUserSchema.ts","../../src/features/profile/index.tsx"],"sourcesContent":["import { apiClient } from '@/config/apiClient';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { User } from '@/integrations/api/api.patch';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nasync function onUpdateUser(formData: z.infer<typeof UpdateUserSchema>) {\n\tconst { id, newPassword, confirmNewPassword, ...otherFields } = formData;\n\tconst userData: Partial<SchemaUser & { password: string }> = {\n\t\t...otherFields,\n\t};\n\tif (newPassword && newPassword === confirmNewPassword) {\n\t\tuserData.password = newPassword;\n\t}\n\tconst { data } = await apiClient.patch(`/User/${id}` as '/User/{id}', userData);\n\treturn data as Partial<User>;\n}\n\nexport function useUpdateUserMutation() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof UpdateUserSchema>) => onUpdateUser(formData),\n\t});\n}\n","import { z } from 'zod';\n\nexport const UpdateUserSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tfirstname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your first name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'First name is required.' })\n\t\t\t.max(50, { error: 'First name must be less than 50 characters.' }),\n\t\tlastname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your last name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'Last name is required.' })\n\t\t\t.max(50, { error: 'Last name must be less than 50 characters.' }),\n\t\tnewPassword: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your new password.',\n\t\t\t})\n\t\t\t.min(8, { error: 'Password must be 8 characters or more.' })\n\t\t\t.or(z.string().max(0)),\n\t\tconfirmNewPassword: z\n\t\t\t.string()\n\t\t\t.optional(),\n\t})\n\t.refine((data) => data.newPassword === data.confirmNewPassword, {\n\t\terror: 'Passwords do not match',\n\t\tpath: ['confirmNewPassword'],\n\t});\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { logoutOnSuccess } from '@/features/auth/handlers/logoutOnSuccess';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useUpdateUserMutation } from '@/features/profile/mutations/updateUserMutation';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useNavigate, useRouter } from '@tanstack/react-router';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function ProfileIndex() {\n\tconst router = useRouter();\n\tconst navigate = useNavigate();\n\tconst { user } = useCloudAuth();\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(UpdateUserSchema),\n\t\tdefaultValues: {\n\t\t\tconfirmNewPassword: '',\n\t\t\tfirstname: user?.firstname || '',\n\t\t\tid: user?.id || '',\n\t\t\tlastname: user?.lastname || '',\n\t\t\tnewPassword: '',\n\t\t},\n\t});\n\tconst { control, handleSubmit, reset, formState: { defaultValues, isDirty, isValid } } = methods;\n\tconst { mutate: updateUser, isPending: isUpdatePending } = useUpdateUserMutation();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof UpdateUserSchema>) => {\n\t\t\tif (formData) {\n\t\t\t\tupdateUser(formData, {\n\t\t\t\t\tonSuccess: (data) => {\n\t\t\t\t\t\treset({\n\t\t\t\t\t\t\t...defaultValues,\n\t\t\t\t\t\t\t...data,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tauthStore.updateUserForEntity(OverallAppSignIn, data);\n\t\t\t\t\t\tif (formData.newPassword) {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!', {\n\t\t\t\t\t\t\t\tdescription: 'Please sign in with your new password.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tlogoutOnSuccess();\n\t\t\t\t\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t\t\t\t\t\tvoid router.invalidate();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!');\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[defaultValues, navigate, reset, router, updateUser],\n\t);\n\n\treturn (\n\t\t<div className=\"mt-20 px-4 pt-4 md:px-12\">\n\t\t\t<h2 className=\"text-2xl font-light\">Profile</h2>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"profile-edit-form\"\n\t\t\t\t\tname=\"profile-edit-form\"\n\t\t\t\t\tonSubmit={handleSubmit(onSubmitClick)}\n\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"firstname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">First Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"lastname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Last Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormLabel className=\"pb-1\">Email</FormLabel>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\tvalue={user?.email || ''}\n\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"newPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"Optional\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"confirmNewPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tdisabled={isUpdatePending || !isDirty || !isValid}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save /> Update Profile\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n"],"names":["z.object","z.string","zodResolver","useCallback","jsxs","jsx"],"mappings":"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"}
|