@ionite/redis-core 0.0.23 → 0.0.24-beta.20260907.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/dist/index.d.ts +4 -0
- package/dist/index.js +10 -10
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -300,8 +300,10 @@ declare class RedisCustomerStore<TExtended = Record<string, never>> implements C
|
|
|
300
300
|
private entityKey;
|
|
301
301
|
private idsSetKey;
|
|
302
302
|
private nameIndexKey;
|
|
303
|
+
private externalIdIndexKey;
|
|
303
304
|
get(sub: string): Promise<BaseCustomer<TExtended> | undefined>;
|
|
304
305
|
lookup(customer: BaseCustomer<TExtended>): Promise<BaseCustomer<TExtended> | undefined>;
|
|
306
|
+
getByExternalId(externalId: string): Promise<BaseCustomer<TExtended> | undefined>;
|
|
305
307
|
upsert(customer: BaseCustomer<TExtended>): Promise<BaseCustomer<TExtended>>;
|
|
306
308
|
delete(sub: string): Promise<number>;
|
|
307
309
|
list(options?: ListOptions3): Promise<ListResult3<BaseCustomer<TExtended>>>;
|
|
@@ -478,8 +480,10 @@ declare class RedisWorkloadIdentityStore<TExtended = Record<string, never>> impl
|
|
|
478
480
|
private entityKey;
|
|
479
481
|
private idsSetKey;
|
|
480
482
|
private clientIndexKey;
|
|
483
|
+
private externalIdIndexKey;
|
|
481
484
|
get(id: string): Promise<BaseWorkloadIdentity<TExtended> | undefined>;
|
|
482
485
|
lookup(identity: BaseWorkloadIdentity<TExtended>): Promise<BaseWorkloadIdentity<TExtended> | undefined>;
|
|
486
|
+
getByExternalId(externalId: string): Promise<BaseWorkloadIdentity<TExtended> | undefined>;
|
|
483
487
|
upsert(identity: BaseWorkloadIdentity<TExtended>): Promise<BaseWorkloadIdentity<TExtended>>;
|
|
484
488
|
delete(id: string): Promise<number>;
|
|
485
489
|
list(options?: ListOptions7): Promise<ListResult7<BaseWorkloadIdentity<TExtended>>>;
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{accessRefId as i,accessRootId as
|
|
1
|
+
import{accessRefId as i,accessRootId as aZ,assertRequiredSubjectType as VZ,list as BZ}from"@ionite/core";function E(Z){return typeof Z.runScript==="function"}async function m(Z,$,Q,Y){let W=Y?.ttlSeconds;if(E(Z)){let B=`local cur=redis.call('GET',KEYS[1])
|
|
2
2
|
if cur then if cur==ARGV[1] then return 'exists_identical' else return 'conflict' end end
|
|
3
3
|
${W!=null?"redis.call('SET',KEYS[1],ARGV[1],'EX',ARGV[2])":"redis.call('SET',KEYS[1],ARGV[1])"}
|
|
4
|
-
return 'created'`,U=W!=null?[Q,String(Math.max(1,Math.floor(W)))]:[Q],
|
|
4
|
+
return 'created'`,U=W!=null?[Q,String(Math.max(1,Math.floor(W)))]:[Q],J=String(await Z.runScript(B,[$],U));return J==="exists_identical"||J==="conflict"?J:"created"}let V=await Z.get($);if(V!=null)return V===Q?"exists_identical":"conflict";if(W!=null)await Z.setex($,Math.max(1,Math.floor(W)),Q);else await Z.set($,Q);return"created"}async function c(Z,$,Q,Y,W){if(!E(Z))return"unsupported";let V=W!=null&&W>0?Math.max(1,Math.floor(W)):void 0,B=`local cur=redis.call('GET',KEYS[1])
|
|
5
5
|
if not cur then return 'missing' end
|
|
6
6
|
if cur~=ARGV[1] then return 'retry' end
|
|
7
7
|
${V!=null?"redis.call('SET',KEYS[1],ARGV[2],'EX',ARGV[3])":"redis.call('SET',KEYS[1],ARGV[2],'KEEPTTL')"}
|
|
8
|
-
return 'ok'`,U=V!=null?[Q,Y,String(V)]:[Q,Y],
|
|
8
|
+
return 'ok'`,U=V!=null?[Q,Y,String(V)]:[Q,Y],J=String(await Z.runScript(B,[$],U));if(J==="missing"||J==="retry")return J;return"ok"}var p=500,lZ=`local ki=1
|
|
9
9
|
local ai=1
|
|
10
10
|
local C=tonumber(ARGV[ai]);ai=ai+1
|
|
11
11
|
for i=1,C do
|
|
@@ -43,11 +43,11 @@ for i=1,W do
|
|
|
43
43
|
redis.call('SREM',k,unpack(members))
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
-
return 'ok'`;class
|
|
46
|
+
return 'ok'`;class D{claims=[];writes=[];claimUnique(Z,$){return this.claims.push({key:Z,owner:$}),this}set(Z,$){return this.writes.push({op:"set",key:Z,value:$}),this}setex(Z,$,Q){return this.writes.push({op:"setex",key:Z,ttl:Math.max(1,Math.floor($)),value:Q}),this}del(Z){return this.writes.push({op:"del",key:Z}),this}sadd(Z,...$){if($.length>0)this.writes.push({op:"sadd",key:Z,members:$});return this}srem(Z,...$){if($.length>0)this.writes.push({op:"srem",key:Z,members:$});return this}async exec(Z){if(E(Z))return this.execLua(Z);return this.execSequential(Z)}async execLua(Z){if(this.claims.length>0||this.writes.length<=p)return ZZ(Z,this.claims,this.writes);for(let $=0;$<this.writes.length;$+=p)await ZZ(Z,[],this.writes.slice($,$+p));return"ok"}async execSequential(Z){for(let $ of this.claims){let Q=await Z.get($.key);if(Q!=null&&Q!==$.owner)return"conflict"}for(let $ of this.writes)switch($.op){case"set":await Z.set($.key,$.value);break;case"setex":await Z.setex($.key,$.ttl,$.value);break;case"del":await Z.del($.key);break;case"sadd":await Z.sadd($.key,...$.members);break;case"srem":await Z.srem($.key,...$.members);break}return"ok"}}async function ZZ(Z,$,Q){let Y=[],W=[String($.length)];for(let G of $)Y.push(G.key),W.push(G.owner);W.push(String(Q.length));for(let G of Q)switch(G.op){case"set":W.push("set"),Y.push(G.key),W.push(G.value);break;case"setex":W.push("setex"),Y.push(G.key),W.push(String(G.ttl),G.value);break;case"del":W.push("del"),Y.push(G.key);break;case"sadd":W.push("sadd"),Y.push(G.key),W.push(String(G.members.length),...G.members);break;case"srem":W.push("srem"),Y.push(G.key),W.push(String(G.members.length),...G.members);break}return String(await Z.runScript(lZ,Y,W))==="conflict"?"conflict":"ok"}import{list as uZ,matchesListFilter as pZ}from"@ionite/core";var $Z=100,QZ=1000;function h(Z){let $=Z?.limit,Q=$==null||!Number.isFinite($)||$<=0?$Z:Math.min(Math.floor($),QZ);return{...Z,limit:Q}}function K(Z,$,Q=(Y,W)=>Y[W]){let Y=Math.max(0,$?.start??0),W=$?.limit,V=$?.filter?Z.filter((J)=>pZ({requestable:Q(J,"requestable"),userName:Q(J,"userName"),clientId:Q(J,"clientId"),externalId:Q(J,"externalId"),updatedAt:Q(J,"updatedAt")},$.filter)):Z,G=V.length,B=W!=null?Y+W:void 0,U=V.slice(Y,B);return uZ(G,U,Y,W)}import{defaultLogger as cZ}from"@ionite/core";function L(Z,$){let Q=$.log??cZ,Y={"ion.operation":"redis.revive","ion.outcome":"corrupt",store:$.store,...$.key?{key:$.key}:{}},W;try{W=JSON.parse(Z)}catch{Q.warn("Redis store: discarded corrupt JSON payload (failed to parse)",Y);return}if(W===null||typeof W!=="object"||Array.isArray(W)){Q.warn("Redis store: discarded JSON payload that is not a record object",Y);return}return W}import{createHash as dZ}from"node:crypto";import{defaultLogger as iZ}from"@ionite/core";var oZ=4096,YZ=new Set,WZ=new Set;function GZ(Z,$){Z.delete($),Z.add($);while(Z.size>oZ){let Q=Z.values().next().value;if(Q===void 0)break;Z.delete(Q)}}function _(Z,$){let Q=Z.keyPrefix;if(typeof Q!=="string"||Q.length===0)throw Error('Redis store keyPrefix is required and must be a non-empty string. Pass an explicit per-tenant prefix (e.g. "ion:t:<tenantId>:") so tenant keyspaces never collide.');if($){let Y=`${$}\x00${Q}`;if(YZ.has(Y)&&!WZ.has(Y))F(Z).warn(`Redis ${$} constructed twice with the same keyPrefix "${Q}". Each tenant MUST use a distinct keyPrefix (e.g. "ion:t:<tenantId>:") so tenant keyspaces never collide; sharing a prefix across tenants lets them read/write each other's data.`),GZ(WZ,Y);GZ(YZ,Y)}return Q}function F(Z){return Z.logger??iZ}function C(Z,...$){return Z+$.join(":")}var nZ=/^[A-Za-z0-9_.@|-]{1,64}$/;function X(Z){if(nZ.test(Z))return`=${Z}`;return`#${dZ("sha256").update(Z,"utf8").digest("base64url").slice(0,22)}`}var sZ="access:ids",rZ="access:subject:",tZ="access:target:";function eZ(Z){return JSON.stringify({...Z,createdAt:Z.createdAt.toISOString(),updatedAt:Z.updatedAt.toISOString()})}function d(Z,$){let Q=L(Z,{store:"access",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt),updatedAt:new Date(Q.updatedAt)}}function UZ(Z){return{id:Z.id,subject:Z.subject,subjectType:Z.subjectType,targetType:Z.targetType,target:Z.target,resources:Z.resources,applyToApplication:Z.applyToApplication,provenance:Z.provenance,status:Z.status,metadata:Z.metadata}}function HZ(Z){let $=i(Z.subject),Q=i(Z.target);if(!$)throw Error("Access change subject must resolve to a non-empty id.");if(!Z.targetType)throw Error("Access change targetType is required.");if(!Q)throw Error("Access change target must resolve to a non-empty id.");return{id:Z.id??aZ(Z),subjectId:$,targetId:Q}}class JZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"access-assignment-store"),this.log=F(Z)}key(...Z){return C(this.prefix,...Z)}idsSetKey(){return this.key(sZ)}accessStorageKey(Z){return this.key("access",X(Z))}subjectIndexKey(Z,$){return this.key(`${rZ}${$}:${X(Z)}`)}targetIndexKey(Z,$){return this.key(tZ+Z,X($))}async grant(Z){VZ(Z.subjectType,"Access change subjectType");let $=HZ(Z),Q=this.accessStorageKey($.id),Y=await this.redis.get(Q),W=Y?d(Y,this.log):void 0,V=new Date,G={...Z,id:$.id,status:Z.status??"active",subjectId:$.subjectId,targetId:$.targetId,createdAt:W?.createdAt??V,updatedAt:V},B=new D;B.set(Q,eZ(G)),B.sadd(this.idsSetKey(),$.id),B.sadd(this.subjectIndexKey($.subjectId,Z.subjectType),$.id),B.sadd(this.targetIndexKey(Z.targetType,$.targetId),$.id),await B.exec(this.redis)}async revoke(Z){let $=HZ(Z);if(await this.redis.get(this.accessStorageKey($.id))==null)return;let Y=new D;Y.del(this.accessStorageKey($.id)),Y.srem(this.idsSetKey(),$.id),Y.srem(this.subjectIndexKey($.subjectId,Z.subjectType),$.id),Y.srem(this.targetIndexKey(Z.targetType,$.targetId),$.id),await Y.exec(this.redis)}async get(Z){let $=await this.redis.get(this.accessStorageKey(Z));if($==null)return;let Q=d($,this.log);return Q?UZ(Q):void 0}async list(Z){return this.listInMemory(h(Z))}async listByTarget(Z,$,Q){let Y=await this.redis.smembers(this.targetIndexKey(Z,$.trim()));return this.listFromIds(Y,Q)}async listBySubject(Z,$,Q){VZ($);let Y=i(Z);if(!Y)return BZ(0,[],Q?.start??0,Q?.limit);let W=await this.redis.smembers(this.subjectIndexKey(Y,$));return this.listFromIds(W,Q)}async listInMemory(Z){let $=await this.redis.smembers(this.idsSetKey());return this.listFromIds($,Z)}async listFromIds(Z,$){if(Z.length===0)return BZ(0,[],$?.start??0,$?.limit);let Y=[...Z].sort().map((B)=>this.accessStorageKey(B)),V=(await this.redis.mget(Y)).filter((B)=>B!=null).map((B)=>d(B,this.log)).filter((B)=>B!=null).filter((B)=>(B.status??"active")==="active"),G=K(V,$);return{...G,items:G.items.map(UZ)}}}import{assertValidSubjectTypeScoping as MZ,deepEqualPlain as Z$,readyCatalogEntry as OZ}from"@ionite/core";class zZ{groups;roles;permissions;listeners=new Set;constructor(Z){let $=Z.redis,Q=_(Z,"access-catalog-store"),Y=F(Z),W=(V)=>{for(let G of this.listeners)G(V)};this.groups=new I($,Q,"group",W,Y),this.roles=new I($,Q,"role",W,Y),this.permissions=new I($,Q,"permission",W,Y)}afterChange(Z){return this.listeners.add(Z),()=>{this.listeners.delete(Z)}}}class XZ{redis;prefix;log;listeners=new Set;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"resource-store"),this.log=F(Z)}key(...Z){return C(this.prefix,"authz","resource",...Z)}entityKey(Z){return this.key(X(Z))}idsSetKey(){return this.key("ids")}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;let Q=L($,{store:"authz:resource",key:Z,log:this.log});return Q===void 0?void 0:Q}async list(Z){let $=await this.redis.smembers(this.idsSetKey());if($.length===0)return K([],Z);let Y=(await this.redis.mget($.map((W)=>this.entityKey(W)))).filter((W)=>W!=null).map((W)=>L(W,{store:"authz:resource",log:this.log})).filter((W)=>W!==void 0).map((W)=>W);return K(Y,Z)}async children(Z){return(await this.list()).items.filter((Q)=>{return(typeof Q.parent==="string"?Q.parent:Q.parent?.id)===Z})}changed(Z){return this.listeners.add(Z),()=>{this.listeners.delete(Z)}}async set(Z){await new D().set(this.entityKey(Z.id),JSON.stringify(Z)).sadd(this.idsSetKey(),Z.id).exec(this.redis),this.emitChange({id:Z.id})}async delete(Z){await new D().del(this.entityKey(Z)).srem(this.idsSetKey(),Z).exec(this.redis),this.emitChange({id:Z,deleted:!0})}emitChange(Z){for(let $ of this.listeners)$(Z)}}class I{redis;prefix;kind;emit;log;constructor(Z,$,Q,Y,W){this.redis=Z;this.prefix=$;this.kind=Q;this.emit=Y;this.log=W}key(...Z){return C(this.prefix,"authz",this.kind,...Z)}idsSetKey(){return this.key("ids")}entityKey(Z){return this.key(X(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;let Q=L($,{store:`authz:${this.kind}`,key:Z,log:this.log});return Q===void 0?void 0:Q}set(Z){MZ(Z);let $,Q=!0,Y=(async()=>{$=await this.get(Z.id),Q=!$||!Z$($,Z);let W=new D;W.set(this.entityKey(Z.id),JSON.stringify(Z)),W.sadd(this.idsSetKey(),Z.id),await W.exec(this.redis)})();return Y.then(()=>{if(!Q)return;this.emit({op:"set",kind:this.kind,entity:Z,previous:$})},(W)=>{this.log?.warn("authz catalog store: background persist failed",{"ion.operation":`authz.catalog.${this.kind}.set`,"ion.outcome":"error",id:Z.id,error:W instanceof Error?W.message:String(W)})}),OZ(Z,Y)}insertIfAbsent(Z){MZ(Z);let $={...Z},Q=!1,Y=(async()=>{if(!E(this.redis))throw Error("RedisAccessCatalogStore.insertIfAbsent requires a Redis adapter with runScript support.");let W=JSON.stringify(Z),V=await this.redis.runScript(`local cur=redis.call('GET',KEYS[1])
|
|
47
47
|
if cur then return {0,cur} end
|
|
48
48
|
redis.call('SET',KEYS[1],ARGV[1])
|
|
49
49
|
redis.call('SADD',KEYS[2],ARGV[2])
|
|
50
|
-
return {1,ARGV[1]}`,[this.entityKey(Z.id),this.idsSetKey()],[W,Z.id]);if(!Array.isArray(V)||V.length<2)throw Error("RedisAccessCatalogStore.insertIfAbsent received an invalid Redis response.");Q=String(V[0])==="1";let G=String(V[1]),B=L(G,{store:`authz:${this.kind}`,key:Z.id,log:this.log});if(!B)throw Error("RedisAccessCatalogStore.insertIfAbsent could not parse the winning row.");let U=$;for(let
|
|
50
|
+
return {1,ARGV[1]}`,[this.entityKey(Z.id),this.idsSetKey()],[W,Z.id]);if(!Array.isArray(V)||V.length<2)throw Error("RedisAccessCatalogStore.insertIfAbsent received an invalid Redis response.");Q=String(V[0])==="1";let G=String(V[1]),B=L(G,{store:`authz:${this.kind}`,key:Z.id,log:this.log});if(!B)throw Error("RedisAccessCatalogStore.insertIfAbsent could not parse the winning row.");let U=$;for(let J of Object.keys(U))delete U[J];Object.assign(U,B)})();return Y.then(()=>{if(!Q)return;this.emit({op:"set",kind:this.kind,entity:$,previous:void 0})},(W)=>{this.log?.warn("authz catalog store: atomic insert-if-absent failed",{"ion.operation":`authz.catalog.${this.kind}.insert_if_absent`,"ion.outcome":"error",id:Z.id,error:W instanceof Error?W.message:String(W)})}),OZ($,Y)}async delete(Z){let $=await this.get(Z),Q=new D;if(Q.del(this.entityKey(Z)),Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),!$)return;this.emit({op:"delete",kind:this.kind,entity:$})}async list(Z){let $=await this.redis.smembers(this.idsSetKey());if($.length===0)return K([],Z);let Y=(await this.redis.mget($.map((W)=>this.entityKey(W)))).filter((W)=>W!=null).map((W)=>L(W,{store:`authz:${this.kind}`,log:this.log})).filter((W)=>W!==void 0).map((W)=>W);return K(Y,Z)}}import{accessRefId as R,assertRequiredSubjectType as w}from"@ionite/core";var y="__app__",qZ=100;function $$(Z){if(!Array.isArray(Z))return[];return Z.map(($)=>$==null?"":String($)).filter(($)=>$.length>0)}var Q$=`local rootId=ARGV[1]
|
|
51
51
|
local A=tonumber(ARGV[2])
|
|
52
52
|
local R=tonumber(ARGV[3])
|
|
53
53
|
local rootKey=KEYS[1]
|
|
@@ -96,7 +96,7 @@ for i=0,R-1 do
|
|
|
96
96
|
end
|
|
97
97
|
redis.call('SREM',rootKey,descriptor)
|
|
98
98
|
end
|
|
99
|
-
return 'ok'`,
|
|
99
|
+
return 'ok'`,Y$=`local rootId=ARGV[1]
|
|
100
100
|
local n=tonumber(ARGV[2])
|
|
101
101
|
for i=0,n-1 do
|
|
102
102
|
local kb=1+i*5
|
|
@@ -120,7 +120,7 @@ for i=0,n-1 do
|
|
|
120
120
|
end
|
|
121
121
|
end
|
|
122
122
|
redis.call('DEL',KEYS[1])
|
|
123
|
-
return 'ok'`,
|
|
123
|
+
return 'ok'`,W$=`local n=tonumber(ARGV[1])
|
|
124
124
|
local roots={}
|
|
125
125
|
local seen={}
|
|
126
126
|
for i=0,n-1 do
|
|
@@ -139,8 +139,8 @@ for i=0,n-1 do
|
|
|
139
139
|
redis.call('DEL',ak)
|
|
140
140
|
end
|
|
141
141
|
redis.call('DEL',KEYS[1])
|
|
142
|
-
return roots`,
|
|
143
|
-
return 'ok'`,
|
|
142
|
+
return roots`,G$=`for i=1,#KEYS do redis.call('DEL',KEYS[i]) end
|
|
143
|
+
return 'ok'`,V$=`local subjectMember=ARGV[1]
|
|
144
144
|
local C=tonumber(ARGV[2])
|
|
145
145
|
local R=tonumber(ARGV[3])
|
|
146
146
|
local D=tonumber(ARGV[4])
|
|
@@ -173,4 +173,4 @@ if D==0 then
|
|
|
173
173
|
else
|
|
174
174
|
redis.call('SADD',KEYS[2],subjectMember)
|
|
175
175
|
end
|
|
176
|
-
return 'ok'`;function w(Z,$){return`${$}:${Z}`}function b(Z){return Z&&Z.length>0?Z:g}function n(Z){return JSON.stringify([Z.subject,Z.targetType,Z.target,Z.rToken])}function j(Z){let $;try{$=JSON.parse(Z)}catch{$=[]}let[Q,Y,W,V]=Array.isArray($)?$:[];return{subject:Q??"",targetType:Y??"permission",target:W??"",rToken:V??g}}class zZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"access-index"),this.log=D(Z)}key(...Z){return C(this.prefix,...Z)}subjectKeyPart(Z){let $=Z.indexOf(":");if($<=0)return O(Z);return`${Z.slice(0,$)}:${O(Z.slice($+1))}`}hasKey(Z,$,Q,Y){return this.key("idx:has",this.subjectKeyPart(Z),$,O(Q),O(Y))}anyKey(Z,$,Q){return this.key("idx:any",this.subjectKeyPart(Z),$,O(Q))}edgeRootsKey(Z,$,Q,Y){return this.key("idx:er",this.subjectKeyPart(Z),$,O(Q),O(Y))}tripleKey(Z,$,Q){return this.key("idx:tr",this.subjectKeyPart(Z),$,O(Q))}rootKey(Z){return this.key("idx:root",O(Z))}subjectKey(Z){return this.key("idx:subj",this.subjectKeyPart(Z))}subjectsKey(){return this.key("idx:subjects")}disabledKey(Z){return this.key("idx:disabled",this.subjectKeyPart(Z))}async has(Z,$,Q,Y,W){T(W);let V=E(Z),G=E(Q);if(!V||!G)return{allow:!1};let B=w(V,W);if(Y===void 0){let[F,A]=await this.redis.mget([this.disabledKey(B),this.anyKey(B,$,G)]);if(F!=null)return{allow:!1,metadata:{reason:"subject_disabled"}};return A!=null?this.allow(V,W,$,G,void 0):{allow:!1}}let U=E(Y),M=await this.redis.mget([this.disabledKey(B),this.hasKey(B,$,G,b(U)),this.hasKey(B,$,G,g)]);if(M[0]!=null)return{allow:!1,metadata:{reason:"subject_disabled"}};if(M[1]!=null)return this.allow(V,W,$,G,U);if(M[2]!=null)return this.allow(V,W,$,G,void 0);return{allow:!1}}async hasGroup(Z,$,Q,Y){return this.has(Z,"group",$,Q,Y)}async hasRole(Z,$,Q,Y){return this.has(Z,"role",$,Q,Y)}async hasPermission(Z,$,Q,Y){return this.has(Z,"permission",$,Q,Y)}async hasAny(Z,$,Q){if($.length===0)return{allow:!1};this.warnLargeCheck("redis.access_index.has_any",$.length);let Y=await this.evaluateTargets(Z,$,Q);for(let W of Y)if(W.allow)return W;return{allow:!1}}async hasAll(Z,$,Q){if($.length===0){let V=E(Z);if(V){if(await this.redis.get(this.disabledKey(w(V,Q)))!=null)return{allow:!1,metadata:{reason:"subject_disabled"}}}return{allow:!0}}this.warnLargeCheck("redis.access_index.has_all",$.length);let Y=await this.evaluateTargets(Z,$,Q),W=[];for(let V of Y){if(!V.allow)return{allow:!1,matched:W};if(V.matched)W.push(...V.matched)}return{allow:!0,matched:W}}async evaluateTargets(Z,$,Q){let Y=E(Z);if(!Y)return $.map(()=>({allow:!1}));let W=w(Y,Q),V=[this.disabledKey(W)],G=$.map((U)=>{let M=E(U.target);if(!M)return{kind:"invalid"};if(U.resource===void 0){let P=V.push(this.anyKey(W,U.targetType,M))-1;return{kind:"any",targetType:U.targetType,targetId:M,idx:P}}let F=E(U.resource),A=V.push(this.hasKey(W,U.targetType,M,b(F)))-1,z=V.push(this.hasKey(W,U.targetType,M,g))-1;return{kind:"resource",targetType:U.targetType,targetId:M,resourceId:F,idxResource:A,idxApp:z}}),B=await this.redis.mget(V);if(B[0]!=null)return $.map(()=>({allow:!1,metadata:{reason:"subject_disabled"}}));return G.map((U)=>{if(U.kind==="invalid")return{allow:!1};if(U.kind==="any")return B[U.idx]!=null?this.allow(Y,Q,U.targetType,U.targetId,void 0):{allow:!1};if(B[U.idxResource]!=null)return this.allow(Y,Q,U.targetType,U.targetId,U.resourceId);if(B[U.idxApp]!=null)return this.allow(Y,Q,U.targetType,U.targetId,void 0);return{allow:!1}})}edgeKeys(Z){return[this.edgeRootsKey(Z.subject,Z.targetType,Z.target,Z.rToken),this.hasKey(Z.subject,Z.targetType,Z.target,Z.rToken),this.tripleKey(Z.subject,Z.targetType,Z.target),this.anyKey(Z.subject,Z.targetType,Z.target),this.subjectKey(Z.subject)]}async materialize(Z,$){let Q=new Map;for(let G of $){let B=E(G.subject),U=E(G.target);if(!B||!U)continue;T(G.subjectType,"Effective edge subjectType");let M=w(B,G.subjectType),F=b(G.resource),A={subject:M,targetType:G.targetType,target:U,rToken:F};Q.set(n(A),A)}let Y=new Set(await this.redis.smembers(this.rootKey(Z))),W=[];for(let[G,B]of Q)if(!Y.has(G))W.push({encoded:G,d:B});let V=[];for(let G of Y)if(!Q.has(G))V.push({encoded:G,d:j(G)});if(W.length===0&&V.length===0)return;if(R(this.redis)){let G=[this.rootKey(Z),this.subjectsKey()],B=[Z,String(W.length),String(V.length)];for(let{encoded:U,d:M}of W)G.push(...this.edgeKeys(M)),B.push(U,M.rToken,M.subject);for(let{encoded:U,d:M}of V)G.push(...this.edgeKeys(M)),B.push(U,M.rToken);await this.redis.runScript($$,G,B);return}for(let{encoded:G,d:B}of W)await this.redis.sadd(this.edgeRootsKey(B.subject,B.targetType,B.target,B.rToken),Z),await this.redis.set(this.hasKey(B.subject,B.targetType,B.target,B.rToken),"1"),await this.redis.sadd(this.tripleKey(B.subject,B.targetType,B.target),B.rToken),await this.redis.set(this.anyKey(B.subject,B.targetType,B.target),"1"),await this.redis.sadd(this.rootKey(Z),G),await this.redis.sadd(this.subjectKey(B.subject),G),await this.redis.sadd(this.subjectsKey(),B.subject);for(let{encoded:G,d:B}of V)await this.dropRootFromEdge(Z,B.subject,B.targetType,B.target,B.rToken),await this.redis.srem(this.rootKey(Z),G)}async replaceSubject(Z,$,Q){if(!R(this.redis))throw Error("RedisAccessIndex.replaceSubject requires an adapter with atomic runScript support.");let Y=E(Z);if(!Y)return;let W=w(Y,$),V=[];for(let z of Q){let P=E(z.subject);T(z.subjectType,"Effective edge subjectType");let v=z.subjectType;if(P!==Y||v!==$)throw Error(`AccessIndex.replaceSubject received an edge for ${v}:${P}; expected ${W}.`);let f=E(z.target);if(!f)continue;let S={subject:W,targetType:z.targetType,target:f,rToken:b(z.resource)};V.push({rootId:z.rootId,encoded:n(S),d:S})}let B=(await this.redis.smembers(this.subjectKey(W))).map(j),U=await Promise.all(B.map((z)=>this.redis.smembers(this.edgeRootsKey(z.subject,z.targetType,z.target,z.rToken)))),M=[...new Set(U.flat())],F=[this.subjectKey(W),this.subjectsKey()];for(let z of B){let[P,v,f,S]=this.edgeKeys(z);F.push(P,v,f,S)}for(let z of M)F.push(this.rootKey(z));for(let z of V){let[P,v,f,S]=this.edgeKeys(z.d);F.push(this.rootKey(z.rootId),P,v,f,S)}let A=[W,String(B.length),String(M.length),String(V.length)];for(let z of V)A.push(z.rootId,z.encoded,z.d.rToken);await this.redis.runScript(G$,F,A)}async removeByRoot(Z){let $=this.rootKey(Z),Q=await this.redis.smembers($);if(Q.length===0){await this.redis.del($);return}if(R(this.redis)){let Y=[$],W=[Z,String(Q.length)];for(let V of Q){let G=j(V);Y.push(...this.edgeKeys(G)),W.push(V,G.rToken)}await this.redis.runScript(Q$,Y,W);return}for(let Y of Q){let{subject:W,targetType:V,target:G,rToken:B}=j(Y);await this.dropRootFromEdge(Z,W,V,G,B)}await this.redis.del($)}async listSubjects(){let Z=await this.redis.smembers(this.subjectsKey()),$=[];for(let Q of Z){let Y=Q.indexOf(":");if(Y<=0)throw Error(`AccessIndex subject key "${Q}" is missing a subjectType prefix.`);let W=Q.slice(0,Y);T(W,"AccessIndex subject key subjectType"),$.push({subjectType:W,subject:Q.slice(Y+1)})}return $}async setSubjectDisabled(Z,$,Q){let Y=E(Z);if(!Y)return;let W=this.disabledKey(w(Y,$));if(Q)await this.redis.set(W,"1");else await this.redis.del(W)}async isSubjectDisabled(Z,$){T($);let Q=E(Z);if(!Q)return!1;return await this.redis.get(this.disabledKey(w(Q,$)))!=null}async clear(Z,$){if(Z===void 0){let W=await this.redis.smembers(this.subjectsKey());for(let V of W)await this.clearSubject(V);await this.redis.del(this.subjectsKey());return}T($);let Q=E(Z);if(!Q)return;let Y=w(Q,$);await this.clearSubject(Y),await this.redis.srem(this.subjectsKey(),Y)}async clearSubject(Z){let $=this.subjectKey(Z),Q=await this.redis.smembers($);if(Q.length===0){await this.redis.del($);return}if(R(this.redis)){let Y=[$];for(let V of Q){let{targetType:G,target:B,rToken:U}=j(V);Y.push(this.edgeRootsKey(Z,G,B,U),this.hasKey(Z,G,B,U),this.tripleKey(Z,G,B),this.anyKey(Z,G,B))}let W=Z$(await this.redis.runScript(Y$,Y,[String(Q.length)]));if(W.length>0)await this.redis.runScript(W$,W.map((V)=>this.rootKey(V)),[]);return}for(let Y of Q){let{targetType:W,target:V,rToken:G}=j(Y),B=this.edgeRootsKey(Z,W,V,G),U=await this.redis.smembers(B);for(let F of U)await this.redis.srem(this.rootKey(F),Y);if(await this.redis.del(B),await this.redis.del(this.hasKey(Z,W,V,G)),await this.redis.srem(this.tripleKey(Z,W,V),G),(await this.redis.smembers(this.tripleKey(Z,W,V))).length===0)await this.redis.del(this.tripleKey(Z,W,V)),await this.redis.del(this.anyKey(Z,W,V))}await this.redis.del($)}async dropRootFromEdge(Z,$,Q,Y,W){let V=this.edgeRootsKey($,Q,Y,W);if(await this.redis.srem(V,Z),(await this.redis.smembers(V)).length>0)return;await this.redis.del(V),await this.redis.del(this.hasKey($,Q,Y,W));let B=n({subject:$,targetType:Q,target:Y,rToken:W});if(await this.redis.srem(this.subjectKey($),B),await this.redis.srem(this.tripleKey($,Q,Y),W),(await this.redis.smembers(this.tripleKey($,Q,Y))).length===0)await this.redis.del(this.tripleKey($,Q,Y)),await this.redis.del(this.anyKey($,Q,Y))}allow(Z,$,Q,Y,W){return{allow:!0,matched:[{subject:Z,subjectType:$,targetType:Q,target:Y,resources:W?[W]:void 0}]}}warnLargeCheck(Z,$){if($<=OZ)return;this.log.warn("Redis access index check received a large bounded target set; issuing per-target reads.",{"ion.operation":Z,"ion.outcome":"degraded",count:$,threshold:OZ})}}var V$=512;async function B$(Z,$,Q=512){if(Z.length===0)return[];let Y=Q>0?Q:512,W=[];for(let V=0;V<Z.length;V+=Y){let G=await $(Z.slice(V,V+Y));for(let B of G)W.push(B??null)}return W}import{list as U$,StoreConflictError as H$}from"@ionite/core";var J$="customer:ids",M$="customer:name:";function X$(Z){let $=Z.createdAt??new Date,Q=Z.updatedAt??$,Y={...Z,createdAt:$.toISOString(),updatedAt:Q.toISOString()};if(Y.ciam&&typeof Y.ciam==="object"&&Y.ciam!==null){let W=Y.ciam;if(W.expires instanceof Date)W.expires=W.expires.toISOString()}return JSON.stringify(Y)}function o(Z,$){let Q=L(Z,{store:"customer",log:$});if(Q===void 0)return;if(Q.ciam&&typeof Q.ciam==="object"&&Q.ciam!==null){let Y=Q.ciam;if(typeof Y.expires==="string")Y.expires=new Date(Y.expires)}return{...Q,createdAt:typeof Q.createdAt==="string"?new Date(Q.createdAt):void 0,updatedAt:typeof Q.updatedAt==="string"?new Date(Q.updatedAt):void 0}}class DZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"customer-store"),this.log=D(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("customer",O(Z))}idsSetKey(){return this.key(J$)}nameIndexKey(Z){return this.key(M$+O(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return o($,this.log)}async lookup(Z){if(Z.id){let $=await this.get(Z.id);if($)return $}if(Z.userName){let $=await this.redis.get(this.nameIndexKey(Z.userName.toLowerCase()));if($!=null)return this.get($)}return}async upsert(Z){let $=Z.id?.trim()||crypto.randomUUID(),Q={...Z,id:$},Y=this.entityKey($),W=await this.redis.get(Y),V=W!=null?o(W,this.log)??null:null,G=Q.userName?.toLowerCase(),B=V?.userName?.toLowerCase(),U=new q;if(G)U.claimUnique(this.nameIndexKey(G),$);if(B&&B!==G)U.del(this.nameIndexKey(B));if(U.set(Y,X$(Q)),G)U.set(this.nameIndexKey(G),$);if(U.sadd(this.idsSetKey(),$),await U.exec(this.redis)==="conflict")throw new H$(`userName "${Q.userName}" is already in use`,"unique_violation","userName");return Q}async delete(Z){let $=await this.get(Z);if($==null)return 0;let Q=new q;if(Q.del(this.entityKey(Z)),$.userName)Q.del(this.nameIndexKey($.userName.toLowerCase()));return Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),1}async list(Z){let $=h(Z),Q=(await this.redis.smembers(this.idsSetKey())).sort();if(Q.length===0)return U$(0,[],$.start??0,$.limit);let Y=Q.map((G)=>this.entityKey(G)),V=(await this.redis.mget(Y)).filter((G)=>G!=null).map((G)=>o(G,this.log)).filter((G)=>G!=null);return K(V,$)}}import{createHash as F$}from"node:crypto";function qZ(Z){return F$("sha1").update(Z,"utf8").digest("hex")}function O$(Z){return(Z instanceof Error?Z.message:String(Z)).includes("NOSCRIPT")}function z$(Z){let $=new Map;return async(Q,Y,W)=>{let V=$.get(Q);if(!V)V=qZ(Q),$.set(Q,V);try{return await Z.evalsha(V,Y,W)}catch(G){if(O$(G))return Z.eval(Q,Y,W);throw G}}}function LZ(Z){return typeof Z==="object"&&Z!==null&&!Array.isArray(Z)}function D$(Z){let $=LZ(Z.clientOptions)?{...Z.clientOptions}:LZ(Z)?{...Z}:{};return delete $.redisUrl,delete $.clientOptions,{redisUrl:(typeof Z.redisUrl==="string"?Z.redisUrl.trim():"")||void 0,clientOptions:$}}import{defaultLogger as q$}from"@ionite/core";function _Z(Z,$){return`${Z}:${encodeURIComponent($)}`}function L$(Z,$){if(typeof Z!=="object"||Z===null||Array.isArray(Z))return!1;let Q=Z,Y=Q.headers;return Q.kind==="delivery"&&typeof Q.key==="string"&&typeof Q.rawBody==="string"&&typeof Y==="object"&&Y!==null&&Y.requestId===$&&typeof Y.keyId==="string"&&typeof Y.signature==="string"}function _$(Z,$={}){if(!Z.getdel)throw Error("Redis adapter must implement getdel() for LFV callback coordination");let Q=Z.getdel.bind(Z),Y=$.channelPrefix?.trim()||"ionite:lfv:otp",W=$.logger??q$;return{async put(V,G,B){if(G.kind!=="delivery"||G.headers.requestId!==V)throw Error("LFV callback mailbox only accepts matching delivery envelopes");let U=Math.max(1,Math.ceil(B/1000));await Z.setex(_Z(Y,V),U,JSON.stringify(G))},async take(V){let G=await Q(_Z(Y,V));if(G==null)return;let B;try{B=JSON.parse(G)}catch(U){W.warn("Invalid JSON received from LFV Redis callback mailbox",{"ion.operation":"lfv.callback.redis.take","ion.outcome":"rejected",requestId:V,error:U instanceof Error?U.message:String(U)});return}if(!L$(B,V)){W.warn("Invalid envelope received from LFV Redis callback mailbox",{"ion.operation":"lfv.callback.redis.take","ion.outcome":"rejected",requestId:V});return}return B}}}import{StoreConflictError as C$}from"@ionite/core";function N$(Z){return JSON.stringify({token:Z.token,customer:Z.customer,createdAt:Z.createdAt.toISOString(),expiresAt:Z.expiresAt.toISOString()})}function CZ(Z,$){let Q=L(Z,{store:"magic-link",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt),expiresAt:new Date(Q.expiresAt)}}class NZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"magic-link-store"),this.log=D(Z)}key(Z){return C(this.prefix,"magic",O(Z))}async create(Z,$,Q){let Y=this.key(Z),W={token:Z,customer:$,createdAt:new Date,expiresAt:Q},V=Math.max(1,Math.floor((Q.getTime()-Date.now())/1000));if(await m(this.redis,Y,N$(W),{ttlSeconds:V})==="conflict")throw new C$(`Magic link with token ${Z} already exists`,"already_exists","token")}async get(Z){let $=await this.redis.get(this.key(Z));if($==null)return null;return CZ($,this.log)??null}async getAndDelete(Z){let $=this.key(Z),Q;if(typeof this.redis.getdel==="function")Q=await this.redis.getdel($);else if(Q=await this.redis.get($),Q!=null)await this.redis.del($);if(Q==null)return null;let Y=CZ(Q,this.log);if(Y==null)return null;if(Date.now()>Y.expiresAt.getTime())return null;return Y}async delete(Z){await this.redis.del(this.key(Z))}}import{defaultLogger as A$}from"@ionite/core";function P$(Z,$){if(typeof $!=="number"||$<=0)return Z;return new Promise((Q,Y)=>{let W=setTimeout(()=>{Y(Error(`Reactive Redis adapter did not become ready within ${$}ms`))},$);Z.then(()=>{clearTimeout(W),Q()},(V)=>{clearTimeout(W),Y(V)})})}function K$(){let Z,$;return{promise:new Promise((Y,W)=>{Z=Y,$=W}),resolve:Z,reject:$}}function AZ(Z){return typeof Z==="function"}function E$(Z){let $=Z.logger??A$,Q=Z.sourceName?.trim()||"redis",Y=Z.path.trim(),W,V,G=!1,B,U,M,F=!1,A=!1,z=!1,P=new Map,v=Promise.resolve(),f=K$();f.promise.catch(()=>{});let S={async get(H){return k((J)=>J.get(H))},async set(H,J){await k((X)=>X.set(H,J))},async setex(H,J,X){await k((N)=>N.setex(H,J,X))},async del(H){await k((J)=>J.del(H))},async sadd(H,...J){await k((X)=>X.sadd(H,...J))},async srem(H,...J){await k((X)=>X.srem(H,...J))},async smembers(H){return k((J)=>J.smembers(H))},async mget(H){return k((J)=>J.mget(H))},async publish(H,J){await k(async(X)=>{if(!X.publish)throw Error("Active Redis adapter does not support publish (Pub/Sub)");await X.publish(H,J)})},async subscribeChannel(H,J){let X=P.get(H);if(!X){let x=new Set;X={listeners:x,dispatch:(bZ)=>{for(let gZ of Array.from(x))try{gZ(bZ)}catch(u){$.warn("Redis channel listener threw",{"ion.operation":"redis.adapter.subscribe","ion.outcome":"failure",sourceName:Q,path:Y,channel:H,error:u instanceof Error?u.message:String(u)})}}},P.set(H,X)}let N=X;N.listeners.add(J);try{await TZ(H,N)}catch(x){if(N.listeners.delete(J),N.listeners.size===0)P.delete(H);throw x}return async()=>{if(N.listeners.delete(J),N.listeners.size===0){P.delete(H);let x=N.unsubscribe;N.unsubscribe=void 0,await x?.()}}},ready(H){return P$(f.promise,H)},isReady(){return W!==void 0},async close(){if(F=!0,e(),!G)G=!0,f.reject(Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" was closed before becoming ready.`));await v.catch(()=>{}),await y(W),W=void 0;for(let H of P.values())H.unsubscribe=void 0;P.clear(),l()}};function r(H){v=v.then(H).catch((J)=>{if(!G)G=!0,f.reject(J);$.warn("Reactive Redis adapter update failed",{"ion.operation":"redis.adapter.update","ion.outcome":"degraded",sourceName:Q,path:Y,error:J instanceof Error?J.message:String(J)})})}async function t(){if(F)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" is closed.`);let H=W?.adapter;if(H)return H;if(await v.catch(()=>{}),F)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" is closed.`);let J=W?.adapter;if(J)return J;if(await f.promise,F)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" is closed.`);let X=W?.adapter;if(!X)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" did not become ready.`);return X}async function k(H){let J=await t();return H(J)}function e(){V?.(),V=void 0}async function TZ(H,J){if(J.unsubscribe)return;if(!J.attaching)J.attaching=(async()=>{let X=await t();if(!X.subscribeChannel)throw Error("Active Redis adapter does not support subscribeChannel (Pub/Sub)");if(J.listeners.size===0)return;J.unsubscribe=await X.subscribeChannel(H,J.dispatch)})().finally(()=>{J.attaching=void 0});await J.attaching}async function jZ(H){for(let[J,X]of P){if(X.attaching)await X.attaching.catch(()=>{});if(X.unsubscribe=void 0,!H.subscribeChannel){$.warn("Active Redis adapter does not support subscribeChannel; channel subscriptions dropped.",{"ion.operation":"redis.adapter.capabilities","ion.outcome":"degraded",sourceName:Q,path:Y,capability:"subscribeChannel"});return}try{X.unsubscribe=await H.subscribeChannel(J,X.dispatch)}catch(N){$.warn("Failed to re-subscribe Redis channel after client rotation",{"ion.operation":"redis.adapter.subscribe","ion.outcome":"failure",sourceName:Q,path:Y,channel:J,error:N instanceof Error?N.message:String(N)})}}}async function mZ(H){e(),V=await H.subscribe(Y,(J)=>{r(async()=>{if(F)return;await IZ(J)})},Z.subscription??Z.secretOptions)}async function IZ(H){if(F)return;let J=`${Q}:${Y}:${H.metadata.version}`;if(W!==void 0&&U===J&&B===H.metadata.version)return;let X=Z.endpointOf?.(H);if(W!==void 0&&X!=null&&X!==""&&M!=null&&M!==""&&X!==M)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" rejected a rotation that changed the endpoint (${M} -> ${X}); only credentials may rotate under an active adapter.`);let N=await Z.createClient(H);if(F){await y(N);return}let x=W;if(W=N,U=J,B=H.metadata.version,X!=null&&X!=="")M=X;if(l(),x!==void 0)await jZ(N.adapter);if(!G)G=!0,f.resolve();await y(x)}async function y(H){if(!H?.dispose)return;await H.dispose()}function l(){let H=W?.adapter;if(H?.runScript&&AZ(H.runScript))S.runScript=async(J,X,N)=>{return k(async(x)=>{if(!x.runScript)throw Error("Active Redis adapter does not support runScript");return x.runScript(J,X,N)})};else if(delete S.runScript,H!==void 0&&!A)A=!0,$.warn("Active Redis adapter does not support runScript (EVAL); stores fall back to non-isolated writes.",{"ion.operation":"redis.adapter.capabilities","ion.outcome":"degraded",sourceName:Q,path:Y,capability:"runScript"});if(H?.getdel&&AZ(H.getdel))S.getdel=async(J)=>{return k(async(X)=>{if(!X.getdel)return null;return X.getdel(J)})};else if(delete S.getdel,H!==void 0&&!z)z=!0,$.warn("Active Redis adapter does not support getdel (GETDEL); single-use consume falls back to get+del.",{"ion.operation":"redis.adapter.capabilities","ion.outcome":"degraded",sourceName:Q,path:Y,capability:"getdel"})}return l(),r(async()=>{if(F)return;await mZ(Z.source)}),S}import{StoreConflictError as R$}from"@ionite/core";var f$=5;function S$(Z,$){let Q;try{Q=JSON.parse(Z)}catch{return}if(Q==null||typeof Q!=="object"||Array.isArray(Q))return;return JSON.stringify({...Q,...$})}function PZ(Z){return JSON.stringify({...Z,createdAt:Z.createdAt.toISOString()})}function KZ(Z,$){let Q=L(Z,{store:"session",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt)}}function EZ(Z){if(!Z)return;let $=Z instanceof Date?Z.getTime():new Date(Z).getTime();if(Number.isNaN($))return;let Q=Math.ceil(($-Date.now())/1000);return Q>0?Q:1}class RZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"session-store"),this.log=D(Z)}key(Z){return C(this.prefix,"session",O(Z))}async create(Z){let $=this.key(Z.sid),Q=EZ(Z.expiresAt);if(await m(this.redis,$,PZ(Z),{ttlSeconds:Q})==="conflict")throw new R$(`Session with sid ${Z.sid} already exists`,"already_exists","sid")}async get(Z){let $=await this.redis.get(this.key(Z));if($==null)return null;return KZ($,this.log)??null}async update(Z,$){let Q=this.key(Z),Y=JSON.parse(JSON.stringify($)),W="expiresAt"in Y?EZ(Y.expiresAt):void 0;if(R(this.redis))for(let M=0;M<f$;M++){let F=await this.redis.get(Q);if(F==null)throw Error(`Session with sid ${Z} not found`);let A=S$(F,Y);if(A===void 0)throw Error(`Session with sid ${Z} not found`);let z=await c(this.redis,Q,F,A,W);if(z==="ok")return;if(z==="missing")throw Error(`Session with sid ${Z} not found`)}let V=await this.redis.get(Q);if(V==null)throw Error(`Session with sid ${Z} not found`);let G=KZ(V,this.log);if(G==null)throw Error(`Session with sid ${Z} not found`);let B={...G,...$},U=PZ(B);if(W!=null&&W>0)await this.redis.setex(Q,Math.max(1,Math.floor(W)),U);else await this.redis.set(Q,U)}async delete(Z){await this.redis.del(this.key(Z))}}var x$="tenant:ids";function v$(Z){return JSON.stringify({...Z,createdAt:Z.createdAt.toISOString(),updatedAt:Z.updatedAt.toISOString()})}function fZ(Z,$){let Q=L(Z,{store:"tenant",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt),updatedAt:new Date(Q.updatedAt)}}class SZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"tenant-store"),this.log=D(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("tenant",O(Z))}idsSetKey(){return this.key(x$)}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return fZ($,this.log)}async upsert(Z){return await new q().set(this.entityKey(Z.id),v$(Z)).sadd(this.idsSetKey(),Z.id).exec(this.redis),Z}async list(Z){let $=await this.redis.smembers(this.idsSetKey());if($.length===0)return K([],Z);let Q=$.map((V)=>this.entityKey(V)),W=(await this.redis.mget(Q)).map((V)=>V!=null?fZ(V,this.log):void 0).filter((V)=>V!=null);return K(W,Z)}async delete(Z){let $=await this.get(Z);return await new q().srem(this.idsSetKey(),Z).del(this.entityKey(Z)).exec(this.redis),$?1:0}}class xZ{store;ionCache;constructor(Z){this.ionCache=Z.ionCache,this.store=new SZ(Z)}async get(Z){return this.store.get(Z)}async upsert(Z){let $=await this.store.upsert(Z);return this.ionCache?.delete(Z.id),$}async list(Z){return this.store.list(Z)}async delete(Z){let $=await this.store.delete(Z);return this.ionCache?.delete(Z),$}async getIon(Z){if(!this.ionCache)throw Error(`${this.constructor.name}.getIon() requires an app-owned ionCache. Pass { ionCache } (an lru-cache instance whose fetchMethod builds the tenant Ionite and whose dispose `+"closes it) — the SDK does not cache tenant runtimes. See the multi-tenant docs.");return this.ionCache.fetch(Z)}}import{list as k$,StoreConflictError as vZ}from"@ionite/core";var h$="user:ids",w$="user:name:",T$="user:external-id:";function j$(Z){let $=Z.createdAt??new Date,Q=Z.updatedAt??$,Y={...Z,createdAt:$.toISOString(),updatedAt:Q.toISOString()};if(Y.sso&&typeof Y.sso==="object"&&Y.sso!==null){let W=Y.sso;if(W.expires instanceof Date)W.expires=W.expires.toISOString()}return JSON.stringify(Y)}function a(Z,$){let Q=L(Z,{store:"user",log:$});if(Q===void 0)return;if(Q.sso&&typeof Q.sso==="object"&&Q.sso!==null){let Y=Q.sso;if(typeof Y.expires==="string")Y.expires=new Date(Y.expires)}return{...Q,createdAt:typeof Q.createdAt==="string"?new Date(Q.createdAt):void 0,updatedAt:typeof Q.updatedAt==="string"?new Date(Q.updatedAt):void 0}}class kZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"user-store"),this.log=D(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("user",O(Z))}idsSetKey(){return this.key(h$)}nameIndexKey(Z){return this.key(w$+O(Z))}externalIdIndexKey(Z){return this.key(T$+O(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return a($,this.log)}async getByExternalId(Z){let $=await this.redis.get(this.externalIdIndexKey(Z));return $?this.get($):void 0}async lookup(Z){return this.get(Z.id??"")}async upsert(Z){let $=Z.id?.trim()||crypto.randomUUID(),Q={...Z,id:$},Y=this.entityKey($),W=await this.redis.get(Y),V=W!=null?a(W,this.log)??null:null,G=Q.userName?.toLowerCase(),B=V?.userName?.toLowerCase(),U=Q.externalId,M=V?.externalId,F=new q;if(G)F.claimUnique(this.nameIndexKey(G),$);if(U)F.claimUnique(this.externalIdIndexKey(U),$);if(B&&B!==G)F.del(this.nameIndexKey(B));if(M&&M!==U)F.del(this.externalIdIndexKey(M));if(F.set(Y,j$(Q)),G)F.set(this.nameIndexKey(G),$);if(U)F.set(this.externalIdIndexKey(U),$);if(F.sadd(this.idsSetKey(),$),await F.exec(this.redis)==="conflict"){if(U){let A=await this.redis.get(this.externalIdIndexKey(U));if(A&&A!==$)throw new vZ(`externalId "${U}" is already in use`,"unique_violation","externalId")}throw new vZ(`userName "${Q.userName}" is already in use`,"unique_violation","userName")}return Q}async delete(Z){let $=await this.get(Z);if($==null)return 0;let Q=new q;if(Q.del(this.entityKey(Z)),$.userName)Q.del(this.nameIndexKey($.userName.toLowerCase()));if($.externalId)Q.del(this.externalIdIndexKey($.externalId));return Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),1}async list(Z){let $=h(Z),Q=(await this.redis.smembers(this.idsSetKey())).sort();if(Q.length===0)return k$(0,[],$.start??0,$.limit);let Y=Q.map((G)=>this.entityKey(G)),V=(await this.redis.mget(Y)).filter((G)=>G!=null).map((G)=>a(G,this.log)).filter((G)=>G!=null);return K(V,$)}}import{list as m$,StoreConflictError as I$}from"@ionite/core";var b$="workload-identity:ids",g$="workload-identity:client:";function y$(Z){let $=Z.createdAt??new Date,Q=Z.updatedAt??$;return JSON.stringify({...Z,createdAt:$.toISOString(),updatedAt:Q.toISOString()})}function s(Z,$){let Q=L(Z,{store:"workload-identity",log:$});if(Q===void 0)return;return{...Q,createdAt:typeof Q.createdAt==="string"?new Date(Q.createdAt):void 0,updatedAt:typeof Q.updatedAt==="string"?new Date(Q.updatedAt):void 0}}class hZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"workload-identity-store"),this.log=D(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("workload-identity",O(Z))}idsSetKey(){return this.key(b$)}clientIndexKey(Z){return this.key(g$+O(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return s($,this.log)}async lookup(Z){if(Z.id){let $=await this.get(Z.id);if($)return $}if(Z.clientId){let $=await this.redis.get(this.clientIndexKey(Z.clientId));if($!=null)return this.get($)}return}async upsert(Z){let $=Z.id?.trim()||crypto.randomUUID(),Q=this.entityKey($),Y=await this.redis.get(Q),W=null;if(Y!=null)W=s(Y,this.log)??null;let V=new Date,G={...Z,id:$,createdAt:W?.createdAt??Z.createdAt??V,updatedAt:V},B=new q;if(G.clientId)B.claimUnique(this.clientIndexKey(G.clientId),$);if(W?.clientId&&W.clientId!==G.clientId)B.del(this.clientIndexKey(W.clientId));if(B.set(Q,y$(G)),G.clientId)B.set(this.clientIndexKey(G.clientId),$);if(B.sadd(this.idsSetKey(),$),await B.exec(this.redis)==="conflict")throw new I$(`clientId "${G.clientId}" is already in use`,"unique_violation","clientId");return G}async delete(Z){let $=await this.get(Z);if($==null)return 0;let Q=new q;if(Q.del(this.entityKey(Z)),$.clientId)Q.del(this.clientIndexKey($.clientId));return Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),1}async list(Z){let $=h(Z),Q=(await this.redis.smembers(this.idsSetKey())).sort();if(Q.length===0)return m$(0,[],$.start??0,$.limit);let Y=Q.map((G)=>this.entityKey(G)),V=(await this.redis.mget(Y)).filter((G)=>G!=null).map((G)=>s(G,this.log)).filter((G)=>G!=null);return K(V,$)}}function l$(Z){return JSON.stringify({...Z,expires_at:Z.expires_at.toISOString(),created_at:Z.created_at.toISOString()})}function u$(Z,$){let Q=L(Z,{store:"workload-token",log:$});if(Q===void 0)return;return{...Q,expires_at:new Date(Q.expires_at),created_at:new Date(Q.created_at)}}class wZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"workload-token-store"),this.log=D(Z)}key(Z){return C(this.prefix,"workload","token",O(Z))}async set(Z){let $=this.key(Z.workload_id),Q=Math.max(1,Math.floor((Z.expires_at.getTime()-Date.now())/1000));await this.redis.setex($,Q,l$(Z))}async get(Z){let $=await this.redis.get(this.key(Z));if($==null)return null;let Q=u$($,this.log);if(Q==null)return null;if(Date.now()>Q.expires_at.getTime())return await this.redis.del(this.key(Z)),null;return Q}async delete(Z){await this.redis.del(this.key(Z))}async isValid(Z){return await this.get(Z)!==null}async cleanup(){}}export{R as supportsRunScript,D$ as splitIonRedisSecret,qZ as scriptSha1,C as prefixedKey,D as getLogger,_ as getKeyPrefix,O as encodeKeyId,_$ as createRedisLfvTransport,E$ as createReactiveRedis,z$ as createEvalshaRunner,B$ as chunkedMget,m as atomicCreate,c as atomicCompareAndSet,wZ as RedisWorkloadTokenStore,hZ as RedisWorkloadIdentityStore,kZ as RedisUserStore,q as RedisTxn,xZ as RedisTenantStore,RZ as RedisSessionStore,FZ as RedisResourceStore,NZ as RedisMagicLinkStore,DZ as RedisCustomerStore,zZ as RedisAccessIndex,XZ as RedisAccessCatalogStore,JZ as RedisAccessAssignmentStore,QZ as MAX_LIST_LIMIT,V$ as DEFAULT_MGET_CHUNK_SIZE,$Z as DEFAULT_LIST_LIMIT};
|
|
176
|
+
return 'ok'`;function T(Z,$){return`${$}:${Z}`}function b(Z){return Z&&Z.length>0?Z:y}function o(Z){return JSON.stringify([Z.subject,Z.targetType,Z.target,Z.rToken])}function j(Z){let $;try{$=JSON.parse(Z)}catch{$=[]}let[Q,Y,W,V]=Array.isArray($)?$:[];return{subject:Q??"",targetType:Y??"permission",target:W??"",rToken:V??y}}class FZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"access-index"),this.log=F(Z)}key(...Z){return C(this.prefix,...Z)}subjectKeyPart(Z){let $=Z.indexOf(":");if($<=0)return X(Z);return`${Z.slice(0,$)}:${X(Z.slice($+1))}`}hasKey(Z,$,Q,Y){return this.key("idx:has",this.subjectKeyPart(Z),$,X(Q),X(Y))}anyKey(Z,$,Q){return this.key("idx:any",this.subjectKeyPart(Z),$,X(Q))}edgeRootsKey(Z,$,Q,Y){return this.key("idx:er",this.subjectKeyPart(Z),$,X(Q),X(Y))}tripleKey(Z,$,Q){return this.key("idx:tr",this.subjectKeyPart(Z),$,X(Q))}rootKey(Z){return this.key("idx:root",X(Z))}subjectKey(Z){return this.key("idx:subj",this.subjectKeyPart(Z))}subjectsKey(){return this.key("idx:subjects")}disabledKey(Z){return this.key("idx:disabled",this.subjectKeyPart(Z))}async has(Z,$,Q,Y,W){w(W);let V=R(Z),G=R(Q);if(!V||!G)return{allow:!1};let B=T(V,W);if(Y===void 0){let[O,A]=await this.redis.mget([this.disabledKey(B),this.anyKey(B,$,G)]);if(O!=null)return{allow:!1,metadata:{reason:"subject_disabled"}};return A!=null?this.allow(V,W,$,G,void 0):{allow:!1}}let U=R(Y),J=await this.redis.mget([this.disabledKey(B),this.hasKey(B,$,G,b(U)),this.hasKey(B,$,G,y)]);if(J[0]!=null)return{allow:!1,metadata:{reason:"subject_disabled"}};if(J[1]!=null)return this.allow(V,W,$,G,U);if(J[2]!=null)return this.allow(V,W,$,G,void 0);return{allow:!1}}async hasGroup(Z,$,Q,Y){return this.has(Z,"group",$,Q,Y)}async hasRole(Z,$,Q,Y){return this.has(Z,"role",$,Q,Y)}async hasPermission(Z,$,Q,Y){return this.has(Z,"permission",$,Q,Y)}async hasAny(Z,$,Q){if($.length===0)return{allow:!1};this.warnLargeCheck("redis.access_index.has_any",$.length);let Y=await this.evaluateTargets(Z,$,Q);for(let W of Y)if(W.allow)return W;return{allow:!1}}async hasAll(Z,$,Q){if($.length===0){let V=R(Z);if(V){if(await this.redis.get(this.disabledKey(T(V,Q)))!=null)return{allow:!1,metadata:{reason:"subject_disabled"}}}return{allow:!0}}this.warnLargeCheck("redis.access_index.has_all",$.length);let Y=await this.evaluateTargets(Z,$,Q),W=[];for(let V of Y){if(!V.allow)return{allow:!1,matched:W};if(V.matched)W.push(...V.matched)}return{allow:!0,matched:W}}async evaluateTargets(Z,$,Q){let Y=R(Z);if(!Y)return $.map(()=>({allow:!1}));let W=T(Y,Q),V=[this.disabledKey(W)],G=$.map((U)=>{let J=R(U.target);if(!J)return{kind:"invalid"};if(U.resource===void 0){let P=V.push(this.anyKey(W,U.targetType,J))-1;return{kind:"any",targetType:U.targetType,targetId:J,idx:P}}let O=R(U.resource),A=V.push(this.hasKey(W,U.targetType,J,b(O)))-1,q=V.push(this.hasKey(W,U.targetType,J,y))-1;return{kind:"resource",targetType:U.targetType,targetId:J,resourceId:O,idxResource:A,idxApp:q}}),B=await this.redis.mget(V);if(B[0]!=null)return $.map(()=>({allow:!1,metadata:{reason:"subject_disabled"}}));return G.map((U)=>{if(U.kind==="invalid")return{allow:!1};if(U.kind==="any")return B[U.idx]!=null?this.allow(Y,Q,U.targetType,U.targetId,void 0):{allow:!1};if(B[U.idxResource]!=null)return this.allow(Y,Q,U.targetType,U.targetId,U.resourceId);if(B[U.idxApp]!=null)return this.allow(Y,Q,U.targetType,U.targetId,void 0);return{allow:!1}})}edgeKeys(Z){return[this.edgeRootsKey(Z.subject,Z.targetType,Z.target,Z.rToken),this.hasKey(Z.subject,Z.targetType,Z.target,Z.rToken),this.tripleKey(Z.subject,Z.targetType,Z.target),this.anyKey(Z.subject,Z.targetType,Z.target),this.subjectKey(Z.subject)]}async materialize(Z,$){let Q=new Map;for(let G of $){let B=R(G.subject),U=R(G.target);if(!B||!U)continue;w(G.subjectType,"Effective edge subjectType");let J=T(B,G.subjectType),O=b(G.resource),A={subject:J,targetType:G.targetType,target:U,rToken:O};Q.set(o(A),A)}let Y=new Set(await this.redis.smembers(this.rootKey(Z))),W=[];for(let[G,B]of Q)if(!Y.has(G))W.push({encoded:G,d:B});let V=[];for(let G of Y)if(!Q.has(G))V.push({encoded:G,d:j(G)});if(W.length===0&&V.length===0)return;if(E(this.redis)){let G=[this.rootKey(Z),this.subjectsKey()],B=[Z,String(W.length),String(V.length)];for(let{encoded:U,d:J}of W)G.push(...this.edgeKeys(J)),B.push(U,J.rToken,J.subject);for(let{encoded:U,d:J}of V)G.push(...this.edgeKeys(J)),B.push(U,J.rToken);await this.redis.runScript(Q$,G,B);return}for(let{encoded:G,d:B}of W)await this.redis.sadd(this.edgeRootsKey(B.subject,B.targetType,B.target,B.rToken),Z),await this.redis.set(this.hasKey(B.subject,B.targetType,B.target,B.rToken),"1"),await this.redis.sadd(this.tripleKey(B.subject,B.targetType,B.target),B.rToken),await this.redis.set(this.anyKey(B.subject,B.targetType,B.target),"1"),await this.redis.sadd(this.rootKey(Z),G),await this.redis.sadd(this.subjectKey(B.subject),G),await this.redis.sadd(this.subjectsKey(),B.subject);for(let{encoded:G,d:B}of V)await this.dropRootFromEdge(Z,B.subject,B.targetType,B.target,B.rToken),await this.redis.srem(this.rootKey(Z),G)}async replaceSubject(Z,$,Q){if(!E(this.redis))throw Error("RedisAccessIndex.replaceSubject requires an adapter with atomic runScript support.");let Y=R(Z);if(!Y)return;let W=T(Y,$),V=[];for(let q of Q){let P=R(q.subject);w(q.subjectType,"Effective edge subjectType");let k=q.subjectType;if(P!==Y||k!==$)throw Error(`AccessIndex.replaceSubject received an edge for ${k}:${P}; expected ${W}.`);let f=R(q.target);if(!f)continue;let S={subject:W,targetType:q.targetType,target:f,rToken:b(q.resource)};V.push({rootId:q.rootId,encoded:o(S),d:S})}let B=(await this.redis.smembers(this.subjectKey(W))).map(j),U=await Promise.all(B.map((q)=>this.redis.smembers(this.edgeRootsKey(q.subject,q.targetType,q.target,q.rToken)))),J=[...new Set(U.flat())],O=[this.subjectKey(W),this.subjectsKey()];for(let q of B){let[P,k,f,S]=this.edgeKeys(q);O.push(P,k,f,S)}for(let q of J)O.push(this.rootKey(q));for(let q of V){let[P,k,f,S]=this.edgeKeys(q.d);O.push(this.rootKey(q.rootId),P,k,f,S)}let A=[W,String(B.length),String(J.length),String(V.length)];for(let q of V)A.push(q.rootId,q.encoded,q.d.rToken);await this.redis.runScript(V$,O,A)}async removeByRoot(Z){let $=this.rootKey(Z),Q=await this.redis.smembers($);if(Q.length===0){await this.redis.del($);return}if(E(this.redis)){let Y=[$],W=[Z,String(Q.length)];for(let V of Q){let G=j(V);Y.push(...this.edgeKeys(G)),W.push(V,G.rToken)}await this.redis.runScript(Y$,Y,W);return}for(let Y of Q){let{subject:W,targetType:V,target:G,rToken:B}=j(Y);await this.dropRootFromEdge(Z,W,V,G,B)}await this.redis.del($)}async listSubjects(){let Z=await this.redis.smembers(this.subjectsKey()),$=[];for(let Q of Z){let Y=Q.indexOf(":");if(Y<=0)throw Error(`AccessIndex subject key "${Q}" is missing a subjectType prefix.`);let W=Q.slice(0,Y);w(W,"AccessIndex subject key subjectType"),$.push({subjectType:W,subject:Q.slice(Y+1)})}return $}async setSubjectDisabled(Z,$,Q){let Y=R(Z);if(!Y)return;let W=this.disabledKey(T(Y,$));if(Q)await this.redis.set(W,"1");else await this.redis.del(W)}async isSubjectDisabled(Z,$){w($);let Q=R(Z);if(!Q)return!1;return await this.redis.get(this.disabledKey(T(Q,$)))!=null}async clear(Z,$){if(Z===void 0){let W=await this.redis.smembers(this.subjectsKey());for(let V of W)await this.clearSubject(V);await this.redis.del(this.subjectsKey());return}w($);let Q=R(Z);if(!Q)return;let Y=T(Q,$);await this.clearSubject(Y),await this.redis.srem(this.subjectsKey(),Y)}async clearSubject(Z){let $=this.subjectKey(Z),Q=await this.redis.smembers($);if(Q.length===0){await this.redis.del($);return}if(E(this.redis)){let Y=[$];for(let V of Q){let{targetType:G,target:B,rToken:U}=j(V);Y.push(this.edgeRootsKey(Z,G,B,U),this.hasKey(Z,G,B,U),this.tripleKey(Z,G,B),this.anyKey(Z,G,B))}let W=$$(await this.redis.runScript(W$,Y,[String(Q.length)]));if(W.length>0)await this.redis.runScript(G$,W.map((V)=>this.rootKey(V)),[]);return}for(let Y of Q){let{targetType:W,target:V,rToken:G}=j(Y),B=this.edgeRootsKey(Z,W,V,G),U=await this.redis.smembers(B);for(let O of U)await this.redis.srem(this.rootKey(O),Y);if(await this.redis.del(B),await this.redis.del(this.hasKey(Z,W,V,G)),await this.redis.srem(this.tripleKey(Z,W,V),G),(await this.redis.smembers(this.tripleKey(Z,W,V))).length===0)await this.redis.del(this.tripleKey(Z,W,V)),await this.redis.del(this.anyKey(Z,W,V))}await this.redis.del($)}async dropRootFromEdge(Z,$,Q,Y,W){let V=this.edgeRootsKey($,Q,Y,W);if(await this.redis.srem(V,Z),(await this.redis.smembers(V)).length>0)return;await this.redis.del(V),await this.redis.del(this.hasKey($,Q,Y,W));let B=o({subject:$,targetType:Q,target:Y,rToken:W});if(await this.redis.srem(this.subjectKey($),B),await this.redis.srem(this.tripleKey($,Q,Y),W),(await this.redis.smembers(this.tripleKey($,Q,Y))).length===0)await this.redis.del(this.tripleKey($,Q,Y)),await this.redis.del(this.anyKey($,Q,Y))}allow(Z,$,Q,Y,W){return{allow:!0,matched:[{subject:Z,subjectType:$,targetType:Q,target:Y,resources:W?[W]:void 0}]}}warnLargeCheck(Z,$){if($<=qZ)return;this.log.warn("Redis access index check received a large bounded target set; issuing per-target reads.",{"ion.operation":Z,"ion.outcome":"degraded",count:$,threshold:qZ})}}var B$=512;async function U$(Z,$,Q=512){if(Z.length===0)return[];let Y=Q>0?Q:512,W=[];for(let V=0;V<Z.length;V+=Y){let G=await $(Z.slice(V,V+Y));for(let B of G)W.push(B??null)}return W}import{list as H$,StoreConflictError as J$}from"@ionite/core";var M$="customer:ids",O$="customer:name:",z$="customer:external:";function X$(Z){let $=Z.createdAt??new Date,Q=Z.updatedAt??$,Y={...Z,createdAt:$.toISOString(),updatedAt:Q.toISOString()};if(Y.ciam&&typeof Y.ciam==="object"&&Y.ciam!==null){let W=Y.ciam;if(W.expires instanceof Date)W.expires=W.expires.toISOString()}return JSON.stringify(Y)}function n(Z,$){let Q=L(Z,{store:"customer",log:$});if(Q===void 0)return;if(Q.ciam&&typeof Q.ciam==="object"&&Q.ciam!==null){let Y=Q.ciam;if(typeof Y.expires==="string")Y.expires=new Date(Y.expires)}return{...Q,createdAt:typeof Q.createdAt==="string"?new Date(Q.createdAt):void 0,updatedAt:typeof Q.updatedAt==="string"?new Date(Q.updatedAt):void 0}}class DZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"customer-store"),this.log=F(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("customer",X(Z))}idsSetKey(){return this.key(M$)}nameIndexKey(Z){return this.key(O$+X(Z))}externalIdIndexKey(Z){return this.key(z$+X(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return n($,this.log)}async lookup(Z){if(Z.id){let $=await this.get(Z.id);if($)return $}if(Z.userName){let $=await this.redis.get(this.nameIndexKey(Z.userName.toLowerCase()));if($!=null)return this.get($)}if(Z.externalId)return this.getByExternalId(Z.externalId);return}async getByExternalId(Z){let $=await this.redis.get(this.externalIdIndexKey(Z));if($==null)return;return this.get($)}async upsert(Z){let $=Z.id?.trim()||crypto.randomUUID(),Q={...Z,id:$},Y=this.entityKey($),W=await this.redis.get(Y),V=W!=null?n(W,this.log)??null:null,G=Q.userName?.toLowerCase(),B=V?.userName?.toLowerCase(),U=Q.externalId,J=V?.externalId,O=new D;if(G)O.claimUnique(this.nameIndexKey(G),$);if(U)O.claimUnique(this.externalIdIndexKey(U),$);if(B&&B!==G)O.del(this.nameIndexKey(B));if(J&&J!==U)O.del(this.externalIdIndexKey(J));if(O.set(Y,X$(Q)),G)O.set(this.nameIndexKey(G),$);if(U)O.set(this.externalIdIndexKey(U),$);if(O.sadd(this.idsSetKey(),$),await O.exec(this.redis)==="conflict")throw new J$(`userName "${Q.userName}" is already in use`,"unique_violation","userName");return Q}async delete(Z){let $=await this.get(Z);if($==null)return 0;let Q=new D;if(Q.del(this.entityKey(Z)),$.userName)Q.del(this.nameIndexKey($.userName.toLowerCase()));if($.externalId)Q.del(this.externalIdIndexKey($.externalId));return Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),1}async list(Z){let $=h(Z),Q=(await this.redis.smembers(this.idsSetKey())).sort();if(Q.length===0)return H$(0,[],$.start??0,$.limit);let Y=Q.map((G)=>this.entityKey(G)),V=(await this.redis.mget(Y)).filter((G)=>G!=null).map((G)=>n(G,this.log)).filter((G)=>G!=null);return K(V,$)}}import{createHash as q$}from"node:crypto";function LZ(Z){return q$("sha1").update(Z,"utf8").digest("hex")}function F$(Z){return(Z instanceof Error?Z.message:String(Z)).includes("NOSCRIPT")}function D$(Z){let $=new Map;return async(Q,Y,W)=>{let V=$.get(Q);if(!V)V=LZ(Q),$.set(Q,V);try{return await Z.evalsha(V,Y,W)}catch(G){if(F$(G))return Z.eval(Q,Y,W);throw G}}}function _Z(Z){return typeof Z==="object"&&Z!==null&&!Array.isArray(Z)}function L$(Z){let $=_Z(Z.clientOptions)?{...Z.clientOptions}:_Z(Z)?{...Z}:{};return delete $.redisUrl,delete $.clientOptions,{redisUrl:(typeof Z.redisUrl==="string"?Z.redisUrl.trim():"")||void 0,clientOptions:$}}import{defaultLogger as _$}from"@ionite/core";function CZ(Z,$){return`${Z}:${encodeURIComponent($)}`}function C$(Z,$){if(typeof Z!=="object"||Z===null||Array.isArray(Z))return!1;let Q=Z,Y=Q.headers;return Q.kind==="delivery"&&typeof Q.key==="string"&&typeof Q.rawBody==="string"&&typeof Y==="object"&&Y!==null&&Y.requestId===$&&typeof Y.keyId==="string"&&typeof Y.signature==="string"}function N$(Z,$={}){if(!Z.getdel)throw Error("Redis adapter must implement getdel() for LFV callback coordination");let Q=Z.getdel.bind(Z),Y=$.channelPrefix?.trim()||"ionite:lfv:otp",W=$.logger??_$;return{async put(V,G,B){if(G.kind!=="delivery"||G.headers.requestId!==V)throw Error("LFV callback mailbox only accepts matching delivery envelopes");let U=Math.max(1,Math.ceil(B/1000));await Z.setex(CZ(Y,V),U,JSON.stringify(G))},async take(V){let G=await Q(CZ(Y,V));if(G==null)return;let B;try{B=JSON.parse(G)}catch(U){W.warn("Invalid JSON received from LFV Redis callback mailbox",{"ion.operation":"lfv.callback.redis.take","ion.outcome":"rejected",requestId:V,error:U instanceof Error?U.message:String(U)});return}if(!C$(B,V)){W.warn("Invalid envelope received from LFV Redis callback mailbox",{"ion.operation":"lfv.callback.redis.take","ion.outcome":"rejected",requestId:V});return}return B}}}import{StoreConflictError as A$}from"@ionite/core";function P$(Z){return JSON.stringify({token:Z.token,customer:Z.customer,createdAt:Z.createdAt.toISOString(),expiresAt:Z.expiresAt.toISOString()})}function NZ(Z,$){let Q=L(Z,{store:"magic-link",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt),expiresAt:new Date(Q.expiresAt)}}class AZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"magic-link-store"),this.log=F(Z)}key(Z){return C(this.prefix,"magic",X(Z))}async create(Z,$,Q){let Y=this.key(Z),W={token:Z,customer:$,createdAt:new Date,expiresAt:Q},V=Math.max(1,Math.floor((Q.getTime()-Date.now())/1000));if(await m(this.redis,Y,P$(W),{ttlSeconds:V})==="conflict")throw new A$(`Magic link with token ${Z} already exists`,"already_exists","token")}async get(Z){let $=await this.redis.get(this.key(Z));if($==null)return null;return NZ($,this.log)??null}async getAndDelete(Z){let $=this.key(Z),Q;if(typeof this.redis.getdel==="function")Q=await this.redis.getdel($);else if(Q=await this.redis.get($),Q!=null)await this.redis.del($);if(Q==null)return null;let Y=NZ(Q,this.log);if(Y==null)return null;if(Date.now()>Y.expiresAt.getTime())return null;return Y}async delete(Z){await this.redis.del(this.key(Z))}}import{defaultLogger as K$}from"@ionite/core";function R$(Z,$){if(typeof $!=="number"||$<=0)return Z;return new Promise((Q,Y)=>{let W=setTimeout(()=>{Y(Error(`Reactive Redis adapter did not become ready within ${$}ms`))},$);Z.then(()=>{clearTimeout(W),Q()},(V)=>{clearTimeout(W),Y(V)})})}function E$(){let Z,$;return{promise:new Promise((Y,W)=>{Z=Y,$=W}),resolve:Z,reject:$}}function PZ(Z){return typeof Z==="function"}function f$(Z){let $=Z.logger??K$,Q=Z.sourceName?.trim()||"redis",Y=Z.path.trim(),W,V,G=!1,B,U,J,O=!1,A=!1,q=!1,P=new Map,k=Promise.resolve(),f=E$();f.promise.catch(()=>{});let S={async get(H){return x((M)=>M.get(H))},async set(H,M){await x((z)=>z.set(H,M))},async setex(H,M,z){await x((N)=>N.setex(H,M,z))},async del(H){await x((M)=>M.del(H))},async sadd(H,...M){await x((z)=>z.sadd(H,...M))},async srem(H,...M){await x((z)=>z.srem(H,...M))},async smembers(H){return x((M)=>M.smembers(H))},async mget(H){return x((M)=>M.mget(H))},async publish(H,M){await x(async(z)=>{if(!z.publish)throw Error("Active Redis adapter does not support publish (Pub/Sub)");await z.publish(H,M)})},async subscribeChannel(H,M){let z=P.get(H);if(!z){let v=new Set;z={listeners:v,dispatch:(yZ)=>{for(let gZ of Array.from(v))try{gZ(yZ)}catch(u){$.warn("Redis channel listener threw",{"ion.operation":"redis.adapter.subscribe","ion.outcome":"failure",sourceName:Q,path:Y,channel:H,error:u instanceof Error?u.message:String(u)})}}},P.set(H,z)}let N=z;N.listeners.add(M);try{await jZ(H,N)}catch(v){if(N.listeners.delete(M),N.listeners.size===0)P.delete(H);throw v}return async()=>{if(N.listeners.delete(M),N.listeners.size===0){P.delete(H);let v=N.unsubscribe;N.unsubscribe=void 0,await v?.()}}},ready(H){return R$(f.promise,H)},isReady(){return W!==void 0},async close(){if(O=!0,e(),!G)G=!0,f.reject(Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" was closed before becoming ready.`));await k.catch(()=>{}),await g(W),W=void 0;for(let H of P.values())H.unsubscribe=void 0;P.clear(),l()}};function r(H){k=k.then(H).catch((M)=>{if(!G)G=!0,f.reject(M);$.warn("Reactive Redis adapter update failed",{"ion.operation":"redis.adapter.update","ion.outcome":"degraded",sourceName:Q,path:Y,error:M instanceof Error?M.message:String(M)})})}async function t(){if(O)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" is closed.`);let H=W?.adapter;if(H)return H;if(await k.catch(()=>{}),O)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" is closed.`);let M=W?.adapter;if(M)return M;if(await f.promise,O)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" is closed.`);let z=W?.adapter;if(!z)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" did not become ready.`);return z}async function x(H){let M=await t();return H(M)}function e(){V?.(),V=void 0}async function jZ(H,M){if(M.unsubscribe)return;if(!M.attaching)M.attaching=(async()=>{let z=await t();if(!z.subscribeChannel)throw Error("Active Redis adapter does not support subscribeChannel (Pub/Sub)");if(M.listeners.size===0)return;M.unsubscribe=await z.subscribeChannel(H,M.dispatch)})().finally(()=>{M.attaching=void 0});await M.attaching}async function mZ(H){for(let[M,z]of P){if(z.attaching)await z.attaching.catch(()=>{});if(z.unsubscribe=void 0,!H.subscribeChannel){$.warn("Active Redis adapter does not support subscribeChannel; channel subscriptions dropped.",{"ion.operation":"redis.adapter.capabilities","ion.outcome":"degraded",sourceName:Q,path:Y,capability:"subscribeChannel"});return}try{z.unsubscribe=await H.subscribeChannel(M,z.dispatch)}catch(N){$.warn("Failed to re-subscribe Redis channel after client rotation",{"ion.operation":"redis.adapter.subscribe","ion.outcome":"failure",sourceName:Q,path:Y,channel:M,error:N instanceof Error?N.message:String(N)})}}}async function IZ(H){e(),V=await H.subscribe(Y,(M)=>{r(async()=>{if(O)return;await bZ(M)})},Z.subscription??Z.secretOptions)}async function bZ(H){if(O)return;let M=`${Q}:${Y}:${H.metadata.version}`;if(W!==void 0&&U===M&&B===H.metadata.version)return;let z=Z.endpointOf?.(H);if(W!==void 0&&z!=null&&z!==""&&J!=null&&J!==""&&z!==J)throw Error(`Reactive Redis adapter for source "${Q}" at path "${Y}" rejected a rotation that changed the endpoint (${J} -> ${z}); only credentials may rotate under an active adapter.`);let N=await Z.createClient(H);if(O){await g(N);return}let v=W;if(W=N,U=M,B=H.metadata.version,z!=null&&z!=="")J=z;if(l(),v!==void 0)await mZ(N.adapter);if(!G)G=!0,f.resolve();await g(v)}async function g(H){if(!H?.dispose)return;await H.dispose()}function l(){let H=W?.adapter;if(H?.runScript&&PZ(H.runScript))S.runScript=async(M,z,N)=>{return x(async(v)=>{if(!v.runScript)throw Error("Active Redis adapter does not support runScript");return v.runScript(M,z,N)})};else if(delete S.runScript,H!==void 0&&!A)A=!0,$.warn("Active Redis adapter does not support runScript (EVAL); stores fall back to non-isolated writes.",{"ion.operation":"redis.adapter.capabilities","ion.outcome":"degraded",sourceName:Q,path:Y,capability:"runScript"});if(H?.getdel&&PZ(H.getdel))S.getdel=async(M)=>{return x(async(z)=>{if(!z.getdel)return null;return z.getdel(M)})};else if(delete S.getdel,H!==void 0&&!q)q=!0,$.warn("Active Redis adapter does not support getdel (GETDEL); single-use consume falls back to get+del.",{"ion.operation":"redis.adapter.capabilities","ion.outcome":"degraded",sourceName:Q,path:Y,capability:"getdel"})}return l(),r(async()=>{if(O)return;await IZ(Z.source)}),S}import{StoreConflictError as S$}from"@ionite/core";var v$=5;function k$(Z,$){let Q;try{Q=JSON.parse(Z)}catch{return}if(Q==null||typeof Q!=="object"||Array.isArray(Q))return;return JSON.stringify({...Q,...$})}function KZ(Z){return JSON.stringify({...Z,createdAt:Z.createdAt.toISOString()})}function RZ(Z,$){let Q=L(Z,{store:"session",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt)}}function EZ(Z){if(!Z)return;let $=Z instanceof Date?Z.getTime():new Date(Z).getTime();if(Number.isNaN($))return;let Q=Math.ceil(($-Date.now())/1000);return Q>0?Q:1}class fZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"session-store"),this.log=F(Z)}key(Z){return C(this.prefix,"session",X(Z))}async create(Z){let $=this.key(Z.sid),Q=EZ(Z.expiresAt);if(await m(this.redis,$,KZ(Z),{ttlSeconds:Q})==="conflict")throw new S$(`Session with sid ${Z.sid} already exists`,"already_exists","sid")}async get(Z){let $=await this.redis.get(this.key(Z));if($==null)return null;return RZ($,this.log)??null}async update(Z,$){let Q=this.key(Z),Y=JSON.parse(JSON.stringify($)),W="expiresAt"in Y?EZ(Y.expiresAt):void 0;if(E(this.redis))for(let J=0;J<v$;J++){let O=await this.redis.get(Q);if(O==null)throw Error(`Session with sid ${Z} not found`);let A=k$(O,Y);if(A===void 0)throw Error(`Session with sid ${Z} not found`);let q=await c(this.redis,Q,O,A,W);if(q==="ok")return;if(q==="missing")throw Error(`Session with sid ${Z} not found`)}let V=await this.redis.get(Q);if(V==null)throw Error(`Session with sid ${Z} not found`);let G=RZ(V,this.log);if(G==null)throw Error(`Session with sid ${Z} not found`);let B={...G,...$},U=KZ(B);if(W!=null&&W>0)await this.redis.setex(Q,Math.max(1,Math.floor(W)),U);else await this.redis.set(Q,U)}async delete(Z){await this.redis.del(this.key(Z))}}var x$="tenant:ids";function h$(Z){return JSON.stringify({...Z,createdAt:Z.createdAt.toISOString(),updatedAt:Z.updatedAt.toISOString()})}function SZ(Z,$){let Q=L(Z,{store:"tenant",log:$});if(Q===void 0)return;return{...Q,createdAt:new Date(Q.createdAt),updatedAt:new Date(Q.updatedAt)}}class vZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"tenant-store"),this.log=F(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("tenant",X(Z))}idsSetKey(){return this.key(x$)}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return SZ($,this.log)}async upsert(Z){return await new D().set(this.entityKey(Z.id),h$(Z)).sadd(this.idsSetKey(),Z.id).exec(this.redis),Z}async list(Z){let $=await this.redis.smembers(this.idsSetKey());if($.length===0)return K([],Z);let Q=$.map((V)=>this.entityKey(V)),W=(await this.redis.mget(Q)).map((V)=>V!=null?SZ(V,this.log):void 0).filter((V)=>V!=null);return K(W,Z)}async delete(Z){let $=await this.get(Z);return await new D().srem(this.idsSetKey(),Z).del(this.entityKey(Z)).exec(this.redis),$?1:0}}class kZ{store;ionCache;constructor(Z){this.ionCache=Z.ionCache,this.store=new vZ(Z)}async get(Z){return this.store.get(Z)}async upsert(Z){let $=await this.store.upsert(Z);return this.ionCache?.delete(Z.id),$}async list(Z){return this.store.list(Z)}async delete(Z){let $=await this.store.delete(Z);return this.ionCache?.delete(Z),$}async getIon(Z){if(!this.ionCache)throw Error(`${this.constructor.name}.getIon() requires an app-owned ionCache. Pass { ionCache } (an lru-cache instance whose fetchMethod builds the tenant Ionite and whose dispose `+"closes it) — the SDK does not cache tenant runtimes. See the multi-tenant docs.");return this.ionCache.fetch(Z)}}import{list as T$,StoreConflictError as xZ}from"@ionite/core";var w$="user:ids",j$="user:name:",m$="user:external-id:";function I$(Z){let $=Z.createdAt??new Date,Q=Z.updatedAt??$,Y={...Z,createdAt:$.toISOString(),updatedAt:Q.toISOString()};if(Y.sso&&typeof Y.sso==="object"&&Y.sso!==null){let W=Y.sso;if(W.expires instanceof Date)W.expires=W.expires.toISOString()}return JSON.stringify(Y)}function a(Z,$){let Q=L(Z,{store:"user",log:$});if(Q===void 0)return;if(Q.sso&&typeof Q.sso==="object"&&Q.sso!==null){let Y=Q.sso;if(typeof Y.expires==="string")Y.expires=new Date(Y.expires)}return{...Q,createdAt:typeof Q.createdAt==="string"?new Date(Q.createdAt):void 0,updatedAt:typeof Q.updatedAt==="string"?new Date(Q.updatedAt):void 0}}class hZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"user-store"),this.log=F(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("user",X(Z))}idsSetKey(){return this.key(w$)}nameIndexKey(Z){return this.key(j$+X(Z))}externalIdIndexKey(Z){return this.key(m$+X(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return a($,this.log)}async getByExternalId(Z){let $=await this.redis.get(this.externalIdIndexKey(Z));return $?this.get($):void 0}async lookup(Z){return this.get(Z.id??"")}async upsert(Z){let $=Z.id?.trim()||crypto.randomUUID(),Q={...Z,id:$},Y=this.entityKey($),W=await this.redis.get(Y),V=W!=null?a(W,this.log)??null:null,G=Q.userName?.toLowerCase(),B=V?.userName?.toLowerCase(),U=Q.externalId,J=V?.externalId,O=new D;if(G)O.claimUnique(this.nameIndexKey(G),$);if(U)O.claimUnique(this.externalIdIndexKey(U),$);if(B&&B!==G)O.del(this.nameIndexKey(B));if(J&&J!==U)O.del(this.externalIdIndexKey(J));if(O.set(Y,I$(Q)),G)O.set(this.nameIndexKey(G),$);if(U)O.set(this.externalIdIndexKey(U),$);if(O.sadd(this.idsSetKey(),$),await O.exec(this.redis)==="conflict"){if(U){let A=await this.redis.get(this.externalIdIndexKey(U));if(A&&A!==$)throw new xZ(`externalId "${U}" is already in use`,"unique_violation","externalId")}throw new xZ(`userName "${Q.userName}" is already in use`,"unique_violation","userName")}return Q}async delete(Z){let $=await this.get(Z);if($==null)return 0;let Q=new D;if(Q.del(this.entityKey(Z)),$.userName)Q.del(this.nameIndexKey($.userName.toLowerCase()));if($.externalId)Q.del(this.externalIdIndexKey($.externalId));return Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),1}async list(Z){let $=h(Z),Q=(await this.redis.smembers(this.idsSetKey())).sort();if(Q.length===0)return T$(0,[],$.start??0,$.limit);let Y=Q.map((G)=>this.entityKey(G)),V=(await this.redis.mget(Y)).filter((G)=>G!=null).map((G)=>a(G,this.log)).filter((G)=>G!=null);return K(V,$)}}import{list as b$,StoreConflictError as y$}from"@ionite/core";var g$="workload-identity:ids",l$="workload-identity:client:",u$="workload-identity:external:";function p$(Z){let $=Z.createdAt??new Date,Q=Z.updatedAt??$;return JSON.stringify({...Z,createdAt:$.toISOString(),updatedAt:Q.toISOString()})}function s(Z,$){let Q=L(Z,{store:"workload-identity",log:$});if(Q===void 0)return;return{...Q,createdAt:typeof Q.createdAt==="string"?new Date(Q.createdAt):void 0,updatedAt:typeof Q.updatedAt==="string"?new Date(Q.updatedAt):void 0}}class TZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"workload-identity-store"),this.log=F(Z)}key(...Z){return C(this.prefix,...Z)}entityKey(Z){return this.key("workload-identity",X(Z))}idsSetKey(){return this.key(g$)}clientIndexKey(Z){return this.key(l$+X(Z))}externalIdIndexKey(Z){return this.key(u$+X(Z))}async get(Z){let $=await this.redis.get(this.entityKey(Z));if($==null)return;return s($,this.log)}async lookup(Z){if(Z.id){let $=await this.get(Z.id);if($)return $}if(Z.clientId){let $=await this.redis.get(this.clientIndexKey(Z.clientId));if($!=null)return this.get($)}if(Z.externalId)return this.getByExternalId(Z.externalId);return}async getByExternalId(Z){let $=await this.redis.get(this.externalIdIndexKey(Z));if($==null)return;return this.get($)}async upsert(Z){let $=Z.id?.trim()||crypto.randomUUID(),Q=this.entityKey($),Y=await this.redis.get(Q),W=null;if(Y!=null)W=s(Y,this.log)??null;let V=new Date,G={...Z,id:$,createdAt:W?.createdAt??Z.createdAt??V,updatedAt:V},B=new D;if(G.clientId)B.claimUnique(this.clientIndexKey(G.clientId),$);if(G.externalId)B.claimUnique(this.externalIdIndexKey(G.externalId),$);if(W?.clientId&&W.clientId!==G.clientId)B.del(this.clientIndexKey(W.clientId));if(W?.externalId&&W.externalId!==G.externalId)B.del(this.externalIdIndexKey(W.externalId));if(B.set(Q,p$(G)),G.clientId)B.set(this.clientIndexKey(G.clientId),$);if(G.externalId)B.set(this.externalIdIndexKey(G.externalId),$);if(B.sadd(this.idsSetKey(),$),await B.exec(this.redis)==="conflict")throw new y$(`clientId "${G.clientId}" is already in use`,"unique_violation","clientId");return G}async delete(Z){let $=await this.get(Z);if($==null)return 0;let Q=new D;if(Q.del(this.entityKey(Z)),$.clientId)Q.del(this.clientIndexKey($.clientId));if($.externalId)Q.del(this.externalIdIndexKey($.externalId));return Q.srem(this.idsSetKey(),Z),await Q.exec(this.redis),1}async list(Z){let $=h(Z),Q=(await this.redis.smembers(this.idsSetKey())).sort();if(Q.length===0)return b$(0,[],$.start??0,$.limit);let Y=Q.map((G)=>this.entityKey(G)),V=(await this.redis.mget(Y)).filter((G)=>G!=null).map((G)=>s(G,this.log)).filter((G)=>G!=null);return K(V,$)}}function c$(Z){return JSON.stringify({...Z,expires_at:Z.expires_at.toISOString(),created_at:Z.created_at.toISOString()})}function d$(Z,$){let Q=L(Z,{store:"workload-token",log:$});if(Q===void 0)return;return{...Q,expires_at:new Date(Q.expires_at),created_at:new Date(Q.created_at)}}class wZ{redis;prefix;log;constructor(Z){this.redis=Z.redis,this.prefix=_(Z,"workload-token-store"),this.log=F(Z)}key(Z){return C(this.prefix,"workload","token",X(Z))}async set(Z){let $=this.key(Z.workload_id),Q=Math.max(1,Math.floor((Z.expires_at.getTime()-Date.now())/1000));await this.redis.setex($,Q,c$(Z))}async get(Z){let $=await this.redis.get(this.key(Z));if($==null)return null;let Q=d$($,this.log);if(Q==null)return null;if(Date.now()>Q.expires_at.getTime())return await this.redis.del(this.key(Z)),null;return Q}async delete(Z){await this.redis.del(this.key(Z))}async isValid(Z){return await this.get(Z)!==null}async cleanup(){}}export{E as supportsRunScript,L$ as splitIonRedisSecret,LZ as scriptSha1,C as prefixedKey,F as getLogger,_ as getKeyPrefix,X as encodeKeyId,N$ as createRedisLfvTransport,f$ as createReactiveRedis,D$ as createEvalshaRunner,U$ as chunkedMget,m as atomicCreate,c as atomicCompareAndSet,wZ as RedisWorkloadTokenStore,TZ as RedisWorkloadIdentityStore,hZ as RedisUserStore,D as RedisTxn,kZ as RedisTenantStore,fZ as RedisSessionStore,XZ as RedisResourceStore,AZ as RedisMagicLinkStore,DZ as RedisCustomerStore,FZ as RedisAccessIndex,zZ as RedisAccessCatalogStore,JZ as RedisAccessAssignmentStore,QZ as MAX_LIST_LIMIT,B$ as DEFAULT_MGET_CHUNK_SIZE,$Z as DEFAULT_LIST_LIMIT};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ionite/redis-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24-beta.20260907.2",
|
|
4
4
|
"description": "Redis adapter interface and store implementations for ionite. Use with @ionite/redis (node-redis), @ionite/ioredis, or a custom RedisAdapter.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "ionite",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@ionite/core": "
|
|
27
|
+
"@ionite/core": "0.0.24-beta.20260907.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "^26.1.0"
|