@yielded/auth-persistence 0.1.0-beta.22 → 0.1.0-beta.24
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/README.md +11 -0
- package/dist/Adapter.d.mts +13 -5
- package/dist/Adapter.mjs +9 -2
- package/dist/OAuthPersistence.d.mts +87 -0
- package/dist/OAuthPersistence.mjs +125 -0
- package/dist/OAuthPersistence.mjs.map +1 -0
- package/dist/_virtual/_rolldown/runtime.mjs +13 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +3 -1
- package/dist/internal/authority-snapshot.mjs +53 -0
- package/dist/internal/authority-snapshot.mjs.map +1 -0
- package/dist/internal/configuration.d.mts +1 -1
- package/dist/internal/configuration.mjs.map +1 -1
- package/dist/internal/models/oauth-connected-model.d.mts +294 -0
- package/dist/internal/models/oauth-connected-model.mjs +22 -0
- package/dist/internal/models/oauth-connected-model.mjs.map +1 -0
- package/dist/internal/models/oauth-model.d.mts +467 -0
- package/dist/internal/models/oauth-model.mjs +49 -0
- package/dist/internal/models/oauth-model.mjs.map +1 -0
- package/dist/internal/models/password-model.d.mts +4 -97
- package/dist/internal/models/password-model.mjs +0 -3
- package/dist/internal/models/password-model.mjs.map +1 -1
- package/dist/internal/native-sql-table.d.mts +34 -0
- package/dist/internal/native-sql-table.mjs +111 -0
- package/dist/internal/native-sql-table.mjs.map +1 -0
- package/dist/internal/oauth/accounts.d.mts +8 -0
- package/dist/internal/oauth/accounts.mjs +379 -0
- package/dist/internal/oauth/accounts.mjs.map +1 -0
- package/dist/internal/oauth/connected-access.d.mts +9 -0
- package/dist/internal/oauth/connected-access.mjs +229 -0
- package/dist/internal/oauth/connected-access.mjs.map +1 -0
- package/dist/internal/oauth/connected-collection.d.mts +7 -0
- package/dist/internal/oauth/connected-collection.mjs +214 -0
- package/dist/internal/oauth/connected-collection.mjs.map +1 -0
- package/dist/internal/oauth/connected-custody.d.mts +6 -0
- package/dist/internal/oauth/connected-custody.mjs +165 -0
- package/dist/internal/oauth/connected-custody.mjs.map +1 -0
- package/dist/internal/oauth/connected-flow.d.mts +7 -0
- package/dist/internal/oauth/connected-flow.mjs +324 -0
- package/dist/internal/oauth/connected-flow.mjs.map +1 -0
- package/dist/internal/oauth/connected-input.mjs +122 -0
- package/dist/internal/oauth/connected-input.mjs.map +1 -0
- package/dist/internal/oauth/connected-keys.d.mts +2 -0
- package/dist/internal/oauth/connected-keys.mjs +22 -0
- package/dist/internal/oauth/connected-keys.mjs.map +1 -0
- package/dist/internal/oauth/connected-maintenance.d.mts +9 -0
- package/dist/internal/oauth/connected-maintenance.mjs +226 -0
- package/dist/internal/oauth/connected-maintenance.mjs.map +1 -0
- package/dist/internal/oauth/connected-management.d.mts +9 -0
- package/dist/internal/oauth/connected-management.mjs +243 -0
- package/dist/internal/oauth/connected-management.mjs.map +1 -0
- package/dist/internal/oauth/connected-reference.mjs +63 -0
- package/dist/internal/oauth/connected-reference.mjs.map +1 -0
- package/dist/internal/oauth/connected-settlement.d.mts +8 -0
- package/dist/internal/oauth/connected-settlement.mjs +141 -0
- package/dist/internal/oauth/connected-settlement.mjs.map +1 -0
- package/dist/internal/oauth/connected-sign-in.d.mts +10 -0
- package/dist/internal/oauth/connected-sign-in.mjs +281 -0
- package/dist/internal/oauth/connected-sign-in.mjs.map +1 -0
- package/dist/internal/oauth/connected-state.d.mts +14 -0
- package/dist/internal/oauth/connected-state.mjs +469 -0
- package/dist/internal/oauth/connected-state.mjs.map +1 -0
- package/dist/internal/oauth/connected-target.d.mts +21 -0
- package/dist/internal/oauth/connected-target.mjs +117 -0
- package/dist/internal/oauth/connected-target.mjs.map +1 -0
- package/dist/internal/oauth/flow.d.mts +5 -0
- package/dist/internal/oauth/flow.mjs +279 -0
- package/dist/internal/oauth/flow.mjs.map +1 -0
- package/dist/internal/oauth/input.mjs +127 -0
- package/dist/internal/oauth/input.mjs.map +1 -0
- package/dist/internal/oauth/owner.d.mts +10 -0
- package/dist/internal/oauth/owner.mjs +10 -0
- package/dist/internal/oauth/owner.mjs.map +1 -0
- package/dist/internal/oauth/query-compiler.d.mts +7 -0
- package/dist/internal/oauth/query-compiler.mjs +9 -0
- package/dist/internal/oauth/query-compiler.mjs.map +1 -0
- package/dist/internal/oauth/registration.d.mts +7 -0
- package/dist/internal/oauth/registration.mjs +393 -0
- package/dist/internal/oauth/registration.mjs.map +1 -0
- package/dist/internal/oauth/state.mjs +107 -0
- package/dist/internal/oauth/state.mjs.map +1 -0
- package/dist/internal/oauth/target.d.mts +31 -0
- package/dist/internal/oauth/target.mjs +273 -0
- package/dist/internal/oauth/target.mjs.map +1 -0
- package/dist/internal/oauth-kernel.d.mts +1423 -0
- package/dist/internal/oauth-kernel.mjs +187 -0
- package/dist/internal/oauth-kernel.mjs.map +1 -0
- package/dist/internal/oauth-proxy.d.mts +31 -0
- package/dist/internal/oauth-proxy.mjs +129 -0
- package/dist/internal/oauth-proxy.mjs.map +1 -0
- package/dist/internal/passkey/target.d.mts +1 -1
- package/dist/internal/passkey-kernel.d.mts +5 -5
- package/dist/internal/passkeys.mjs +1 -1
- package/dist/internal/password-credentials.d.mts +11 -0
- package/dist/internal/password-credentials.mjs +121 -0
- package/dist/internal/password-credentials.mjs.map +1 -0
- package/dist/internal/password-kernel.d.mts +15 -28
- package/dist/internal/password-kernel.mjs +35 -236
- package/dist/internal/password-kernel.mjs.map +1 -1
- package/dist/internal/persistence.d.mts +2 -0
- package/dist/internal/persistence.mjs +5 -5
- package/dist/internal/persistence.mjs.map +1 -1
- package/dist/internal/query-operations.d.mts +2 -0
- package/dist/internal/session-kernel.d.mts +5 -3
- package/dist/internal/session-kernel.mjs +95 -29
- package/dist/internal/session-kernel.mjs.map +1 -1
- package/dist/internal/sql-oauth-connected-model.d.mts +29 -0
- package/dist/internal/sql-oauth-connected-model.mjs +7 -0
- package/dist/internal/sql-oauth-connected-model.mjs.map +1 -0
- package/dist/internal/sql-oauth-model.d.mts +60 -0
- package/dist/internal/sql-oauth-model.mjs +10 -0
- package/dist/internal/sql-oauth-model.mjs.map +1 -0
- package/dist/internal/sql-persistence.mjs +3 -1
- package/dist/internal/sql-persistence.mjs.map +1 -1
- package/dist/internal/sql-query.d.mts +12 -0
- package/dist/internal/sql-query.mjs +15 -18
- package/dist/internal/sql-query.mjs.map +1 -1
- package/dist/internal/sql-storage-validation.mjs +54 -0
- package/dist/internal/sql-storage-validation.mjs.map +1 -0
- package/dist/internal/storage-mapping.mjs +2 -67
- package/dist/internal/storage-mapping.mjs.map +1 -1
- package/dist/internal/storage-plans.d.mts +7 -0
- package/dist/internal/storage-plans.mjs +189 -0
- package/dist/internal/storage-plans.mjs.map +1 -0
- package/dist/internal/storage-tables.d.mts +0 -99
- package/dist/internal/storage-tables.mjs +0 -43
- package/dist/internal/storage-tables.mjs.map +1 -1
- package/dist/internal/storage-validation.d.mts +6 -1
- package/dist/internal/storage-validation.mjs +42 -1
- package/dist/internal/storage-validation.mjs.map +1 -1
- package/dist/internal/transaction-execution-kernel.d.mts +1 -1
- package/dist/internal/transaction-kernel.d.mts +1 -1
- package/dist/internal/transaction-kernel.mjs +3 -2
- package/dist/internal/transaction-kernel.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Adapter.ts +97 -8
- package/src/OAuthPersistence.ts +427 -0
- package/src/index.ts +3 -0
- package/src/internal/authority-snapshot.ts +91 -0
- package/src/internal/configuration.ts +1 -8
- package/src/internal/models/oauth-connected-model.ts +396 -0
- package/src/internal/models/oauth-model.ts +708 -0
- package/src/internal/models/password-model.ts +0 -120
- package/src/internal/native-sql-table.ts +178 -0
- package/src/internal/oauth/accounts.ts +838 -0
- package/src/internal/oauth/connected-access.ts +388 -0
- package/src/internal/oauth/connected-collection.ts +345 -0
- package/src/internal/oauth/connected-custody.ts +308 -0
- package/src/internal/oauth/connected-flow.ts +562 -0
- package/src/internal/oauth/connected-input.ts +147 -0
- package/src/internal/oauth/connected-keys.ts +31 -0
- package/src/internal/oauth/connected-maintenance.ts +379 -0
- package/src/internal/oauth/connected-management.ts +391 -0
- package/src/internal/oauth/connected-reference.ts +135 -0
- package/src/internal/oauth/connected-settlement.ts +278 -0
- package/src/internal/oauth/connected-sign-in.ts +472 -0
- package/src/internal/oauth/connected-state.ts +924 -0
- package/src/internal/oauth/connected-target.ts +307 -0
- package/src/internal/oauth/flow.ts +505 -0
- package/src/internal/oauth/input.ts +201 -0
- package/src/internal/oauth/owner.ts +22 -0
- package/src/internal/oauth/query-compiler.ts +15 -0
- package/src/internal/oauth/registration.ts +676 -0
- package/src/internal/oauth/state.ts +218 -0
- package/src/internal/oauth/target.ts +803 -0
- package/src/internal/oauth-kernel.ts +294 -0
- package/src/internal/oauth-proxy.ts +176 -0
- package/src/internal/password-credentials.ts +245 -0
- package/src/internal/password-kernel.ts +98 -712
- package/src/internal/persistence.ts +5 -10
- package/src/internal/query-operations.ts +2 -0
- package/src/internal/session-kernel.ts +231 -81
- package/src/internal/sql-oauth-connected-model.ts +145 -0
- package/src/internal/sql-oauth-model.ts +263 -0
- package/src/internal/sql-persistence.ts +2 -0
- package/src/internal/sql-query.ts +16 -13
- package/src/internal/sql-storage-validation.ts +64 -0
- package/src/internal/storage-mapping.ts +0 -66
- package/src/internal/storage-plans.ts +218 -0
- package/src/internal/storage-tables.ts +0 -35
- package/src/internal/storage-validation.ts +58 -0
- package/src/internal/transaction-kernel.ts +6 -2
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { requireStandalone } from "./standalone.mjs";
|
|
2
|
+
import { makeTransactionKernel } from "./transaction-kernel.mjs";
|
|
3
|
+
import { makeTransactionExecutionKernel } from "./transaction-execution-kernel.mjs";
|
|
4
|
+
import { OAuthTransactionExecution } from "./oauth/owner.mjs";
|
|
5
|
+
import { OAuthQueryCompiler } from "./oauth/query-compiler.mjs";
|
|
6
|
+
import { captureOAuthMapping, unavailable } from "./oauth/state.mjs";
|
|
7
|
+
import { OAuthFlow } from "./oauth/flow.mjs";
|
|
8
|
+
import { OAuthRegistration } from "./oauth/registration.mjs";
|
|
9
|
+
import { OAuthAccounts } from "./oauth/accounts.mjs";
|
|
10
|
+
import { OAuthConnectedState } from "./oauth/connected-state.mjs";
|
|
11
|
+
import { OAuthConnectedCustody } from "./oauth/connected-custody.mjs";
|
|
12
|
+
import { OAuthConnectedFlow } from "./oauth/connected-flow.mjs";
|
|
13
|
+
import { OAuthConnectedSettlement } from "./oauth/connected-settlement.mjs";
|
|
14
|
+
import { OAuthConnectedAccess } from "./oauth/connected-access.mjs";
|
|
15
|
+
import { OAuthConnectedCollection } from "./oauth/connected-collection.mjs";
|
|
16
|
+
import { OAuthConnectedMaintenance } from "./oauth/connected-maintenance.mjs";
|
|
17
|
+
import { OAuthConnectedManagement } from "./oauth/connected-management.mjs";
|
|
18
|
+
import { makeOAuthConnectedReferenceKernel } from "./oauth/connected-reference.mjs";
|
|
19
|
+
import { OAuthConnectedSignIn } from "./oauth/connected-sign-in.mjs";
|
|
20
|
+
import { OAuthTarget, oauthAccountsPersistenceLayer, oauthRegistrationAuthorityLayer, oauthRegistrationIntentsLayer, oauthSignInPersistenceLayer } from "./oauth/target.mjs";
|
|
21
|
+
import { OAuthConnectedTarget, oauthConnectedPersistenceLayer, oauthConnectedRevocationsLayer } from "./oauth/connected-target.mjs";
|
|
22
|
+
import { Effect, Layer } from "effect";
|
|
23
|
+
//#region src/internal/oauth-kernel.ts
|
|
24
|
+
/** Adapter composition root. Shared operation Layers acquire their dependencies;
|
|
25
|
+
* database and transaction services are still resolved by each operation. */
|
|
26
|
+
const makeOAuthKernel = (operations, dialect) => {
|
|
27
|
+
const transactions = makeTransactionKernel(operations);
|
|
28
|
+
const connectedReference = makeOAuthConnectedReferenceKernel(operations, dialect);
|
|
29
|
+
const compilerLive = Layer.succeed(OAuthQueryCompiler, {
|
|
30
|
+
...operations,
|
|
31
|
+
...transactions.makeTransactionRows(unavailable),
|
|
32
|
+
both: transactions.both,
|
|
33
|
+
connectedReferenceCondition: connectedReference.connectedReferenceCondition
|
|
34
|
+
});
|
|
35
|
+
const executionLive = Layer.succeed(OAuthTransactionExecution, makeTransactionExecutionKernel(transactions));
|
|
36
|
+
const flowLive = OAuthFlow.layer.pipe(Layer.provide([compilerLive]));
|
|
37
|
+
const registrationLive = OAuthRegistration.layer.pipe(Layer.provide([compilerLive, flowLive]));
|
|
38
|
+
const accountsLive = OAuthAccounts.layer.pipe(Layer.provide([
|
|
39
|
+
compilerLive,
|
|
40
|
+
flowLive,
|
|
41
|
+
registrationLive
|
|
42
|
+
]));
|
|
43
|
+
const targetLive = OAuthTarget.layer.pipe(Layer.provide([
|
|
44
|
+
compilerLive,
|
|
45
|
+
accountsLive,
|
|
46
|
+
flowLive,
|
|
47
|
+
registrationLive,
|
|
48
|
+
executionLive
|
|
49
|
+
]));
|
|
50
|
+
const connectedStateLive = OAuthConnectedState.layer.pipe(Layer.provide([compilerLive, flowLive]));
|
|
51
|
+
const connectedFlowLive = OAuthConnectedFlow.layer.pipe(Layer.provide([
|
|
52
|
+
compilerLive,
|
|
53
|
+
connectedStateLive,
|
|
54
|
+
registrationLive
|
|
55
|
+
]));
|
|
56
|
+
const connectedCustodyLive = OAuthConnectedCustody.layer.pipe(Layer.provide([compilerLive, connectedStateLive]));
|
|
57
|
+
const connectedCollectionLive = OAuthConnectedCollection.layer.pipe(Layer.provide([
|
|
58
|
+
compilerLive,
|
|
59
|
+
connectedCustodyLive,
|
|
60
|
+
connectedFlowLive,
|
|
61
|
+
connectedStateLive
|
|
62
|
+
]));
|
|
63
|
+
const connectedSettlementLive = OAuthConnectedSettlement.layer.pipe(Layer.provide([
|
|
64
|
+
compilerLive,
|
|
65
|
+
connectedCustodyLive,
|
|
66
|
+
connectedFlowLive,
|
|
67
|
+
connectedStateLive
|
|
68
|
+
]));
|
|
69
|
+
const connectedAccessLive = OAuthConnectedAccess.layer.pipe(Layer.provide([
|
|
70
|
+
compilerLive,
|
|
71
|
+
connectedCustodyLive,
|
|
72
|
+
connectedFlowLive,
|
|
73
|
+
connectedSettlementLive,
|
|
74
|
+
connectedStateLive
|
|
75
|
+
]));
|
|
76
|
+
const connectedManagementLive = OAuthConnectedManagement.layer.pipe(Layer.provide([
|
|
77
|
+
compilerLive,
|
|
78
|
+
connectedAccessLive,
|
|
79
|
+
connectedCustodyLive,
|
|
80
|
+
connectedFlowLive,
|
|
81
|
+
connectedStateLive
|
|
82
|
+
]));
|
|
83
|
+
const connectedMaintenanceLive = OAuthConnectedMaintenance.layer.pipe(Layer.provide([
|
|
84
|
+
compilerLive,
|
|
85
|
+
connectedCollectionLive,
|
|
86
|
+
connectedCustodyLive,
|
|
87
|
+
connectedFlowLive,
|
|
88
|
+
connectedStateLive
|
|
89
|
+
]));
|
|
90
|
+
const connectedSignInLive = OAuthConnectedSignIn.layer.pipe(Layer.provide([
|
|
91
|
+
compilerLive,
|
|
92
|
+
connectedCustodyLive,
|
|
93
|
+
connectedFlowLive,
|
|
94
|
+
connectedSettlementLive,
|
|
95
|
+
connectedStateLive,
|
|
96
|
+
flowLive
|
|
97
|
+
]));
|
|
98
|
+
const connectedTargetLive = OAuthConnectedTarget.layer.pipe(Layer.provide([
|
|
99
|
+
connectedAccessLive,
|
|
100
|
+
connectedFlowLive,
|
|
101
|
+
connectedMaintenanceLive,
|
|
102
|
+
connectedManagementLive,
|
|
103
|
+
connectedSettlementLive,
|
|
104
|
+
connectedSignInLive,
|
|
105
|
+
connectedStateLive,
|
|
106
|
+
targetLive
|
|
107
|
+
]));
|
|
108
|
+
const makeTargetOAuthSignInServices = (mapping, configuration) => {
|
|
109
|
+
const captured = captureOAuthMapping(mapping);
|
|
110
|
+
return Effect.flatMap(OAuthTarget, (service) => service.makeTargetOAuthSignInServices(captured, configuration)).pipe(Effect.provide(targetLive, { local: true }));
|
|
111
|
+
};
|
|
112
|
+
const makeTargetOAuthRegistrationIntentServices = (mapping, configuration) => {
|
|
113
|
+
const captured = captureOAuthMapping(mapping);
|
|
114
|
+
return Effect.flatMap(OAuthTarget, (service) => service.makeTargetOAuthRegistrationIntentServices(captured, configuration)).pipe(Effect.provide(targetLive, { local: true }));
|
|
115
|
+
};
|
|
116
|
+
const makeTargetOAuthRegistrationServices = (mapping, configuration) => {
|
|
117
|
+
const captured = captureOAuthMapping(mapping);
|
|
118
|
+
return Effect.flatMap(OAuthTarget, (service) => service.makeTargetOAuthRegistrationServices(captured, configuration)).pipe(Effect.provide(targetLive, { local: true }));
|
|
119
|
+
};
|
|
120
|
+
const makeTargetOAuthAccountsServices = (mapping, configuration) => {
|
|
121
|
+
const captured = captureOAuthMapping(mapping);
|
|
122
|
+
return Effect.flatMap(OAuthTarget, (service) => service.makeTargetOAuthAccountsServices(captured, configuration)).pipe(Effect.provide(targetLive, { local: true }));
|
|
123
|
+
};
|
|
124
|
+
const coordinateTargetOAuthRegistration = (database, mapping, configuration, owner) => {
|
|
125
|
+
const captured = captureOAuthMapping(mapping);
|
|
126
|
+
return Effect.flatMap(OAuthTarget, (service) => service.coordinateTargetOAuthRegistration(database, captured, configuration, owner)).pipe(Effect.provide(targetLive, { local: true }));
|
|
127
|
+
};
|
|
128
|
+
const coordinateTargetOAuthSignIn = (database, mapping, configuration, owner) => {
|
|
129
|
+
const captured = captureOAuthMapping(mapping);
|
|
130
|
+
return Effect.flatMap(OAuthTarget, (service) => service.coordinateTargetOAuthSignIn(database, captured, configuration, owner)).pipe(Effect.provide(targetLive, { local: true }));
|
|
131
|
+
};
|
|
132
|
+
const coordinateTargetOAuthRegistrationIntents = (database, mapping, configuration, owner) => {
|
|
133
|
+
const captured = captureOAuthMapping(mapping);
|
|
134
|
+
return Effect.flatMap(OAuthTarget, (service) => service.coordinateTargetOAuthRegistrationIntents(database, captured, configuration, owner)).pipe(Effect.provide(targetLive, { local: true }));
|
|
135
|
+
};
|
|
136
|
+
const coordinateTargetOAuthAccounts = (database, mapping, configuration, owner) => {
|
|
137
|
+
const captured = captureOAuthMapping(mapping);
|
|
138
|
+
return Effect.flatMap(OAuthTarget, (service) => service.coordinateTargetOAuthAccounts(database, captured, configuration, owner)).pipe(Effect.provide(targetLive, { local: true }));
|
|
139
|
+
};
|
|
140
|
+
const makeTargetOAuthConnectedServices = (mapping, configuration) => {
|
|
141
|
+
const captured = captureOAuthMapping(mapping);
|
|
142
|
+
return Effect.flatMap(OAuthConnectedTarget, (service) => service.makeTargetOAuthConnectedServices(captured, configuration)).pipe(Effect.provide(connectedTargetLive, { local: true }));
|
|
143
|
+
};
|
|
144
|
+
const makeTargetOAuthConnectedRevocationServices = (mapping, configuration) => {
|
|
145
|
+
const captured = captureOAuthMapping(mapping);
|
|
146
|
+
return Effect.flatMap(OAuthConnectedTarget, (service) => service.makeTargetOAuthConnectedRevocationServices(captured, configuration)).pipe(Effect.provide(connectedTargetLive, { local: true }));
|
|
147
|
+
};
|
|
148
|
+
const coordinateTargetOAuthConnected = (database, mapping, configuration, owner) => {
|
|
149
|
+
const captured = captureOAuthMapping(mapping);
|
|
150
|
+
return Effect.flatMap(OAuthConnectedTarget, (service) => service.coordinateTargetOAuthConnected(database, captured, configuration, owner)).pipe(Effect.provide(connectedTargetLive, { local: true }));
|
|
151
|
+
};
|
|
152
|
+
const coordinateTargetOAuthConnectedRevocations = (database, mapping, configuration, owner) => {
|
|
153
|
+
const captured = captureOAuthMapping(mapping);
|
|
154
|
+
return Effect.flatMap(OAuthConnectedTarget, (service) => service.coordinateTargetOAuthConnectedRevocations(database, captured, configuration, owner)).pipe(Effect.provide(connectedTargetLive, { local: true }));
|
|
155
|
+
};
|
|
156
|
+
const sqlClientOAuthStandaloneGuard = (service) => requireStandalone(unavailable, service);
|
|
157
|
+
return {
|
|
158
|
+
target: {
|
|
159
|
+
makeTargetOAuthSignInServices,
|
|
160
|
+
makeTargetOAuthRegistrationIntentServices,
|
|
161
|
+
makeTargetOAuthRegistrationServices,
|
|
162
|
+
makeTargetOAuthAccountsServices,
|
|
163
|
+
coordinateTargetOAuthRegistration,
|
|
164
|
+
coordinateTargetOAuthSignIn,
|
|
165
|
+
coordinateTargetOAuthRegistrationIntents,
|
|
166
|
+
coordinateTargetOAuthAccounts,
|
|
167
|
+
sqlClientOAuthStandaloneGuard,
|
|
168
|
+
oauthAccountsPersistenceLayer,
|
|
169
|
+
oauthSignInPersistenceLayer,
|
|
170
|
+
oauthRegistrationIntentsLayer,
|
|
171
|
+
oauthRegistrationAuthorityLayer
|
|
172
|
+
},
|
|
173
|
+
connectedTarget: {
|
|
174
|
+
makeTargetOAuthConnectedServices,
|
|
175
|
+
makeTargetOAuthConnectedRevocationServices,
|
|
176
|
+
coordinateTargetOAuthConnected,
|
|
177
|
+
coordinateTargetOAuthConnectedRevocations,
|
|
178
|
+
oauthConnectedPersistenceLayer,
|
|
179
|
+
oauthConnectedRevocationsLayer
|
|
180
|
+
},
|
|
181
|
+
connectedReference
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
//#endregion
|
|
185
|
+
export { makeOAuthKernel };
|
|
186
|
+
|
|
187
|
+
//# sourceMappingURL=oauth-kernel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-kernel.mjs","names":[],"sources":["../../src/internal/oauth-kernel.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport type { SqlClient } from \"effect/sql/SqlClient\";\n\nimport { OAuthAccounts } from \"./oauth/accounts\";\nimport { OAuthConnectedAccess } from \"./oauth/connected-access\";\nimport { OAuthConnectedCollection } from \"./oauth/connected-collection\";\nimport { OAuthConnectedCustody } from \"./oauth/connected-custody\";\nimport { OAuthConnectedFlow } from \"./oauth/connected-flow\";\nimport { OAuthConnectedMaintenance } from \"./oauth/connected-maintenance\";\nimport { OAuthConnectedManagement } from \"./oauth/connected-management\";\nimport { makeOAuthConnectedReferenceKernel } from \"./oauth/connected-reference\";\nimport { OAuthConnectedSettlement } from \"./oauth/connected-settlement\";\nimport { OAuthConnectedSignIn } from \"./oauth/connected-sign-in\";\nimport { OAuthConnectedState } from \"./oauth/connected-state\";\nimport {\n OAuthConnectedTarget,\n oauthConnectedPersistenceLayer,\n oauthConnectedRevocationsLayer,\n} from \"./oauth/connected-target\";\nimport { OAuthFlow } from \"./oauth/flow\";\nimport { OAuthTransactionExecution } from \"./oauth/owner\";\nimport { OAuthQueryCompiler } from \"./oauth/query-compiler\";\nimport { OAuthRegistration } from \"./oauth/registration\";\nimport { captureOAuthMapping, unavailable } from \"./oauth/state\";\nimport {\n OAuthTarget,\n oauthAccountsPersistenceLayer,\n oauthSignInPersistenceLayer,\n oauthRegistrationIntentsLayer,\n oauthRegistrationAuthorityLayer,\n} from \"./oauth/target\";\nimport type { QueryOperations } from \"./query-operations\";\nimport { requireStandalone } from \"./standalone\";\nimport { makeTransactionExecutionKernel } from \"./transaction-execution-kernel\";\nimport { makeTransactionKernel } from \"./transaction-kernel\";\n\nexport type OAuthKernel = ReturnType<typeof makeOAuthKernel>;\n\n/** Adapter composition root. Shared operation Layers acquire their dependencies;\n * database and transaction services are still resolved by each operation. */\nexport const makeOAuthKernel = (\n operations: QueryOperations,\n dialect: (table: object) => \"pg\" | \"sqlite\" | \"mysql\",\n) => {\n const transactions = makeTransactionKernel(operations);\n const connectedReference = makeOAuthConnectedReferenceKernel(operations, dialect);\n\n const compilerLive = Layer.succeed(OAuthQueryCompiler, {\n ...operations,\n ...transactions.makeTransactionRows(unavailable),\n both: transactions.both,\n connectedReferenceCondition: connectedReference.connectedReferenceCondition,\n });\n\n const executionLive = Layer.succeed(\n OAuthTransactionExecution,\n makeTransactionExecutionKernel(transactions),\n );\n\n const flowLive = OAuthFlow.layer.pipe(Layer.provide([compilerLive]));\n const registrationLive = OAuthRegistration.layer.pipe(Layer.provide([compilerLive, flowLive]));\n\n const accountsLive = OAuthAccounts.layer.pipe(\n Layer.provide([compilerLive, flowLive, registrationLive]),\n );\n\n const targetLive = OAuthTarget.layer.pipe(\n Layer.provide([compilerLive, accountsLive, flowLive, registrationLive, executionLive]),\n );\n\n const connectedStateLive = OAuthConnectedState.layer.pipe(\n Layer.provide([compilerLive, flowLive]),\n );\n\n const connectedFlowLive = OAuthConnectedFlow.layer.pipe(\n Layer.provide([compilerLive, connectedStateLive, registrationLive]),\n );\n\n const connectedCustodyLive = OAuthConnectedCustody.layer.pipe(\n Layer.provide([compilerLive, connectedStateLive]),\n );\n\n const connectedCollectionLive = OAuthConnectedCollection.layer.pipe(\n Layer.provide([compilerLive, connectedCustodyLive, connectedFlowLive, connectedStateLive]),\n );\n\n const connectedSettlementLive = OAuthConnectedSettlement.layer.pipe(\n Layer.provide([compilerLive, connectedCustodyLive, connectedFlowLive, connectedStateLive]),\n );\n\n const connectedAccessLive = OAuthConnectedAccess.layer.pipe(\n Layer.provide([\n compilerLive,\n connectedCustodyLive,\n connectedFlowLive,\n connectedSettlementLive,\n connectedStateLive,\n ]),\n );\n\n const connectedManagementLive = OAuthConnectedManagement.layer.pipe(\n Layer.provide([\n compilerLive,\n connectedAccessLive,\n connectedCustodyLive,\n connectedFlowLive,\n connectedStateLive,\n ]),\n );\n\n const connectedMaintenanceLive = OAuthConnectedMaintenance.layer.pipe(\n Layer.provide([\n compilerLive,\n connectedCollectionLive,\n connectedCustodyLive,\n connectedFlowLive,\n connectedStateLive,\n ]),\n );\n\n const connectedSignInLive = OAuthConnectedSignIn.layer.pipe(\n Layer.provide([\n compilerLive,\n connectedCustodyLive,\n connectedFlowLive,\n connectedSettlementLive,\n connectedStateLive,\n flowLive,\n ]),\n );\n\n const connectedTargetLive = OAuthConnectedTarget.layer.pipe(\n Layer.provide([\n connectedAccessLive,\n connectedFlowLive,\n connectedMaintenanceLive,\n connectedManagementLive,\n connectedSettlementLive,\n connectedSignInLive,\n connectedStateLive,\n targetLive,\n ]),\n );\n\n // Keep shared operation Layers local to this adapter compiler, even inside another\n // coordinator. Preserve constructor-time snapshots before deferred acquisition.\n const makeTargetOAuthSignInServices: OAuthTarget[\"Service\"][\"makeTargetOAuthSignInServices\"] = (\n mapping,\n configuration,\n ) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.makeTargetOAuthSignInServices(captured, configuration),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const makeTargetOAuthRegistrationIntentServices: OAuthTarget[\"Service\"][\"makeTargetOAuthRegistrationIntentServices\"] =\n (mapping, configuration) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.makeTargetOAuthRegistrationIntentServices(captured, configuration),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const makeTargetOAuthRegistrationServices: OAuthTarget[\"Service\"][\"makeTargetOAuthRegistrationServices\"] =\n (mapping, configuration) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.makeTargetOAuthRegistrationServices(captured, configuration),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const makeTargetOAuthAccountsServices: OAuthTarget[\"Service\"][\"makeTargetOAuthAccountsServices\"] =\n (mapping, configuration) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.makeTargetOAuthAccountsServices(captured, configuration),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const coordinateTargetOAuthRegistration: OAuthTarget[\"Service\"][\"coordinateTargetOAuthRegistration\"] =\n (database, mapping, configuration, owner) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.coordinateTargetOAuthRegistration(database, captured, configuration, owner),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const coordinateTargetOAuthSignIn: OAuthTarget[\"Service\"][\"coordinateTargetOAuthSignIn\"] = (\n database,\n mapping,\n configuration,\n owner,\n ) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.coordinateTargetOAuthSignIn(database, captured, configuration, owner),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const coordinateTargetOAuthRegistrationIntents: OAuthTarget[\"Service\"][\"coordinateTargetOAuthRegistrationIntents\"] =\n (database, mapping, configuration, owner) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.coordinateTargetOAuthRegistrationIntents(database, captured, configuration, owner),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const coordinateTargetOAuthAccounts: OAuthTarget[\"Service\"][\"coordinateTargetOAuthAccounts\"] = (\n database,\n mapping,\n configuration,\n owner,\n ) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthTarget, (service) =>\n service.coordinateTargetOAuthAccounts(database, captured, configuration, owner),\n ).pipe(Effect.provide(targetLive, { local: true }));\n };\n\n const makeTargetOAuthConnectedServices: OAuthConnectedTarget[\"Service\"][\"makeTargetOAuthConnectedServices\"] =\n (mapping, configuration) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthConnectedTarget, (service) =>\n service.makeTargetOAuthConnectedServices(captured, configuration),\n ).pipe(Effect.provide(connectedTargetLive, { local: true }));\n };\n\n const makeTargetOAuthConnectedRevocationServices: OAuthConnectedTarget[\"Service\"][\"makeTargetOAuthConnectedRevocationServices\"] =\n (mapping, configuration) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthConnectedTarget, (service) =>\n service.makeTargetOAuthConnectedRevocationServices(captured, configuration),\n ).pipe(Effect.provide(connectedTargetLive, { local: true }));\n };\n\n const coordinateTargetOAuthConnected: OAuthConnectedTarget[\"Service\"][\"coordinateTargetOAuthConnected\"] =\n (database, mapping, configuration, owner) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthConnectedTarget, (service) =>\n service.coordinateTargetOAuthConnected(database, captured, configuration, owner),\n ).pipe(Effect.provide(connectedTargetLive, { local: true }));\n };\n\n const coordinateTargetOAuthConnectedRevocations: OAuthConnectedTarget[\"Service\"][\"coordinateTargetOAuthConnectedRevocations\"] =\n (database, mapping, configuration, owner) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(OAuthConnectedTarget, (service) =>\n service.coordinateTargetOAuthConnectedRevocations(database, captured, configuration, owner),\n ).pipe(Effect.provide(connectedTargetLive, { local: true }));\n };\n\n const sqlClientOAuthStandaloneGuard = (service: SqlClient[\"transactionService\"] | undefined) =>\n requireStandalone(unavailable, service);\n\n return {\n target: {\n makeTargetOAuthSignInServices,\n makeTargetOAuthRegistrationIntentServices,\n makeTargetOAuthRegistrationServices,\n makeTargetOAuthAccountsServices,\n coordinateTargetOAuthRegistration,\n coordinateTargetOAuthSignIn,\n coordinateTargetOAuthRegistrationIntents,\n coordinateTargetOAuthAccounts,\n sqlClientOAuthStandaloneGuard,\n oauthAccountsPersistenceLayer,\n oauthSignInPersistenceLayer,\n oauthRegistrationIntentsLayer,\n oauthRegistrationAuthorityLayer,\n },\n connectedTarget: {\n makeTargetOAuthConnectedServices,\n makeTargetOAuthConnectedRevocationServices,\n coordinateTargetOAuthConnected,\n coordinateTargetOAuthConnectedRevocations,\n oauthConnectedPersistenceLayer,\n oauthConnectedRevocationsLayer,\n },\n connectedReference,\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { Persistence, Record, Unavailable } from "@yielded/auth/OAuthProxy";
|
|
4
|
+
//#region src/internal/oauth-proxy.d.ts
|
|
5
|
+
export declare const oauthProxyColumns: {
|
|
6
|
+
readonly namespace: "namespace";
|
|
7
|
+
readonly flowId: "flow_id";
|
|
8
|
+
readonly version: "version";
|
|
9
|
+
readonly stage: "stage";
|
|
10
|
+
readonly context: "context";
|
|
11
|
+
readonly expiresAtMillis: "expires_at_millis";
|
|
12
|
+
readonly handoffExpiresAtMillis: "handoff_expires_at_millis";
|
|
13
|
+
readonly payload: "payload";
|
|
14
|
+
};
|
|
15
|
+
/** Plain text and integer-millisecond storage; adapters supply physical names. */
|
|
16
|
+
export interface OAuthProxySqlTable {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly schema?: string;
|
|
19
|
+
readonly columns: { readonly [K in keyof typeof oauthProxyColumns]: string; };
|
|
20
|
+
}
|
|
21
|
+
export declare const makeOAuthProxyPersistence: (table: OAuthProxySqlTable) => Effect.Effect<{
|
|
22
|
+
readonly get: (namespace: string, id: string) => Effect.Effect<Record | undefined, Unavailable>;
|
|
23
|
+
readonly insert: (namespace: string, record: Record) => Effect.Effect<boolean, Unavailable>;
|
|
24
|
+
readonly compareAndSet: (namespace: string, version: string, record: Record) => Effect.Effect<boolean, Unavailable>;
|
|
25
|
+
}, Unavailable, SqlClient.SqlClient>;
|
|
26
|
+
export declare const OAuthProxyPersistence: {
|
|
27
|
+
migration: string;
|
|
28
|
+
layer: Layer.Layer<Persistence, Unavailable, SqlClient.SqlClient>;
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
//# sourceMappingURL=oauth-proxy.d.mts.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { identifier } from "./sql-table.mjs";
|
|
2
|
+
import { requireStandalone } from "./standalone.mjs";
|
|
3
|
+
import { Effect, Layer, Schema } from "effect";
|
|
4
|
+
import { SqlClient } from "effect/sql";
|
|
5
|
+
import { FlowContext, Persistence, Record, Unavailable } from "@yielded/auth/OAuthProxy";
|
|
6
|
+
//#region src/internal/oauth-proxy.ts
|
|
7
|
+
const oauthProxyColumns = {
|
|
8
|
+
namespace: "namespace",
|
|
9
|
+
flowId: "flow_id",
|
|
10
|
+
version: "version",
|
|
11
|
+
stage: "stage",
|
|
12
|
+
context: "context",
|
|
13
|
+
expiresAtMillis: "expires_at_millis",
|
|
14
|
+
handoffExpiresAtMillis: "handoff_expires_at_millis",
|
|
15
|
+
payload: "payload"
|
|
16
|
+
};
|
|
17
|
+
const codec = Schema.fromJsonString(Record);
|
|
18
|
+
const contextCodec = Schema.fromJsonString(FlowContext);
|
|
19
|
+
const Row = Schema.Struct({
|
|
20
|
+
payload: Schema.String,
|
|
21
|
+
version: Schema.String,
|
|
22
|
+
stage: Schema.String,
|
|
23
|
+
context: Schema.String,
|
|
24
|
+
expiry: Schema.String,
|
|
25
|
+
deadline: Schema.NullOr(Schema.String)
|
|
26
|
+
});
|
|
27
|
+
/** SQLite/D1 and PostgreSQL; apply once through application migrations.
|
|
28
|
+
* Retain terminal records until expires_at_millis, then expired rows may be deleted.
|
|
29
|
+
* Context and stage columns guard each standalone transition without a prior read.
|
|
30
|
+
*/
|
|
31
|
+
const migration = `CREATE TABLE yielded_oauth_proxy (
|
|
32
|
+
namespace TEXT NOT NULL,
|
|
33
|
+
flow_id TEXT NOT NULL,
|
|
34
|
+
version TEXT NOT NULL,
|
|
35
|
+
stage TEXT NOT NULL CHECK (stage IN ('Pending', 'Exchanging', 'Ready', 'Consumed')),
|
|
36
|
+
context TEXT NOT NULL,
|
|
37
|
+
expires_at_millis BIGINT NOT NULL,
|
|
38
|
+
handoff_expires_at_millis BIGINT,
|
|
39
|
+
payload TEXT NOT NULL,
|
|
40
|
+
PRIMARY KEY (namespace, flow_id),
|
|
41
|
+
CHECK ((stage = 'Ready' AND handoff_expires_at_millis IS NOT NULL)
|
|
42
|
+
OR (stage <> 'Ready' AND handoff_expires_at_millis IS NULL))
|
|
43
|
+
)`;
|
|
44
|
+
const makeOAuthProxyPersistence = Effect.fnUntraced(function* (table) {
|
|
45
|
+
const sql = (yield* SqlClient.SqlClient).withoutTransforms();
|
|
46
|
+
if (!sql.onDialectOrElse({
|
|
47
|
+
sqlite: () => true,
|
|
48
|
+
pg: () => true,
|
|
49
|
+
orElse: () => false
|
|
50
|
+
})) return yield* Unavailable.make({});
|
|
51
|
+
const names = Object.values(table.columns);
|
|
52
|
+
if ([
|
|
53
|
+
table.name,
|
|
54
|
+
table.schema ?? "main",
|
|
55
|
+
...names
|
|
56
|
+
].some((name) => !name || name.includes("\0")) || new Set(names).size !== names.length) return yield* Unavailable.make({});
|
|
57
|
+
const name = sql.literal((table.schema === void 0 ? "" : `${identifier(table.schema)}.`) + identifier(table.name));
|
|
58
|
+
const column = (key) => sql.literal(identifier(table.columns[key]));
|
|
59
|
+
const standalone = requireStandalone(() => Unavailable.make({}), sql.transactionService);
|
|
60
|
+
const failure = (effect) => effect.pipe(Effect.mapError(() => Unavailable.make({})));
|
|
61
|
+
const clock = sql.onDialectOrElse({
|
|
62
|
+
sqlite: () => sql.literal("CAST((julianday('now') - 2440587.5) * 86400000 AS INTEGER)"),
|
|
63
|
+
orElse: () => sql.literal("CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)")
|
|
64
|
+
});
|
|
65
|
+
return Persistence.of({
|
|
66
|
+
get: Effect.fnUntraced(function* (namespace, id) {
|
|
67
|
+
yield* standalone;
|
|
68
|
+
const rows = yield* sql`SELECT ${column("payload")} AS payload,
|
|
69
|
+
${column("version")} AS version, ${column("stage")} AS stage, ${column("context")} AS context,
|
|
70
|
+
CAST(${column("expiresAtMillis")} AS TEXT) AS expiry,
|
|
71
|
+
CAST(${column("handoffExpiresAtMillis")} AS TEXT) AS deadline
|
|
72
|
+
FROM ${name} WHERE ${column("namespace")} = ${namespace} AND ${column("flowId")} = ${id}`;
|
|
73
|
+
if (rows.length === 0) return void 0;
|
|
74
|
+
if (rows.length !== 1) return yield* Unavailable.make({});
|
|
75
|
+
const row = yield* Schema.decodeUnknownEffect(Row)(rows[0]);
|
|
76
|
+
const record = yield* Schema.decodeEffect(codec)(row.payload);
|
|
77
|
+
const context = yield* Schema.encodeEffect(contextCodec)(record.context);
|
|
78
|
+
if (record.context.id !== id || record.version !== row.version || record._tag !== row.stage || context !== row.context || String(record.context.expiresAtMillis) !== row.expiry || (record._tag === "Ready" ? String(record.handoffExpiresAtMillis) : null) !== row.deadline) return yield* Unavailable.make({});
|
|
79
|
+
return record;
|
|
80
|
+
}, failure),
|
|
81
|
+
insert: Effect.fnUntraced(function* (namespace, record) {
|
|
82
|
+
yield* standalone;
|
|
83
|
+
if (record._tag !== "Pending") return yield* Unavailable.make({});
|
|
84
|
+
const payload = yield* Schema.encodeEffect(codec)(record);
|
|
85
|
+
const context = yield* Schema.encodeEffect(contextCodec)(record.context);
|
|
86
|
+
return (yield* sql`INSERT INTO ${name}
|
|
87
|
+
(${column("namespace")}, ${column("flowId")}, ${column("version")}, ${column("stage")},
|
|
88
|
+
${column("context")}, ${column("expiresAtMillis")}, ${column("payload")})
|
|
89
|
+
SELECT ${namespace}, ${record.context.id}, ${record.version}, ${record._tag},
|
|
90
|
+
${context}, ${record.context.expiresAtMillis}, ${payload}
|
|
91
|
+
WHERE ${record.context.expiresAtMillis} > ${clock}
|
|
92
|
+
ON CONFLICT (${column("namespace")}, ${column("flowId")}) DO NOTHING
|
|
93
|
+
RETURNING ${column("version")}`).length === 1;
|
|
94
|
+
}, failure),
|
|
95
|
+
compareAndSet: Effect.fnUntraced(function* (namespace, version, record) {
|
|
96
|
+
yield* standalone;
|
|
97
|
+
if (version === record.version || record._tag === "Pending") return yield* Unavailable.make({});
|
|
98
|
+
const payload = yield* Schema.encodeEffect(codec)(record._tag === "Ready" ? record : {
|
|
99
|
+
_tag: record._tag,
|
|
100
|
+
version: record.version,
|
|
101
|
+
context: record.context
|
|
102
|
+
});
|
|
103
|
+
const context = yield* Schema.encodeEffect(contextCodec)(record.context);
|
|
104
|
+
const previous = record._tag === "Exchanging" ? "Pending" : record._tag === "Ready" ? "Exchanging" : "Ready";
|
|
105
|
+
const deadline = record._tag === "Ready" ? record.handoffExpiresAtMillis : null;
|
|
106
|
+
const consume = record._tag === "Consumed" ? sql`AND ${column("handoffExpiresAtMillis")} > ${clock}` : sql.literal("");
|
|
107
|
+
return (yield* sql`UPDATE ${name}
|
|
108
|
+
SET ${column("version")} = ${record.version}, ${column("stage")} = ${record._tag},
|
|
109
|
+
${column("handoffExpiresAtMillis")} = ${deadline}, ${column("payload")} = ${payload}
|
|
110
|
+
WHERE ${column("namespace")} = ${namespace} AND ${column("flowId")} = ${record.context.id}
|
|
111
|
+
AND ${column("version")} = ${version} AND ${column("stage")} = ${previous}
|
|
112
|
+
AND ${column("context")} = ${context}
|
|
113
|
+
AND ${column("expiresAtMillis")} = ${record.context.expiresAtMillis}
|
|
114
|
+
AND ${column("expiresAtMillis")} > ${clock} ${consume}
|
|
115
|
+
RETURNING ${column("version")}`).length === 1;
|
|
116
|
+
}, failure)
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
const OAuthProxyPersistence = {
|
|
120
|
+
migration,
|
|
121
|
+
layer: Layer.effect(Persistence, makeOAuthProxyPersistence({
|
|
122
|
+
name: "yielded_oauth_proxy",
|
|
123
|
+
columns: oauthProxyColumns
|
|
124
|
+
}))
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
export { OAuthProxyPersistence, makeOAuthProxyPersistence, oauthProxyColumns };
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=oauth-proxy.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-proxy.mjs","names":[],"sources":["../../src/internal/oauth-proxy.ts"],"sourcesContent":["import { FlowContext, Persistence, Record, Unavailable } from \"@yielded/auth/OAuthProxy\";\nimport { Effect, Layer, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql\";\n\nimport { identifier } from \"./sql-table\";\nimport { requireStandalone } from \"./standalone\";\n\nexport const oauthProxyColumns = {\n namespace: \"namespace\",\n flowId: \"flow_id\",\n version: \"version\",\n stage: \"stage\",\n context: \"context\",\n expiresAtMillis: \"expires_at_millis\",\n handoffExpiresAtMillis: \"handoff_expires_at_millis\",\n payload: \"payload\",\n} as const;\n\n/** Plain text and integer-millisecond storage; adapters supply physical names. */\nexport interface OAuthProxySqlTable {\n readonly name: string;\n readonly schema?: string;\n readonly columns: { readonly [K in keyof typeof oauthProxyColumns]: string };\n}\n\nconst codec = Schema.fromJsonString(Record);\nconst contextCodec = Schema.fromJsonString(FlowContext);\n\nconst Row = Schema.Struct({\n payload: Schema.String,\n version: Schema.String,\n stage: Schema.String,\n context: Schema.String,\n expiry: Schema.String,\n deadline: Schema.NullOr(Schema.String),\n});\n\n/** SQLite/D1 and PostgreSQL; apply once through application migrations.\n * Retain terminal records until expires_at_millis, then expired rows may be deleted.\n * Context and stage columns guard each standalone transition without a prior read.\n */\nconst migration = `CREATE TABLE yielded_oauth_proxy (\n namespace TEXT NOT NULL,\n flow_id TEXT NOT NULL,\n version TEXT NOT NULL,\n stage TEXT NOT NULL CHECK (stage IN ('Pending', 'Exchanging', 'Ready', 'Consumed')),\n context TEXT NOT NULL,\n expires_at_millis BIGINT NOT NULL,\n handoff_expires_at_millis BIGINT,\n payload TEXT NOT NULL,\n PRIMARY KEY (namespace, flow_id),\n CHECK ((stage = 'Ready' AND handoff_expires_at_millis IS NOT NULL)\n OR (stage <> 'Ready' AND handoff_expires_at_millis IS NULL))\n)`;\n\nexport const makeOAuthProxyPersistence = Effect.fnUntraced(function* (table: OAuthProxySqlTable) {\n const sql = (yield* SqlClient.SqlClient).withoutTransforms();\n\n if (!sql.onDialectOrElse({ sqlite: () => true, pg: () => true, orElse: () => false }))\n return yield* Unavailable.make({});\n\n const names = Object.values(table.columns);\n\n if (\n [table.name, table.schema ?? \"main\", ...names].some((name) => !name || name.includes(\"\\0\")) ||\n new Set(names).size !== names.length\n )\n return yield* Unavailable.make({});\n\n const name = sql.literal(\n (table.schema === undefined ? \"\" : `${identifier(table.schema)}.`) + identifier(table.name),\n );\n\n const column = (key: keyof typeof oauthProxyColumns) =>\n sql.literal(identifier(table.columns[key]));\n\n const standalone = requireStandalone(() => Unavailable.make({}), sql.transactionService);\n\n const failure = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(Effect.mapError(() => Unavailable.make({})));\n\n const clock = sql.onDialectOrElse({\n sqlite: () => sql.literal(\"CAST((julianday('now') - 2440587.5) * 86400000 AS INTEGER)\"),\n orElse: () => sql.literal(\"CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)\"),\n });\n\n return Persistence.of({\n get: Effect.fnUntraced(function* (namespace, id) {\n yield* standalone;\n\n const rows = yield* sql`SELECT ${column(\"payload\")} AS payload,\n ${column(\"version\")} AS version, ${column(\"stage\")} AS stage, ${column(\"context\")} AS context,\n CAST(${column(\"expiresAtMillis\")} AS TEXT) AS expiry,\n CAST(${column(\"handoffExpiresAtMillis\")} AS TEXT) AS deadline\n FROM ${name} WHERE ${column(\"namespace\")} = ${namespace} AND ${column(\"flowId\")} = ${id}`;\n\n if (rows.length === 0) return undefined;\n if (rows.length !== 1) return yield* Unavailable.make({});\n const row = yield* Schema.decodeUnknownEffect(Row)(rows[0]);\n const record = yield* Schema.decodeEffect(codec)(row.payload);\n const context = yield* Schema.encodeEffect(contextCodec)(record.context);\n\n if (\n record.context.id !== id ||\n record.version !== row.version ||\n record._tag !== row.stage ||\n context !== row.context ||\n String(record.context.expiresAtMillis) !== row.expiry ||\n (record._tag === \"Ready\" ? String(record.handoffExpiresAtMillis) : null) !== row.deadline\n )\n return yield* Unavailable.make({});\n\n return record;\n }, failure),\n insert: Effect.fnUntraced(function* (namespace, record) {\n yield* standalone;\n if (record._tag !== \"Pending\") return yield* Unavailable.make({});\n const payload = yield* Schema.encodeEffect(codec)(record);\n const context = yield* Schema.encodeEffect(contextCodec)(record.context);\n\n const rows = yield* sql`INSERT INTO ${name}\n (${column(\"namespace\")}, ${column(\"flowId\")}, ${column(\"version\")}, ${column(\"stage\")},\n ${column(\"context\")}, ${column(\"expiresAtMillis\")}, ${column(\"payload\")})\n SELECT ${namespace}, ${record.context.id}, ${record.version}, ${record._tag},\n ${context}, ${record.context.expiresAtMillis}, ${payload}\n WHERE ${record.context.expiresAtMillis} > ${clock}\n ON CONFLICT (${column(\"namespace\")}, ${column(\"flowId\")}) DO NOTHING\n RETURNING ${column(\"version\")}`;\n\n return rows.length === 1;\n }, failure),\n compareAndSet: Effect.fnUntraced(function* (namespace, version, record) {\n yield* standalone;\n if (version === record.version || record._tag === \"Pending\")\n return yield* Unavailable.make({});\n\n // Explicitly omit private envelopes from both irreversible marker stages.\n const payload = yield* Schema.encodeEffect(codec)(\n record._tag === \"Ready\"\n ? record\n : { _tag: record._tag, version: record.version, context: record.context },\n );\n\n const context = yield* Schema.encodeEffect(contextCodec)(record.context);\n\n const previous =\n record._tag === \"Exchanging\" ? \"Pending\" : record._tag === \"Ready\" ? \"Exchanging\" : \"Ready\";\n\n const deadline = record._tag === \"Ready\" ? record.handoffExpiresAtMillis : null;\n\n const consume =\n record._tag === \"Consumed\"\n ? sql`AND ${column(\"handoffExpiresAtMillis\")} > ${clock}`\n : sql.literal(\"\");\n\n const rows = yield* sql`UPDATE ${name}\n SET ${column(\"version\")} = ${record.version}, ${column(\"stage\")} = ${record._tag},\n ${column(\"handoffExpiresAtMillis\")} = ${deadline}, ${column(\"payload\")} = ${payload}\n WHERE ${column(\"namespace\")} = ${namespace} AND ${column(\"flowId\")} = ${record.context.id}\n AND ${column(\"version\")} = ${version} AND ${column(\"stage\")} = ${previous}\n AND ${column(\"context\")} = ${context}\n AND ${column(\"expiresAtMillis\")} = ${record.context.expiresAtMillis}\n AND ${column(\"expiresAtMillis\")} > ${clock} ${consume}\n RETURNING ${column(\"version\")}`;\n\n return rows.length === 1;\n }, failure),\n });\n});\n\nconst layer = Layer.effect(\n Persistence,\n makeOAuthProxyPersistence({ name: \"yielded_oauth_proxy\", columns: oauthProxyColumns }),\n);\n\nexport const OAuthProxyPersistence = { migration, layer };\n"],"mappings":"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"}
|
|
@@ -9,9 +9,9 @@ import "./flow.mjs";
|
|
|
9
9
|
import { TransactionCoordinatorError, TransactionExecution, TransactionTargetConfiguration } from "../transaction-execution-kernel.mjs";
|
|
10
10
|
import "./registration-ceremony.mjs";
|
|
11
11
|
import { Crypto, Effect, Schema } from "effect";
|
|
12
|
+
import { Statement } from "effect/sql/Statement";
|
|
12
13
|
import { PasskeyConfigurationError, PasskeyPersistence, PasskeyUnavailable, PreparePasskeyCommit } from "@yielded/auth/Passkey";
|
|
13
14
|
import { LifecycleHooks, PreparedCommit } from "@yielded/auth/Hooks";
|
|
14
|
-
import { Statement } from "effect/sql/Statement";
|
|
15
15
|
//#region src/internal/passkey/target.d.ts
|
|
16
16
|
export type PasskeyTargetConfiguration = TransactionTargetConfiguration<PasskeyUnavailable>;
|
|
17
17
|
export type PasskeyCoordinatorError<E> = TransactionCoordinatorError<E, PasskeyUnavailable> | PasskeyConfigurationError | PersistenceMappingError;
|
|
@@ -4374,8 +4374,8 @@ export declare const makePasskeyKernel: (operations: QueryOperations) => {
|
|
|
4374
4374
|
readonly ceremony: import("@yielded/auth/Passkey").PasskeyCeremony;
|
|
4375
4375
|
readonly claimId: string;
|
|
4376
4376
|
}) => import("effect/Effect").Effect<{
|
|
4377
|
-
readonly claim?: never;
|
|
4378
4377
|
readonly _tag: "Rejected";
|
|
4378
|
+
readonly claim?: never;
|
|
4379
4379
|
} | {
|
|
4380
4380
|
readonly _tag: "Claimed";
|
|
4381
4381
|
readonly claim: {
|
|
@@ -5635,7 +5635,7 @@ export declare const makePasskeyKernel: (operations: QueryOperations) => {
|
|
|
5635
5635
|
readonly nowMillis: number;
|
|
5636
5636
|
}) => import("effect/Effect").Effect<{
|
|
5637
5637
|
readonly _tag: "Rejected";
|
|
5638
|
-
|
|
5638
|
+
credential?: never;
|
|
5639
5639
|
} | {
|
|
5640
5640
|
readonly _tag: "Enrolled";
|
|
5641
5641
|
readonly credential: {
|
|
@@ -5706,7 +5706,6 @@ export declare const makePasskeyKernel: (operations: QueryOperations) => {
|
|
|
5706
5706
|
readonly _tag: "Rejected";
|
|
5707
5707
|
readonly decision?: never;
|
|
5708
5708
|
} | {
|
|
5709
|
-
readonly credential?: never;
|
|
5710
5709
|
readonly _tag: "Replay";
|
|
5711
5710
|
readonly result: {
|
|
5712
5711
|
readonly credentialId: string;
|
|
@@ -5718,8 +5717,8 @@ export declare const makePasskeyKernel: (operations: QueryOperations) => {
|
|
|
5718
5717
|
};
|
|
5719
5718
|
readonly replayed: true;
|
|
5720
5719
|
};
|
|
5720
|
+
credential?: never;
|
|
5721
5721
|
} | {
|
|
5722
|
-
readonly result?: never;
|
|
5723
5722
|
readonly _tag: "Target";
|
|
5724
5723
|
readonly credential: {
|
|
5725
5724
|
readonly credentialId: string;
|
|
@@ -5757,6 +5756,7 @@ export declare const makePasskeyKernel: (operations: QueryOperations) => {
|
|
|
5757
5756
|
readonly counter: number;
|
|
5758
5757
|
readonly maximumCounter: number;
|
|
5759
5758
|
};
|
|
5759
|
+
result?: never;
|
|
5760
5760
|
}, import("@yielded/auth/Passkey").PasskeyUnavailable | import("effect/PlatformError").PlatformError, import("effect/Crypto").Crypto | CurrentPasskeyTransaction>;
|
|
5761
5761
|
removeCredential: (mapping: any, input: {
|
|
5762
5762
|
readonly moduleId: string;
|
|
@@ -5784,8 +5784,8 @@ export declare const makePasskeyKernel: (operations: QueryOperations) => {
|
|
|
5784
5784
|
readonly replayed: true;
|
|
5785
5785
|
};
|
|
5786
5786
|
} | {
|
|
5787
|
-
readonly result?: never;
|
|
5788
5787
|
readonly _tag: "LastSignInMethod";
|
|
5788
|
+
result?: never;
|
|
5789
5789
|
} | {
|
|
5790
5790
|
readonly _tag: "Removed";
|
|
5791
5791
|
readonly result: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PersistenceConfigurationError } from "./configuration.mjs";
|
|
2
|
-
import { digest } from "./crypto.mjs";
|
|
3
2
|
import { PersistenceMappingError } from "./mapping-error.mjs";
|
|
3
|
+
import { digest } from "./crypto.mjs";
|
|
4
4
|
import { requiredPasskeyCredentialConstraints, requiredPasskeyPersistenceConstraints } from "./models/passkey-model.mjs";
|
|
5
5
|
import { requiredPasskeyManagementConstraints } from "./models/passkey-write-model.mjs";
|
|
6
6
|
import { requireStandalone } from "./standalone.mjs";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "./transaction-kernel.mjs";
|
|
2
|
+
import "./models/password-model.mjs";
|
|
3
|
+
import "./native-sql-table.mjs";
|
|
4
|
+
import "./password-kernel.mjs";
|
|
5
|
+
import { Effect, Option, Redacted } from "effect";
|
|
6
|
+
import { EncodedPasswordHash, PasswordCredentialSnapshot, PasswordUnavailable } from "@yielded/auth/Password";
|
|
7
|
+
import { LoginIdentifier } from "@yielded/auth/Identity";
|
|
8
|
+
//#region src/internal/password-credentials.d.ts
|
|
9
|
+
export declare const samePasswordCredentialSnapshot: (a: PasswordCredentialSnapshot, b: PasswordCredentialSnapshot) => boolean;
|
|
10
|
+
//#endregion
|
|
11
|
+
//# sourceMappingURL=password-credentials.d.mts.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { sqlMapping } from "./native-sql-table.mjs";
|
|
2
|
+
import { NativeDatabase } from "./transaction-kernel.mjs";
|
|
3
|
+
import { Effect, Option, Redacted, Schema } from "effect";
|
|
4
|
+
import { CurrentCommitJournal, hasCommitScope } from "@yielded/auth/Hooks";
|
|
5
|
+
import { reportPersistenceFailure } from "@yielded/auth/Persistence";
|
|
6
|
+
import { EncodedPasswordHash, PasswordUnavailable, snapshotPasswordCredential } from "@yielded/auth/Password";
|
|
7
|
+
//#region src/internal/password-credentials.ts
|
|
8
|
+
const unavailable = () => PasswordUnavailable.make({});
|
|
9
|
+
const failure = (effect) => reportPersistenceFailure(effect, Schema.is(PasswordUnavailable)).pipe(Effect.mapError(unavailable));
|
|
10
|
+
const samePasswordCredentialSnapshot = (a, b) => a.moduleId === b.moduleId && a.revision.subjectId === b.revision.subjectId && a.revision.securityRevision === b.revision.securityRevision && a.revision.credentials.length === b.revision.credentials.length && new Set(a.revision.credentials.map((entry) => entry.credentialId)).size === a.revision.credentials.length && new Set(b.revision.credentials.map((entry) => entry.credentialId)).size === b.revision.credentials.length && a.revision.credentials.every((entry) => b.revision.credentials.some((other) => entry.credentialId === other.credentialId && entry.revision === other.revision)) && a.credentialId === b.credentialId && a.credentialRevision === b.credentialRevision && a.verifierVersion === b.verifierVersion && Redacted.value(a.verifier) === Redacted.value(b.verifier) && a.normalization === b.normalization && a.identifier.namespace === b.identifier.namespace && a.identifier.value === b.identifier.value && a.identifierBindingRevision === b.identifierBindingRevision && a.identifierVerifiedAtMillis === b.identifierVerifiedAtMillis;
|
|
11
|
+
/** Lookup is read-only; rehash is one conditional maintenance write, never authentication. */
|
|
12
|
+
const makePasswordCredentials = Effect.fnUntraced(function* (table, mapping, options) {
|
|
13
|
+
const sql = (yield* NativeDatabase).$client.withoutTransforms();
|
|
14
|
+
const parent = yield* Effect.serviceOption(CurrentCommitJournal);
|
|
15
|
+
const [s, i, c] = yield* sqlMapping(() => [
|
|
16
|
+
table(mapping.subject.table),
|
|
17
|
+
table(mapping.identifier.table),
|
|
18
|
+
table(mapping.credential.table)
|
|
19
|
+
]).pipe(failure);
|
|
20
|
+
const standalone = Effect.gen(function* () {
|
|
21
|
+
if (options.coordinated) {
|
|
22
|
+
const current = yield* Effect.serviceOption(CurrentCommitJournal);
|
|
23
|
+
if (Option.isNone(parent) || Option.isNone(current) || parent.value !== current.value) return yield* unavailable();
|
|
24
|
+
} else {
|
|
25
|
+
if (yield* hasCommitScope) return yield* unavailable();
|
|
26
|
+
yield* options.standaloneGuard;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const allocate = (asynchronous, sync) => {
|
|
30
|
+
if (options.mode !== "synchronous" && asynchronous !== void 0) return asynchronous;
|
|
31
|
+
return sync === void 0 ? Effect.fail(unavailable()) : Effect.try({
|
|
32
|
+
try: sync,
|
|
33
|
+
catch: unavailable
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
const snapshot = Effect.fnUntraced(function* (nativeId, moduleId, identifier) {
|
|
37
|
+
const subjectTable = s.as("password_subject");
|
|
38
|
+
const identifierTable = i.as("password_identifier");
|
|
39
|
+
const credentialTable = c.as("password_credential");
|
|
40
|
+
const rows = yield* sqlMapping(() => sql`select ${subjectTable.fields("subject_")}, ${identifierTable.fields("identifier_")}, ${credentialTable.fields("credential_")}
|
|
41
|
+
from ${subjectTable.name}
|
|
42
|
+
inner join ${identifierTable.name} on ${identifierTable.column(mapping.identifier.namespace)} = ${identifierTable.value(mapping.identifier.namespace, identifier.namespace)}
|
|
43
|
+
and ${identifierTable.column(mapping.identifier.value)} = ${identifierTable.value(mapping.identifier.value, identifier.value)}
|
|
44
|
+
and ${identifierTable.column(mapping.identifier.subjectId)} = ${identifierTable.value(mapping.identifier.subjectId, nativeId)}
|
|
45
|
+
inner join ${credentialTable.name} on ${credentialTable.column(mapping.credential.moduleId)} = ${credentialTable.value(mapping.credential.moduleId, moduleId)}
|
|
46
|
+
and ${credentialTable.column(mapping.credential.subjectId)} = ${credentialTable.value(mapping.credential.subjectId, nativeId)}
|
|
47
|
+
where ${subjectTable.column(mapping.subject.id)} = ${subjectTable.value(mapping.subject.id, nativeId)}
|
|
48
|
+
`).pipe(Effect.flatten);
|
|
49
|
+
if (rows.length !== 1) return void 0;
|
|
50
|
+
const [subject, identifierRow, credential] = yield* sqlMapping(() => [
|
|
51
|
+
s.decode(rows[0], "subject_"),
|
|
52
|
+
i.decode(rows[0], "identifier_"),
|
|
53
|
+
c.decode(rows[0], "credential_")
|
|
54
|
+
]);
|
|
55
|
+
if (yield* sqlMapping(() => !mapping.subject.isActiveStatus(subject[mapping.subject.status]) || !mapping.identifier.isCurrent(identifierRow) || !mapping.subjectId.equals(nativeId, identifierRow[mapping.identifier.subjectId]) || !mapping.subjectId.equals(nativeId, subject[mapping.subject.id]) || !mapping.subjectId.equals(nativeId, credential[mapping.credential.subjectId]))) return void 0;
|
|
56
|
+
return yield* sqlMapping(() => mapping.credential.decode({
|
|
57
|
+
moduleId,
|
|
58
|
+
subject,
|
|
59
|
+
identifier: identifierRow,
|
|
60
|
+
credential
|
|
61
|
+
})).pipe(Effect.flatten, Effect.flatMap(snapshotPasswordCredential));
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
findCredential: (uncaptured) => Effect.gen(function* () {
|
|
65
|
+
const input = {
|
|
66
|
+
...uncaptured,
|
|
67
|
+
identifier: { ...uncaptured.identifier }
|
|
68
|
+
};
|
|
69
|
+
yield* standalone;
|
|
70
|
+
const identifiers = yield* sqlMapping(() => sql`select ${i.fields("i_")} from ${i.name}
|
|
71
|
+
where ${i.column(mapping.identifier.namespace)} = ${i.value(mapping.identifier.namespace, input.identifier.namespace)}
|
|
72
|
+
and ${i.column(mapping.identifier.value)} = ${i.value(mapping.identifier.value, input.identifier.value)}`).pipe(Effect.flatten);
|
|
73
|
+
const identifier = identifiers.length === 1 ? yield* sqlMapping(() => i.decode(identifiers[0], "i_")) : void 0;
|
|
74
|
+
if (identifier === void 0 || !(yield* sqlMapping(() => mapping.identifier.isCurrent(identifier)))) return Option.none();
|
|
75
|
+
const credential = yield* snapshot(identifier[mapping.identifier.subjectId], input.moduleId, input.identifier);
|
|
76
|
+
return credential === void 0 || input.subjectId !== void 0 && credential.revision.subjectId !== input.subjectId ? Option.none() : Option.some(credential);
|
|
77
|
+
}).pipe(failure),
|
|
78
|
+
rehashIfCurrent: (input) => Effect.gen(function* () {
|
|
79
|
+
const nextVerifier = Redacted.make(yield* Schema.decodeEffect(EncodedPasswordHash)(Redacted.value(input.nextVerifier)));
|
|
80
|
+
const credential = yield* snapshotPasswordCredential(input.credential);
|
|
81
|
+
yield* standalone;
|
|
82
|
+
const nativeId = yield* mapping.subjectId.toNative(credential.revision.subjectId);
|
|
83
|
+
const version = yield* allocate(mapping.allocateRevision, mapping.allocateRevisionSync);
|
|
84
|
+
if (version === credential.verifierVersion) return yield* unavailable();
|
|
85
|
+
yield* sqlMapping(() => {
|
|
86
|
+
const encoded = mapping.credential.encodeVerifier(nextVerifier, version);
|
|
87
|
+
const values = {
|
|
88
|
+
[mapping.credential.verifier]: encoded[mapping.credential.verifier],
|
|
89
|
+
[mapping.credential.verifierVersion]: encoded[mapping.credential.verifierVersion]
|
|
90
|
+
};
|
|
91
|
+
if (Object.values(values).some((value) => value === void 0)) throw unavailable();
|
|
92
|
+
const exact = sql.and(Object.entries({
|
|
93
|
+
[mapping.credential.moduleId]: credential.moduleId,
|
|
94
|
+
[mapping.credential.subjectId]: nativeId,
|
|
95
|
+
[mapping.credential.credentialId]: credential.credentialId,
|
|
96
|
+
[mapping.credential.credentialRevision]: credential.credentialRevision,
|
|
97
|
+
[mapping.credential.verifierVersion]: credential.verifierVersion,
|
|
98
|
+
[mapping.credential.verifier]: Redacted.value(credential.verifier),
|
|
99
|
+
[mapping.credential.normalization]: credential.normalization
|
|
100
|
+
}).map(([key, value]) => {
|
|
101
|
+
const column = c.column(key), bound = c.value(key, value);
|
|
102
|
+
if (typeof value !== "string") return sql`${column} = ${bound}`;
|
|
103
|
+
return sql.onDialectOrElse({
|
|
104
|
+
mysql: () => sql`binary ${column} = binary ${bound}`,
|
|
105
|
+
pg: () => sql`convert_to(cast(${column} as text), 'UTF8') = convert_to(cast(${bound} as text), 'UTF8')`,
|
|
106
|
+
orElse: () => sql`cast(${column} as blob) = cast(${bound} as blob)`
|
|
107
|
+
});
|
|
108
|
+
}));
|
|
109
|
+
return sql`${c.update(values)}
|
|
110
|
+
where ${c.column(mapping.credential.moduleId)} = ${c.value(mapping.credential.moduleId, credential.moduleId)}
|
|
111
|
+
and ${c.column(mapping.credential.subjectId)} = ${c.value(mapping.credential.subjectId, nativeId)}
|
|
112
|
+
and ${c.column(mapping.credential.credentialId)} = ${c.value(mapping.credential.credentialId, credential.credentialId)}
|
|
113
|
+
and ${exact}`;
|
|
114
|
+
}).pipe(Effect.flatten);
|
|
115
|
+
}).pipe(failure)
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
//#endregion
|
|
119
|
+
export { makePasswordCredentials, samePasswordCredentialSnapshot };
|
|
120
|
+
|
|
121
|
+
//# sourceMappingURL=password-credentials.mjs.map
|