ofplatform-rn 0.1.0-alpha.2 → 0.1.0-alpha.4
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 +5 -6
- package/dist/auth/RnServerAuthoritativeAuthHostSupport.d.ts +30 -10
- package/dist/index.esm.js +2 -2
- package/dist/index.js +2 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -9,13 +9,12 @@ React Native platform adapter package for `of*` ecosystem.
|
|
|
9
9
|
- `src/adapters/socket`: scaffold placeholder
|
|
10
10
|
- `src/adapters/storage`: scaffold placeholder
|
|
11
11
|
- `src/auth`:
|
|
12
|
-
- `RnServerAuthoritativeAuthHostSupport` (shared auth bridge
|
|
12
|
+
- `RnServerAuthoritativeAuthHostSupport` (shared auth bridge parity with `ofplatform-web`, backed by injected async storage and fetch)
|
|
13
13
|
|
|
14
|
-
Planned
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- Runtime-backed RN auth host support that fulfills the scaffolded `src/auth` surface once host adoption starts
|
|
14
|
+
Planned follow-up areas:
|
|
15
|
+
- host-specific secure-storage backend selection
|
|
16
|
+
- production SQLite driver binding for React Native runtime hosts
|
|
17
|
+
- optional native transport hardening such as certificate pinning or printer bridges
|
|
19
18
|
|
|
20
19
|
Design rule:
|
|
21
20
|
- Keep platform-specific implementation in platform packages, not in `ofcore`.
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { type AuthoritySessionEnvelope, type CachedIdentityEntry } from 'ofauth-shared-core';
|
|
2
|
+
import type { AsyncStorageBackend } from '../adapters/storage/AsyncStorageAdapter';
|
|
3
|
+
type CacheRecord = {
|
|
4
|
+
identity?: CachedIdentityEntry;
|
|
5
|
+
envelope?: AuthoritySessionEnvelope;
|
|
6
6
|
};
|
|
7
|
+
export type PlatformAuthoritySessionEnvelope = AuthoritySessionEnvelope;
|
|
7
8
|
export type RnServerAuthoritativeAuthHostSupportOptions = {
|
|
8
9
|
serverBaseUrl?: string;
|
|
9
10
|
cacheKey: string;
|
|
10
11
|
targetTenantId?: string;
|
|
11
12
|
targetBranchId?: string;
|
|
12
13
|
targetDomainId?: string;
|
|
13
|
-
storage
|
|
14
|
+
storage: AsyncStorageBackend;
|
|
14
15
|
fetchImpl?: typeof fetch;
|
|
15
16
|
isOnline?: () => boolean;
|
|
16
17
|
verifyOfflineSecret?: (params: {
|
|
@@ -18,6 +19,11 @@ export type RnServerAuthoritativeAuthHostSupportOptions = {
|
|
|
18
19
|
secret: string;
|
|
19
20
|
}) => Promise<boolean>;
|
|
20
21
|
};
|
|
22
|
+
export type AuthorityLoginTarget = {
|
|
23
|
+
targetTenantId?: string;
|
|
24
|
+
targetBranchId?: string;
|
|
25
|
+
targetDomainId?: string;
|
|
26
|
+
};
|
|
21
27
|
export type RnServerAuthoritativeLoginResult = {
|
|
22
28
|
status: 'authenticated';
|
|
23
29
|
mode?: 'online' | 'offline';
|
|
@@ -39,13 +45,27 @@ export declare class RnServerAuthoritativeAuthHostSupport {
|
|
|
39
45
|
private readonly options;
|
|
40
46
|
private readonly serverBaseUrl;
|
|
41
47
|
private readonly cacheKey;
|
|
48
|
+
private readonly targetTenantId;
|
|
49
|
+
private readonly targetBranchId;
|
|
50
|
+
private readonly targetDomainId;
|
|
51
|
+
private readonly storage;
|
|
52
|
+
private readonly fetchImpl;
|
|
53
|
+
private readonly isOnlineResolver;
|
|
54
|
+
private readonly serverBridge;
|
|
42
55
|
constructor(options: RnServerAuthoritativeAuthHostSupportOptions);
|
|
56
|
+
private performAuthorityLogin;
|
|
43
57
|
get isServerConfigured(): boolean;
|
|
44
58
|
get capability(): PlatformAuthSupportCapability;
|
|
45
59
|
get cacheNamespace(): string;
|
|
46
|
-
|
|
60
|
+
loadCacheMap(): Promise<Record<string, CacheRecord>>;
|
|
61
|
+
saveCacheMap(next: Record<string, CacheRecord>): Promise<void>;
|
|
62
|
+
readCacheRecord(principal: string): Promise<CacheRecord | null>;
|
|
63
|
+
writeCacheRecord(principal: string, record: CacheRecord): Promise<void>;
|
|
64
|
+
login(principal: string, secret: string): Promise<RnServerAuthoritativeLoginResult>;
|
|
65
|
+
loginWithTarget(principal: string, secret: string, target?: AuthorityLoginTarget): Promise<RnServerAuthoritativeLoginResult>;
|
|
47
66
|
restoreCachedEnvelope(): Promise<RnRestoredAuthEnvelope | null>;
|
|
48
|
-
logout(
|
|
49
|
-
getStoredAccessToken(
|
|
50
|
-
clearCachedSessionEnvelope(
|
|
67
|
+
logout(principal: string): Promise<void>;
|
|
68
|
+
getStoredAccessToken(principal: string): Promise<string | null>;
|
|
69
|
+
clearCachedSessionEnvelope(principal: string): Promise<void>;
|
|
51
70
|
}
|
|
71
|
+
export {};
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var
|
|
1
|
+
var T=class{static escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}static escapeLiteral(e){return`'${e.replace(/'/g,"''")}'`}static normalizeValue(e){return e==null?null:typeof e=="boolean"?e?1:0:e instanceof Date?e.toISOString():Array.isArray(e)||typeof e=="object"&&e!==null?JSON.stringify(e):e}static buildValueExpr(e,t){if(e.type==="column"){let r=e.tableAlias||t;return{sql:`${this.escapeIdentifier(r)}.${this.escapeIdentifier(e.field)}`,params:[]}}return{sql:"?",params:[this.normalizeValue(e.value)]}}static buildFieldCondition(e,t){if("field"in e){let n=e.alias||t,s=`${this.escapeIdentifier(n)}.${this.escapeIdentifier(e.field)}`,a=e.operator||"=";if(a==="BETWEEN"){if(!Array.isArray(e.value)||e.value.length!==2)throw new Error("BETWEEN requires value tuple [min,max]");return{sql:`${s} BETWEEN ? AND ?`,params:[this.normalizeValue(e.value[0]),this.normalizeValue(e.value[1])]}}if(a==="IN"||a==="NOT IN"){if(!Array.isArray(e.value))throw new Error(`${a} requires array value`);return e.value.length===0?{sql:a==="IN"?"FALSE":"TRUE",params:[]}:{sql:`${s} ${a} (${e.value.map(()=>"?").join(", ")})`,params:e.value.map(l=>this.normalizeValue(l))}}if(a==="IS NULL"||a==="IS NOT NULL")return{sql:`${s} ${a}`,params:[]};if(a==="LIKE"){let p=("likeMode"in e?e.likeMode:"default")==="case-sensitive"?" COLLATE BINARY":"";return{sql:`${s} LIKE${p} ?`,params:[this.normalizeValue(e.value)]}}return{sql:`${s} ${a} ?`,params:[this.normalizeValue(e.value)]}}let r=this.buildValueExpr(e.left,t);if(e.operator==="IS NULL"||e.operator==="IS NOT NULL")return{sql:`${r.sql} ${e.operator}`,params:r.params};let i=this.buildValueExpr(e.right,t);if(e.operator==="IN"||e.operator==="NOT IN"){if(e.right.type!=="literal"||!Array.isArray(e.right.value))throw new Error(`${e.operator} requires literal array on right side`);return e.right.value.length===0?{sql:e.operator==="IN"?"FALSE":"TRUE",params:[]}:{sql:`${r.sql} ${e.operator} (${e.right.value.map(()=>"?").join(", ")})`,params:[...r.params,...e.right.value.map(n=>this.normalizeValue(n))]}}if(e.operator==="BETWEEN"){if(e.right.type!=="literal"||!Array.isArray(e.right.value)||e.right.value.length!==2)throw new Error("BETWEEN requires literal tuple [min,max] on right side");return{sql:`${r.sql} BETWEEN ? AND ?`,params:[...r.params,this.normalizeValue(e.right.value[0]),this.normalizeValue(e.right.value[1])]}}if(e.operator==="LIKE"){let n=e.likeMode==="case-sensitive"?" COLLATE BINARY":"";return{sql:`${r.sql} LIKE${n} ${i.sql}`,params:[...r.params,...i.params]}}return{sql:`${r.sql} ${e.operator} ${i.sql}`,params:[...r.params,...i.params]}}static buildFilter(e,t="t0"){let r=e.and;if(Array.isArray(r)){let n=r.map(s=>this.buildFilter(s,t));return{sql:n.map(s=>`(${s.sql})`).join(" AND "),params:n.flatMap(s=>s.params)}}let i=e.or;if(Array.isArray(i)){let n=i.map(s=>this.buildFilter(s,t));return{sql:n.map(s=>`(${s.sql})`).join(" OR "),params:n.flatMap(s=>s.params)}}if(e!==null&&typeof e=="object"&&!Array.isArray(e)){if("left"in e||"field"in e)return this.buildFieldCondition(e,t);let n=Object.entries(e);if(n.length===0)return{sql:"TRUE",params:[]};let s=n.map(([a,l])=>({sql:`${this.escapeIdentifier(t)}.${this.escapeIdentifier(a)} = ?`,params:[this.normalizeValue(l)]}));return{sql:s.map(a=>`(${a.sql})`).join(" AND "),params:s.flatMap(a=>a.params)}}throw new Error(`Invalid filter expression: ${JSON.stringify(e)}`)}static buildGroupBy(e,t="t0"){return!e||!e.length?"":` GROUP BY ${e.map(i=>{let n=typeof i.field=="string"?{tableAlias:t,field:i.field}:i.field;return`${this.escapeIdentifier(n.tableAlias)}.${this.escapeIdentifier(n.field)}`}).join(", ")}`}static buildSort(e,t="t0"){return!e||!e.length?"":e.map(r=>{let i=typeof r.field=="string"?{tableAlias:t,field:r.field}:r.field;return`${this.escapeIdentifier(i.tableAlias)}.${this.escapeIdentifier(i.field)} ${r.direction.toUpperCase()}`}).join(", ")}static buildSelect(e,t){var u;let r=t,i=(t==null?void 0:t.mainAlias)||"t0",n=(t==null?void 0:t.joins)||[],s=[],a=[],l=[];if(t!=null&&t.aggregates&&t.aggregates.length>0)t.groupBy&&t.groupBy.forEach(o=>{let c=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field;l.push(`${this.escapeIdentifier(c.tableAlias)}.${this.escapeIdentifier(c.field)} AS ${this.escapeIdentifier(`${c.tableAlias}_${c.field}`)}`)}),t.aggregates.forEach(o=>{let c=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field,d=`${this.escapeIdentifier(c.tableAlias)}.${this.escapeIdentifier(c.field)}`;l.push(`${o.function}(${d}) AS ${this.escapeIdentifier(o.as)}`)});else if(t!=null&&t.fields){let o=0;for(let[c,d]of Object.entries(t.fields))for(let m of d){let g=((u=r==null?void 0:r.resultShape)!=null?u:"flat")==="nested"?`__c${o++}`:`${c}_${m}`;a.push({key:g,alias:c,field:m}),l.push(`${this.escapeIdentifier(c)}.${this.escapeIdentifier(m)} AS ${this.escapeIdentifier(g)}`)}}else l.push(`${this.escapeIdentifier(i)}.*`);let p=`SELECT ${l.join(", ")} FROM ${this.escapeIdentifier(e)} AS ${this.escapeIdentifier(i)}`;if(n.forEach(o=>{let c=(o.type||"inner").toUpperCase();if(c==="RIGHT"||c==="FULL")throw new Error(`RnSqliteAdapter does not support ${c} JOIN`);let d=[];o.conditions.forEach(m=>{let f=this.buildValueExpr(m.left,i),g=this.buildValueExpr(m.right,i);d.push(`${f.sql} ${m.operator} ${g.sql}`),s.push(...f.params,...g.params)}),p+=` ${c} JOIN ${this.escapeIdentifier(o.table)} AS ${this.escapeIdentifier(o.alias)} ON ${d.join(" AND ")}`}),t!=null&&t.filters){let o=this.buildFilter(t.filters,i);o.sql&&o.sql!=="TRUE"&&(p+=` WHERE ${o.sql}`,s.push(...o.params))}if(t!=null&&t.aggregates&&t.aggregates.length>0){if(p+=this.buildGroupBy(t.groupBy,i),t.having){let o=this.buildFilter(t.having,i);o.sql&&o.sql!=="TRUE"&&(p+=` HAVING ${o.sql}`,s.push(...o.params))}return{sql:p,params:s,projectionMap:a.length?a:void 0}}if(p+=this.buildGroupBy(t==null?void 0:t.groupBy,i),t!=null&&t.having){let o=this.buildFilter(t.having,i);o.sql&&o.sql!=="TRUE"&&(p+=` HAVING ${o.sql}`,s.push(...o.params))}if(t!=null&&t.sort&&t.sort.length){let o=this.buildSort(t.sort,i);o&&(p+=` ORDER BY ${o}`)}return(t==null?void 0:t.limit)!==void 0&&(p+=" LIMIT ?",s.push(t.limit)),(t==null?void 0:t.offset)!==void 0&&(p+=" OFFSET ?",s.push(t.offset)),{sql:p,params:s,projectionMap:a.length?a:void 0}}static buildInsert(e,t){let r=Object.keys(t),i=r.map(a=>this.escapeIdentifier(a)).join(", "),n=r.map(()=>"?").join(", "),s=r.map(a=>this.normalizeValue(t[a]));return{sql:`INSERT INTO ${this.escapeIdentifier(e)} (${i}) VALUES (${n})`,params:s}}static buildUpdate(e,t,r){let i=Object.keys(r);if(!i.length)throw new Error("Cannot build UPDATE with empty updates");let n=i.map(a=>`${this.escapeIdentifier(a)} = ?`).join(", "),s=i.map(a=>this.normalizeValue(r[a]));return{sql:`UPDATE ${this.escapeIdentifier(e)} SET ${n} WHERE id = ?`,params:[...s,t]}}static buildDelete(e,t){return{sql:`DELETE FROM ${this.escapeIdentifier(e)} WHERE id = ?`,params:[t]}}};var S=class{constructor(e){this.savepointDepth=0;this.schemaMap=new Map;this.metaInitialized=!1;var t;this.driver=e.driver,this.tableNamePrefix=(t=e.tableNamePrefix)!=null?t:"",this.tableNameResolver=e.tableNameMapper}setTableNameResolver(e){this.tableNameResolver=e}resolveTableName(e){return this.tableNameResolver?String(this.tableNameResolver(e)||"").trim()||e:!this.tableNamePrefix||e.startsWith(this.tableNamePrefix)?e:`${this.tableNamePrefix}${e}`}async ensureMetaInit(){this.metaInitialized||(await this.driver.execute(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS _schema_version (
|
|
3
3
|
version INTEGER NOT NULL
|
|
4
4
|
)
|
|
5
|
-
`),this.metaInitialized=!0)}async getSchemaVersion(){await this.ensureMetaInit();let e=await this.driver.execute("SELECT version FROM _schema_version LIMIT 1");return e.rows.length?Number(e.rows[0].version):(await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){await this.ensureMetaInit(),(await this.driver.execute("SELECT 1 FROM _schema_version LIMIT 1")).rows.length?await this.driver.execute("UPDATE _schema_version SET version = ?",[e]):await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${g(i.name)} ${A(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");await this.driver.execute(`CREATE TABLE IF NOT EXISTS ${g(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${g(n)} ON ${g(t)}(${g(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if((await this.driver.execute(`SELECT name FROM pragma_table_info(${y.escapeLiteral(r)})`)).rows.some(a=>a.name===t.name))return;let n=`ALTER TABLE ${g(r)} ADD COLUMN ${g(t.name)} ${A(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(await this.driver.execute(n),t.isIndexed){let a=`idx_${r}_${t.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${g(a)} ON ${g(r)}(${g(t.name)})`)}let s=this.schemaMap.get(e);s&&!s.columns.find(a=>a.name===t.name)&&(s.columns.push(t),this.schemaMap.set(e,s))}async get(e,t){var s;let r,i;return typeof t=="string"?i={id:t}:(r=t,i=r.filters),(s=(await this.query(e,{...r,filters:i,limit:1}))[0])!=null?s:null}async query(e,t){var u,m,h;let r=this.resolveTableName(e),i=(u=t==null?void 0:t.joins)!=null&&u.length?{...t,joins:t.joins.map(d=>({...d,table:this.resolveTableName(d.table)}))}:t,{sql:n,params:s,projectionMap:a}=y.buildSelect(r,i),c=(await this.driver.execute(n,s)).rows;if((m=t==null?void 0:t.aggregates)!=null&&m.length)return c;if(t!=null&&t.fields)return((h=t==null?void 0:t.resultShape)!=null?h:"flat")==="nested"&&(a!=null&&a.length)?c.map(b=>{let T={};for(let v of a)T[v.alias]||(T[v.alias]={}),T[v.alias][v.field]=b[v.key];return T}):c;let f=this.schemaMap.get(e);if(!f)return c;let o=Object.fromEntries(f.columns.map(d=>[d.name,d]));return c.map(d=>R(d,o))}async create(e,t){var o;let r=this.resolveTableName(e),{sql:i,params:n}=y.buildInsert(r,t),s=await this.driver.execute(i,n),a=(o=t==null?void 0:t.id)!=null?o:s.insertId!==void 0?String(s.insertId):void 0,p={...t};a!==void 0&&(p.id=a);let c=this.schemaMap.get(e);if(!c)return p;let f=Object.fromEntries(c.columns.map(u=>[u.name,u]));return R(p,f)}async update(e,t,r){if(!Object.keys(r).length){let p=await this.get(e,t);if(!p)throw new Error(`Record not found: ${e}#${t}`);return p}let i=this.resolveTableName(e),{sql:n,params:s}=y.buildUpdate(i,t,r);await this.driver.execute(n,s);let a=await this.get(e,t);if(!a)throw new Error(`Record not found after update: ${e}#${t}`);return a}async delete(e,t){let r=this.resolveTableName(e),{sql:i,params:n}=y.buildDelete(r,t);await this.driver.execute(i,n)}async bulkCreate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)i.push(await r.create(e,n));return i}):[]}async bulkUpdate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)Object.keys(n.updates).length&&i.push(await r.update(e,n.id,n.updates));return i}):[]}async transaction(e){let t=this.savepointDepth===0,r=t?"BEGIN":`SAVEPOINT sp${this.savepointDepth}`;await this.driver.execute(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return await this.driver.execute(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{await this.driver.execute(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};function g(l){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(l))throw new Error(`Invalid identifier: "${l}"`);return`"${l}"`}function A(l){switch(l){case"string":return"TEXT";case"string[]":return"TEXT";case"number":return"REAL";case"boolean":return"INTEGER";case"json":return"TEXT";case"date":return"TEXT";default:return"TEXT"}}function R(l,e){let t={};for(let[r,i]of Object.entries(l)){let n=e[r],s=i;if(i!=null&&n){if(n.type==="boolean")s=!!i;else if(n.type==="date"&&typeof i=="string"){let a=new Date(i);Number.isNaN(a.getTime())||(s=a)}else if((n.type==="json"||n.type==="string[]")&&typeof i=="string")try{s=JSON.parse(i)}catch{}}t[r]=s}return t}var _=!0;var w=class{constructor(e){this.documentsPath=e.documentsPath.replace(/\/$/,""),this.backend=e.backend}getDocumentPath(e){return`${this.documentsPath}/${e}`}async writeFile(e,t){await this.backend.writeFile(e,t)}async share(e){var t,r;await((r=(t=this.backend).share)==null?void 0:r.call(t,e))}};function P(l,e){if(!e||Object.keys(e).length===0)return l;let t=new URLSearchParams;for(let[i,n]of Object.entries(e))n!=null&&t.set(i,String(n));let r=t.toString();return r?l.includes("?")?`${l}&${r}`:`${l}?${r}`:l}var I=class{constructor(e={}){let t=e.fetch;if(t)this.fetchImpl=t;else{let r=globalThis.fetch;if(typeof r!="function")throw new Error("RnFetchHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch.");this.fetchImpl=r}}async request(e){var n,s;let t=P(e.url,e.query),r=typeof AbortController!="undefined"?new AbortController:null,i=r&&e.timeoutMs?setTimeout(()=>r.abort(),e.timeoutMs):null;try{let a=e.body!==void 0&&e.body!==null,p={...(n=e.headers)!=null?n:{}};a&&!p["content-type"]&&!p["Content-Type"]&&(p["content-type"]="application/json");let c=await this.fetchImpl(t,{method:e.method,headers:p,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),f={};c.headers.forEach((m,h)=>{f[h.toLowerCase()]=m});let u=((s=f["content-type"])!=null?s:"").includes("application/json")?await c.json():await c.text();return{status:c.status,headers:f,data:u}}finally{i!==null&&clearTimeout(i)}}};var Q=!0;var O=class{constructor(e){this.backend=e.backend}configure(e){var t,r;(r=(t=this.backend).configure)==null||r.call(t,e)}createChannel(e){var t,r;(r=(t=this.backend).createChannel)==null||r.call(t,e)}localNotification(e){this.backend.localNotification(e)}};async function C(l){let t=new TextEncoder().encode(l),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(n=>n.toString(16).padStart(2,"0")).join("")}var $=class{constructor(e={}){this.envVars=e.envVars,this.isOnlineFn=e.isOnline,this.hashPinFn=e.hashPin}getEnvVar(e){var r;if(this.envVars)return this.envVars[e];let t=globalThis.process;return(r=t==null?void 0:t.env)==null?void 0:r[e]}isOnline(){if(this.isOnlineFn)return this.isOnlineFn();let e=globalThis.navigator;return e&&typeof e.onLine=="boolean"?e.onLine:!0}async hashPin(e){var r;if(this.hashPinFn)return this.hashPinFn(e);if((r=globalThis.crypto)==null?void 0:r.subtle)return C(e);throw new Error("RnPlatformAdapter: crypto.subtle tidak tersedia di runtime ini. Injeksikan implementasi hashPin via options.hashPin (misalnya @noble/hashes atau expo-crypto).")}async verifyPin(e,t){return await this.hashPin(e)===t}};function L(l){let e=l.query;if(!e||Object.keys(e).length===0)return l.url;let r=new URLSearchParams(e).toString();return l.url.includes("?")?`${l.url}&${r}`:`${l.url}?${r}`}var x=class{constructor(e={}){this.ws=null;this.connectionOptions=null;this.listeners=new Map;this.reconnectAttempts=0;this.reconnectTimeout=null;this.intentionalClose=!1;var r,i,n,s,a;this.reconnect=(r=e.reconnect)!=null?r:!0,this.maxReconnectAttempts=Math.max(0,(i=e.maxReconnectAttempts)!=null?i:5),this.reconnectDelayMs=Math.max(0,(n=e.reconnectDelayMs)!=null?n:500),this.maxReconnectDelayMs=Math.max(this.reconnectDelayMs,(s=e.maxReconnectDelayMs)!=null?s:3e4);let t=(a=e.webSocket)!=null?a:globalThis.WebSocket;if(typeof t!="function")throw new Error("RnWebSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket.");this.WebSocketCtor=t}connect(e){return this.connectionOptions=e,this.intentionalClose=!1,this.reconnectAttempts=0,this.openConnection(e)}async disconnect(){this.intentionalClose=!0,this.clearReconnectTimeout(),this.ws&&(this.ws.close(1e3,"client disconnect"),this.ws=null)}subscribe(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e))}}async publish(e,t){var i,n;if(!this.ws||this.ws.readyState!==this.ws.OPEN)throw new Error(`RnWebSocketAdapter: cannot publish "${e}" \u2014 not connected (readyState=${(n=(i=this.ws)==null?void 0:i.readyState)!=null?n:"null"}).`);let r={event:e,payload:t};this.ws.send(JSON.stringify(r))}isConnected(){return this.ws!==null&&this.ws.readyState===this.ws.OPEN}openConnection(e){return new Promise((t,r)=>{let i=L(e),n;try{n=new this.WebSocketCtor(i)}catch(s){r(s instanceof Error?s:new Error(String(s)));return}n.onopen=()=>{this.ws=n,this.reconnectAttempts=0,t()},n.onerror=()=>{this.ws||r(new Error("RnWebSocketAdapter: connection failed"))},n.onclose=()=>{this.ws===n&&(this.ws=null),!this.intentionalClose&&this.reconnect&&this.connectionOptions&&this.reconnectAttempts<this.maxReconnectAttempts&&this.scheduleReconnect()},n.onmessage=s=>{this.handleMessage(s.data)}})}handleMessage(e){if(typeof e!="string")return;let t;try{t=JSON.parse(e)}catch{return}if(typeof t!="object"||t===null||typeof t.event!="string")return;let{event:r,payload:i}=t,n=this.listeners.get(r);if(n)for(let s of n)try{s(i)}catch{}}scheduleReconnect(){this.clearReconnectTimeout();let e=++this.reconnectAttempts,t=Math.min(this.reconnectDelayMs*Math.pow(2,e-1),this.maxReconnectDelayMs);this.reconnectTimeout=setTimeout(()=>{!this.intentionalClose&&this.connectionOptions&&this.openConnection(this.connectionOptions).catch(()=>{})},t)}clearReconnectTimeout(){this.reconnectTimeout!==null&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null)}};var ie=!0;var N=class{constructor(e){this.store=e.storage}getItem(e){return this.store.getItem(e)}setItem(e,t){return this.store.setItem(e,t)}removeItem(e){return this.store.removeItem(e)}};var oe=!0;var E="OFPLATFORM_RN_AUTH_NOT_IMPLEMENTED: auth host support surface is aligned with ofplatform-web, but runtime implementation is intentionally pending host adoption.",M={platform:"react-native",implemented:!1,notes:"API scaffold aligned with ofplatform-web. Runtime implementation stays pending until a React Native host adopts the shared auth bridge boundary."},k=class{constructor(e){this.options=e;var t;this.serverBaseUrl=((t=e.serverBaseUrl)!=null?t:"").trim().replace(/\/+$/,""),this.cacheKey=e.cacheKey.trim()}get isServerConfigured(){return this.serverBaseUrl.length>0}get capability(){return M}get cacheNamespace(){return this.cacheKey}async login(e,t){throw new Error(E)}async restoreCachedEnvelope(){throw new Error(E)}async logout(e){throw new Error(E)}getStoredAccessToken(e){return null}clearCachedSessionEnvelope(e){}};var de={platform:"react-native",ready:!0,notes:["All adapter domains implemented:","RnSqliteAdapter (db, injectable driver),","RnExportAdapter (export, injectable backend),","RnFetchHttpAdapter (http),","RnNotificationAdapter (notification, injectable backend),","RnPlatformAdapter (platform, injectable hashPin/isOnline/envVars),","RnWebSocketAdapter (socket),","AsyncStorageAdapter (storage).","Auth bridge surface is scaffolded for parity with ofplatform-web."].join(" ")};export{N as AsyncStorageAdapter,M as OFPLATFORM_RN_AUTH_STATUS,_ as OFPLATFORM_RN_DB_ADAPTERS_READY,Q as OFPLATFORM_RN_HTTP_ADAPTERS_READY,ie as OFPLATFORM_RN_SOCKET_ADAPTERS_READY,de as OFPLATFORM_RN_STATUS,oe as OFPLATFORM_RN_STORAGE_ADAPTERS_READY,w as RnExportAdapter,I as RnFetchHttpAdapter,O as RnNotificationAdapter,$ as RnPlatformAdapter,k as RnServerAuthoritativeAuthHostSupport,S as RnSqliteAdapter,y as RnSqliteQueryBuilder,x as RnWebSocketAdapter};
|
|
5
|
+
`),this.metaInitialized=!0)}async getSchemaVersion(){await this.ensureMetaInit();let e=await this.driver.execute("SELECT version FROM _schema_version LIMIT 1");return e.rows.length?Number(e.rows[0].version):(await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){await this.ensureMetaInit(),(await this.driver.execute("SELECT 1 FROM _schema_version LIMIT 1")).rows.length?await this.driver.execute("UPDATE _schema_version SET version = ?",[e]):await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${v(i.name)} ${w(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");await this.driver.execute(`CREATE TABLE IF NOT EXISTS ${v(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${v(n)} ON ${v(t)}(${v(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if((await this.driver.execute(`SELECT name FROM pragma_table_info(${T.escapeLiteral(r)})`)).rows.some(a=>a.name===t.name))return;let n=`ALTER TABLE ${v(r)} ADD COLUMN ${v(t.name)} ${w(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(await this.driver.execute(n),t.isIndexed){let a=`idx_${r}_${t.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${v(a)} ON ${v(r)}(${v(t.name)})`)}let s=this.schemaMap.get(e);s&&!s.columns.find(a=>a.name===t.name)&&(s.columns.push(t),this.schemaMap.set(e,s))}async get(e,t){var s;let r,i;return typeof t=="string"?i={id:t}:(r=t,i=r.filters),(s=(await this.query(e,{...r,filters:i,limit:1}))[0])!=null?s:null}async query(e,t){var c,d,m;let r=this.resolveTableName(e),i=(c=t==null?void 0:t.joins)!=null&&c.length?{...t,joins:t.joins.map(f=>({...f,table:this.resolveTableName(f.table)}))}:t,{sql:n,params:s,projectionMap:a}=T.buildSelect(r,i),p=(await this.driver.execute(n,s)).rows;if((d=t==null?void 0:t.aggregates)!=null&&d.length)return p;if(t!=null&&t.fields)return((m=t==null?void 0:t.resultShape)!=null?m:"flat")==="nested"&&(a!=null&&a.length)?p.map(g=>{let y={};for(let b of a)y[b.alias]||(y[b.alias]={}),y[b.alias][b.field]=g[b.key];return y}):p;let u=this.schemaMap.get(e);if(!u)return p;let o=Object.fromEntries(u.columns.map(f=>[f.name,f]));return p.map(f=>I(f,o))}async create(e,t){var o;let r=this.resolveTableName(e),{sql:i,params:n}=T.buildInsert(r,t),s=await this.driver.execute(i,n),a=(o=t==null?void 0:t.id)!=null?o:s.insertId!==void 0?String(s.insertId):void 0,l={...t};a!==void 0&&(l.id=a);let p=this.schemaMap.get(e);if(!p)return l;let u=Object.fromEntries(p.columns.map(c=>[c.name,c]));return I(l,u)}async update(e,t,r){if(!Object.keys(r).length){let l=await this.get(e,t);if(!l)throw new Error(`Record not found: ${e}#${t}`);return l}let i=this.resolveTableName(e),{sql:n,params:s}=T.buildUpdate(i,t,r);await this.driver.execute(n,s);let a=await this.get(e,t);if(!a)throw new Error(`Record not found after update: ${e}#${t}`);return a}async delete(e,t){let r=this.resolveTableName(e),{sql:i,params:n}=T.buildDelete(r,t);await this.driver.execute(i,n)}async bulkCreate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)i.push(await r.create(e,n));return i}):[]}async bulkUpdate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)Object.keys(n.updates).length&&i.push(await r.update(e,n.id,n.updates));return i}):[]}async transaction(e){let t=this.savepointDepth===0,r=t?"BEGIN":`SAVEPOINT sp${this.savepointDepth}`;await this.driver.execute(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return await this.driver.execute(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{await this.driver.execute(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};function v(h){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(h))throw new Error(`Invalid identifier: "${h}"`);return`"${h}"`}function w(h){switch(h){case"string":return"TEXT";case"string[]":return"TEXT";case"number":return"REAL";case"boolean":return"INTEGER";case"json":return"TEXT";case"date":return"TEXT";default:return"TEXT"}}function I(h,e){let t={};for(let[r,i]of Object.entries(h)){let n=e[r],s=i;if(i!=null&&n){if(n.type==="boolean")s=!!i;else if(n.type==="date"&&typeof i=="string"){let a=new Date(i);Number.isNaN(a.getTime())||(s=a)}else if((n.type==="json"||n.type==="string[]")&&typeof i=="string")try{s=JSON.parse(i)}catch{}}t[r]=s}return t}var U=!0;var E=class{constructor(e){this.documentsPath=e.documentsPath.replace(/\/$/,""),this.backend=e.backend}getDocumentPath(e){return`${this.documentsPath}/${e}`}async writeFile(e,t){await this.backend.writeFile(e,t)}async share(e){var t,r;await((r=(t=this.backend).share)==null?void 0:r.call(t,e))}};function P(h,e){if(!e||Object.keys(e).length===0)return h;let t=new URLSearchParams;for(let[i,n]of Object.entries(e))n!=null&&t.set(i,String(n));let r=t.toString();return r?h.includes("?")?`${h}&${r}`:`${h}?${r}`:h}var O=class{constructor(e={}){let t=e.fetch;if(t)this.fetchImpl=t;else{let r=globalThis.fetch;if(typeof r!="function")throw new Error("RnFetchHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch.");this.fetchImpl=r}}async request(e){var n,s;let t=P(e.url,e.query),r=typeof AbortController!="undefined"?new AbortController:null,i=r&&e.timeoutMs?setTimeout(()=>r.abort(),e.timeoutMs):null;try{let a=e.body!==void 0&&e.body!==null,l={...(n=e.headers)!=null?n:{}};a&&!l["content-type"]&&!l["Content-Type"]&&(l["content-type"]="application/json");let p=await this.fetchImpl(t,{method:e.method,headers:l,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),u={};p.headers.forEach((d,m)=>{u[m.toLowerCase()]=d});let c=((s=u["content-type"])!=null?s:"").includes("application/json")?await p.json():await p.text();return{status:p.status,headers:u,data:c}}finally{i!==null&&clearTimeout(i)}}};var K=!0;var k=class{constructor(e){this.backend=e.backend}configure(e){var t,r;(r=(t=this.backend).configure)==null||r.call(t,e)}createChannel(e){var t,r;(r=(t=this.backend).createChannel)==null||r.call(t,e)}localNotification(e){this.backend.localNotification(e)}};async function D(h){let t=new TextEncoder().encode(h),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(n=>n.toString(16).padStart(2,"0")).join("")}var x=class{constructor(e={}){this.envVars=e.envVars,this.isOnlineFn=e.isOnline,this.hashPinFn=e.hashPin}getEnvVar(e){var r;if(this.envVars)return this.envVars[e];let t=globalThis.process;return(r=t==null?void 0:t.env)==null?void 0:r[e]}isOnline(){if(this.isOnlineFn)return this.isOnlineFn();let e=globalThis.navigator;return e&&typeof e.onLine=="boolean"?e.onLine:!0}async hashPin(e){var r;if(this.hashPinFn)return this.hashPinFn(e);if((r=globalThis.crypto)==null?void 0:r.subtle)return D(e);throw new Error("RnPlatformAdapter: crypto.subtle tidak tersedia di runtime ini. Injeksikan implementasi hashPin via options.hashPin (misalnya @noble/hashes atau expo-crypto).")}async verifyPin(e,t){return await this.hashPin(e)===t}};function L(h){let e=h.query;if(!e||Object.keys(e).length===0)return h.url;let r=new URLSearchParams(e).toString();return h.url.includes("?")?`${h.url}&${r}`:`${h.url}?${r}`}var C=class{constructor(e={}){this.ws=null;this.connectionOptions=null;this.listeners=new Map;this.reconnectAttempts=0;this.reconnectTimeout=null;this.intentionalClose=!1;var r,i,n,s,a;this.reconnect=(r=e.reconnect)!=null?r:!0,this.maxReconnectAttempts=Math.max(0,(i=e.maxReconnectAttempts)!=null?i:5),this.reconnectDelayMs=Math.max(0,(n=e.reconnectDelayMs)!=null?n:500),this.maxReconnectDelayMs=Math.max(this.reconnectDelayMs,(s=e.maxReconnectDelayMs)!=null?s:3e4);let t=(a=e.webSocket)!=null?a:globalThis.WebSocket;if(typeof t!="function")throw new Error("RnWebSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket.");this.WebSocketCtor=t}connect(e){return this.connectionOptions=e,this.intentionalClose=!1,this.reconnectAttempts=0,this.openConnection(e)}async disconnect(){this.intentionalClose=!0,this.clearReconnectTimeout(),this.ws&&(this.ws.close(1e3,"client disconnect"),this.ws=null)}subscribe(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e))}}async publish(e,t){var i,n;if(!this.ws||this.ws.readyState!==this.ws.OPEN)throw new Error(`RnWebSocketAdapter: cannot publish "${e}" \u2014 not connected (readyState=${(n=(i=this.ws)==null?void 0:i.readyState)!=null?n:"null"}).`);let r={event:e,payload:t};this.ws.send(JSON.stringify(r))}isConnected(){return this.ws!==null&&this.ws.readyState===this.ws.OPEN}openConnection(e){return new Promise((t,r)=>{let i=L(e),n;try{n=new this.WebSocketCtor(i)}catch(s){r(s instanceof Error?s:new Error(String(s)));return}n.onopen=()=>{this.ws=n,this.reconnectAttempts=0,t()},n.onerror=()=>{this.ws||r(new Error("RnWebSocketAdapter: connection failed"))},n.onclose=()=>{this.ws===n&&(this.ws=null),!this.intentionalClose&&this.reconnect&&this.connectionOptions&&this.reconnectAttempts<this.maxReconnectAttempts&&this.scheduleReconnect()},n.onmessage=s=>{this.handleMessage(s.data)}})}handleMessage(e){if(typeof e!="string")return;let t;try{t=JSON.parse(e)}catch{return}if(typeof t!="object"||t===null||typeof t.event!="string")return;let{event:r,payload:i}=t,n=this.listeners.get(r);if(n)for(let s of n)try{s(i)}catch{}}scheduleReconnect(){this.clearReconnectTimeout();let e=++this.reconnectAttempts,t=Math.min(this.reconnectDelayMs*Math.pow(2,e-1),this.maxReconnectDelayMs);this.reconnectTimeout=setTimeout(()=>{!this.intentionalClose&&this.connectionOptions&&this.openConnection(this.connectionOptions).catch(()=>{})},t)}clearReconnectTimeout(){this.reconnectTimeout!==null&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null)}};var ae=!0;var $=class{constructor(e){this.store=e.storage}getItem(e){return this.store.getItem(e)}setItem(e,t){return this.store.setItem(e,t)}removeItem(e){return this.store.removeItem(e)}};var ue=!0;import{AuthRejectionError as A,createServerAuthoritativeAuthBridge as B}from"ofauth-shared-core";var M=6e4;function R(h,e){var i,n,s,a,l;let t=new Date().toISOString(),r=h&&typeof h=="object"?h:{};return{sessionId:String((i=r.sessionId)!=null?i:""),identityId:String((n=r.identityId)!=null?n:""),assuranceLevel:String((s=r.assuranceLevel)!=null?s:"basic"),issuedAt:String((a=r.issuedAt)!=null?a:t),expiresAt:String((l=r.expiresAt)!=null?l:e)}}var q={platform:"react-native",implemented:!0,notes:"Runtime implementation aligned with ofplatform-web using injected async storage, fetch, and offline verifier dependencies."},N=class{constructor(e){this.options=e;var i,n,s,a,l,p;if(this.serverBaseUrl=((i=e.serverBaseUrl)!=null?i:"").trim().replace(/\/+$/,""),this.cacheKey=e.cacheKey.trim(),this.targetTenantId=((n=e.targetTenantId)==null?void 0:n.trim())||"",this.targetBranchId=((s=e.targetBranchId)==null?void 0:s.trim())||"",this.targetDomainId=((a=e.targetDomainId)==null?void 0:a.trim())||"",this.storage=e.storage,e.fetchImpl)this.fetchImpl=e.fetchImpl;else if(typeof globalThis.fetch=="function")this.fetchImpl=globalThis.fetch.bind(globalThis);else throw new Error("RnServerAuthoritativeAuthHostSupport requires a fetch implementation");if(this.isOnlineResolver=(l=e.isOnline)!=null?l:(()=>!0),!this.serverBaseUrl){this.serverBridge=null;return}let t={login:async({principal:u,secret:o})=>{var f,g,y,b;let c=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({principal:u,secret:o,...this.targetTenantId?{targetTenantId:this.targetTenantId}:{},...this.targetBranchId?{targetBranchId:this.targetBranchId}:{},...this.targetDomainId?{targetDomainId:this.targetDomainId}:{}})}),d=await c.json().catch(()=>({}));if(!c.ok)throw new A(String((f=d.code)!=null?f:"AUTH_UNAUTHORIZED"));let m=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((g=d.accessToken)!=null?g:""),refreshToken:String((y=d.refreshToken)!=null?y:""),session:R(d.session,m),activeContext:(b=d.activeContext)!=null?b:null,activeRoleRef:d.activeRoleRef==null?"":String(d.activeRoleRef)}},refresh:async({refreshToken:u})=>{var m,f,g,y;let o=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:u})}),c=await o.json().catch(()=>({}));if(!o.ok)throw new A(String((m=c.code)!=null?m:"AUTH_UNAUTHORIZED"));let d=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((f=c.accessToken)!=null?f:""),refreshToken:String((g=c.refreshToken)!=null?g:""),session:R(c.session,d),activeContext:(y=c.activeContext)!=null?y:null}},logout:async({accessToken:u,refreshToken:o})=>{let c={"Content-Type":"application/json"};u&&(c.Authorization=`Bearer ${u}`),await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/logout`,{method:"POST",headers:c,body:JSON.stringify({refreshToken:o})}).catch(()=>{})}},r={getCachedIdentity:async u=>{var o,c;return(c=(o=await this.readCacheRecord(u))==null?void 0:o.identity)!=null?c:null},setCachedIdentity:async u=>{let o=await this.readCacheRecord(u.principal);await this.writeCacheRecord(u.principal,{...o,identity:u})},clearCachedIdentity:async u=>{let o=await this.readCacheRecord(u);o&&await this.writeCacheRecord(u,{...o,identity:void 0})},getSessionEnvelope:async u=>{var o,c;return(c=(o=await this.readCacheRecord(u))==null?void 0:o.envelope)!=null?c:null},setSessionEnvelope:async(u,o)=>{let c=await this.readCacheRecord(u);await this.writeCacheRecord(u,{...c,envelope:o})},clearSessionEnvelope:async u=>{let o=await this.readCacheRecord(u);o&&await this.writeCacheRecord(u,{...o,envelope:void 0})}};this.serverBridge=B({authority:t,cache:r,isOnline:()=>this.isOnlineResolver(),verifyOfflineSecret:(p=this.options.verifyOfflineSecret)!=null?p:(async()=>!1)})}async performAuthorityLogin(e,t,r){var u,o,c,d,m,f,g;let i=((u=r==null?void 0:r.targetTenantId)==null?void 0:u.trim())||this.targetTenantId,n=((o=r==null?void 0:r.targetBranchId)==null?void 0:o.trim())||this.targetBranchId,s=((c=r==null?void 0:r.targetDomainId)==null?void 0:c.trim())||this.targetDomainId,a=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({principal:e,secret:t,...i?{targetTenantId:i}:{},...n?{targetBranchId:n}:{},...s?{targetDomainId:s}:{}})}),l=await a.json().catch(()=>({}));if(!a.ok)throw new A(String((d=l.code)!=null?d:"AUTH_UNAUTHORIZED"));let p=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((m=l.accessToken)!=null?m:""),refreshToken:String((f=l.refreshToken)!=null?f:""),session:R(l.session,p),activeContext:(g=l.activeContext)!=null?g:null,activeRoleRef:l.activeRoleRef==null?"":String(l.activeRoleRef)}}get isServerConfigured(){return this.serverBaseUrl.length>0}get capability(){return q}get cacheNamespace(){return this.cacheKey}async loadCacheMap(){try{let e=await this.storage.getItem(this.cacheKey);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}async saveCacheMap(e){try{await this.storage.setItem(this.cacheKey,JSON.stringify(e))}catch{}}async readCacheRecord(e){var r;return(r=(await this.loadCacheMap())[e])!=null?r:null}async writeCacheRecord(e,t){let r=await this.loadCacheMap(),i={};t.identity&&(i.identity=t.identity),t.envelope&&(i.envelope=t.envelope),!i.identity&&!i.envelope?delete r[e]:r[e]=i,await this.saveCacheMap(r)}async login(e,t){var i,n;if(!this.serverBridge)return{status:"rejected",reasonCode:"AUTH_BRIDGE_NOT_CONFIGURED"};let r=await this.serverBridge.login({principal:e,secret:t,verifyMethod:"pin"});return r.status==="authenticated"?{status:"authenticated",mode:(i=r.mode)!=null?i:"online"}:{status:"rejected",reasonCode:(n=r.reasonCode)!=null?n:"AUTH_UNAUTHORIZED"}}async loginWithTarget(e,t,r){var i,n,s;if(!this.serverBridge||!this.serverBaseUrl)return{status:"rejected",reasonCode:"AUTH_BRIDGE_NOT_CONFIGURED"};try{let a=await this.performAuthorityLogin(e,t,r),l=(i=await this.readCacheRecord(e))!=null?i:{};return await this.writeCacheRecord(e,{...l,envelope:{principal:e,accessToken:a.accessToken,refreshToken:a.refreshToken,assuranceLevel:a.session.assuranceLevel,issuedAt:a.session.issuedAt,expiresAt:a.session.expiresAt,activeRoleRef:(n=a.activeRoleRef)!=null?n:null,activeContext:(s=a.activeContext)!=null?s:null}}),{status:"authenticated",mode:"online"}}catch(a){return{status:"rejected",reasonCode:a instanceof A?a.code:"AUTH_AUTHORITY_UNAVAILABLE"}}}async restoreCachedEnvelope(){var t,r,i;let e=await this.loadCacheMap();for(let n of Object.keys(e)){let s=(t=e[n])==null?void 0:t.envelope;if(!s)continue;let a=Date.parse(s.expiresAt),l=Number.isFinite(a),p=!l||a<=Date.now()+M;if(this.isOnlineResolver()&&p&&s.refreshToken&&this.serverBaseUrl)try{let u=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:s.refreshToken})}),o=await u.json().catch(()=>({}));if(u.ok&&o.accessToken){let c={...s,accessToken:String(o.accessToken),refreshToken:o.refreshToken?String(o.refreshToken):s.refreshToken,activeContext:(i=(r=o.activeContext)!=null?r:s.activeContext)!=null?i:null};return await this.writeCacheRecord(n,{...e[n],envelope:c}),{principal:n,envelope:c}}}catch{}if(l&&a>Date.now())return{principal:n,envelope:s}}return null}async logout(e){this.serverBridge&&await this.serverBridge.logout(e)}async getStoredAccessToken(e){var t,r,i;return(i=(r=(t=await this.readCacheRecord(e))==null?void 0:t.envelope)==null?void 0:r.accessToken)!=null?i:null}async clearCachedSessionEnvelope(e){let t=await this.readCacheRecord(e);t&&await this.writeCacheRecord(e,{...t,envelope:void 0})}};var ye={platform:"react-native",ready:!0,notes:["All adapter domains implemented:","RnSqliteAdapter (db, injectable driver),","RnExportAdapter (export, injectable backend),","RnFetchHttpAdapter (http),","RnNotificationAdapter (notification, injectable backend),","RnPlatformAdapter (platform, injectable hashPin/isOnline/envVars),","RnWebSocketAdapter (socket),","AsyncStorageAdapter (storage).","Auth bridge runtime is implemented for parity with ofplatform-web."].join(" ")};export{$ as AsyncStorageAdapter,q as OFPLATFORM_RN_AUTH_STATUS,U as OFPLATFORM_RN_DB_ADAPTERS_READY,K as OFPLATFORM_RN_HTTP_ADAPTERS_READY,ae as OFPLATFORM_RN_SOCKET_ADAPTERS_READY,ye as OFPLATFORM_RN_STATUS,ue as OFPLATFORM_RN_STORAGE_ADAPTERS_READY,E as RnExportAdapter,O as RnFetchHttpAdapter,k as RnNotificationAdapter,x as RnPlatformAdapter,N as RnServerAuthoritativeAuthHostSupport,S as RnSqliteAdapter,T as RnSqliteQueryBuilder,C as RnWebSocketAdapter};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var R=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var q=(l,e)=>{for(var t in e)R(l,t,{get:e[t],enumerable:!0})},F=(l,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of B(e))!M.call(l,i)&&i!==t&&R(l,i,{get:()=>e[i],enumerable:!(r=L(e,i))||r.enumerable});return l};var _=l=>F(R({},"__esModule",{value:!0}),l);var K={};q(K,{AsyncStorageAdapter:()=>x,OFPLATFORM_RN_AUTH_STATUS:()=>D,OFPLATFORM_RN_DB_ADAPTERS_READY:()=>j,OFPLATFORM_RN_HTTP_ADAPTERS_READY:()=>V,OFPLATFORM_RN_SOCKET_ADAPTERS_READY:()=>z,OFPLATFORM_RN_STATUS:()=>G,OFPLATFORM_RN_STORAGE_ADAPTERS_READY:()=>Q,RnExportAdapter:()=>w,RnFetchHttpAdapter:()=>I,RnNotificationAdapter:()=>E,RnPlatformAdapter:()=>O,RnServerAuthoritativeAuthHostSupport:()=>$,RnSqliteAdapter:()=>S,RnSqliteQueryBuilder:()=>b,RnWebSocketAdapter:()=>k});module.exports=_(K);var b=class{static escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}static escapeLiteral(e){return`'${e.replace(/'/g,"''")}'`}static normalizeValue(e){return e==null?null:typeof e=="boolean"?e?1:0:e instanceof Date?e.toISOString():Array.isArray(e)||typeof e=="object"&&e!==null?JSON.stringify(e):e}static buildValueExpr(e,t){if(e.type==="column"){let r=e.tableAlias||t;return{sql:`${this.escapeIdentifier(r)}.${this.escapeIdentifier(e.field)}`,params:[]}}return{sql:"?",params:[this.normalizeValue(e.value)]}}static buildFieldCondition(e,t){if("field"in e){let n=e.alias||t,s=`${this.escapeIdentifier(n)}.${this.escapeIdentifier(e.field)}`,a=e.operator||"=";if(a==="BETWEEN"){if(!Array.isArray(e.value)||e.value.length!==2)throw new Error("BETWEEN requires value tuple [min,max]");return{sql:`${s} BETWEEN ? AND ?`,params:[this.normalizeValue(e.value[0]),this.normalizeValue(e.value[1])]}}if(a==="IN"||a==="NOT IN"){if(!Array.isArray(e.value))throw new Error(`${a} requires array value`);return e.value.length===0?{sql:a==="IN"?"FALSE":"TRUE",params:[]}:{sql:`${s} ${a} (${e.value.map(()=>"?").join(", ")})`,params:e.value.map(u=>this.normalizeValue(u))}}if(a==="IS NULL"||a==="IS NOT NULL")return{sql:`${s} ${a}`,params:[]};if(a==="LIKE"){let p=("likeMode"in e?e.likeMode:"default")==="case-sensitive"?" COLLATE BINARY":"";return{sql:`${s} LIKE${p} ?`,params:[this.normalizeValue(e.value)]}}return{sql:`${s} ${a} ?`,params:[this.normalizeValue(e.value)]}}let r=this.buildValueExpr(e.left,t);if(e.operator==="IS NULL"||e.operator==="IS NOT NULL")return{sql:`${r.sql} ${e.operator}`,params:r.params};let i=this.buildValueExpr(e.right,t);if(e.operator==="IN"||e.operator==="NOT IN"){if(e.right.type!=="literal"||!Array.isArray(e.right.value))throw new Error(`${e.operator} requires literal array on right side`);return e.right.value.length===0?{sql:e.operator==="IN"?"FALSE":"TRUE",params:[]}:{sql:`${r.sql} ${e.operator} (${e.right.value.map(()=>"?").join(", ")})`,params:[...r.params,...e.right.value.map(n=>this.normalizeValue(n))]}}if(e.operator==="BETWEEN"){if(e.right.type!=="literal"||!Array.isArray(e.right.value)||e.right.value.length!==2)throw new Error("BETWEEN requires literal tuple [min,max] on right side");return{sql:`${r.sql} BETWEEN ? AND ?`,params:[...r.params,this.normalizeValue(e.right.value[0]),this.normalizeValue(e.right.value[1])]}}if(e.operator==="LIKE"){let n=e.likeMode==="case-sensitive"?" COLLATE BINARY":"";return{sql:`${r.sql} LIKE${n} ${i.sql}`,params:[...r.params,...i.params]}}return{sql:`${r.sql} ${e.operator} ${i.sql}`,params:[...r.params,...i.params]}}static buildFilter(e,t="t0"){let r=e.and;if(Array.isArray(r)){let n=r.map(s=>this.buildFilter(s,t));return{sql:n.map(s=>`(${s.sql})`).join(" AND "),params:n.flatMap(s=>s.params)}}let i=e.or;if(Array.isArray(i)){let n=i.map(s=>this.buildFilter(s,t));return{sql:n.map(s=>`(${s.sql})`).join(" OR "),params:n.flatMap(s=>s.params)}}if(e!==null&&typeof e=="object"&&!Array.isArray(e)){if("left"in e||"field"in e)return this.buildFieldCondition(e,t);let n=Object.entries(e);if(n.length===0)return{sql:"TRUE",params:[]};let s=n.map(([a,u])=>({sql:`${this.escapeIdentifier(t)}.${this.escapeIdentifier(a)} = ?`,params:[this.normalizeValue(u)]}));return{sql:s.map(a=>`(${a.sql})`).join(" AND "),params:s.flatMap(a=>a.params)}}throw new Error(`Invalid filter expression: ${JSON.stringify(e)}`)}static buildGroupBy(e,t="t0"){return!e||!e.length?"":` GROUP BY ${e.map(i=>{let n=typeof i.field=="string"?{tableAlias:t,field:i.field}:i.field;return`${this.escapeIdentifier(n.tableAlias)}.${this.escapeIdentifier(n.field)}`}).join(", ")}`}static buildSort(e,t="t0"){return!e||!e.length?"":e.map(r=>{let i=typeof r.field=="string"?{tableAlias:t,field:r.field}:r.field;return`${this.escapeIdentifier(i.tableAlias)}.${this.escapeIdentifier(i.field)} ${r.direction.toUpperCase()}`}).join(", ")}static buildSelect(e,t){var h;let r=t,i=(t==null?void 0:t.mainAlias)||"t0",n=(t==null?void 0:t.joins)||[],s=[],a=[],u=[];if(t!=null&&t.aggregates&&t.aggregates.length>0)t.groupBy&&t.groupBy.forEach(o=>{let c=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field;u.push(`${this.escapeIdentifier(c.tableAlias)}.${this.escapeIdentifier(c.field)} AS ${this.escapeIdentifier(`${c.tableAlias}_${c.field}`)}`)}),t.aggregates.forEach(o=>{let c=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field,d=`${this.escapeIdentifier(c.tableAlias)}.${this.escapeIdentifier(c.field)}`;u.push(`${o.function}(${d}) AS ${this.escapeIdentifier(o.as)}`)});else if(t!=null&&t.fields){let o=0;for(let[c,d]of Object.entries(t.fields))for(let m of d){let g=((h=r==null?void 0:r.resultShape)!=null?h:"flat")==="nested"?`__c${o++}`:`${c}_${m}`;a.push({key:g,alias:c,field:m}),u.push(`${this.escapeIdentifier(c)}.${this.escapeIdentifier(m)} AS ${this.escapeIdentifier(g)}`)}}else u.push(`${this.escapeIdentifier(i)}.*`);let p=`SELECT ${u.join(", ")} FROM ${this.escapeIdentifier(e)} AS ${this.escapeIdentifier(i)}`;if(n.forEach(o=>{let c=(o.type||"inner").toUpperCase();if(c==="RIGHT"||c==="FULL")throw new Error(`RnSqliteAdapter does not support ${c} JOIN`);let d=[];o.conditions.forEach(m=>{let f=this.buildValueExpr(m.left,i),g=this.buildValueExpr(m.right,i);d.push(`${f.sql} ${m.operator} ${g.sql}`),s.push(...f.params,...g.params)}),p+=` ${c} JOIN ${this.escapeIdentifier(o.table)} AS ${this.escapeIdentifier(o.alias)} ON ${d.join(" AND ")}`}),t!=null&&t.filters){let o=this.buildFilter(t.filters,i);o.sql&&o.sql!=="TRUE"&&(p+=` WHERE ${o.sql}`,s.push(...o.params))}if(t!=null&&t.aggregates&&t.aggregates.length>0){if(p+=this.buildGroupBy(t.groupBy,i),t.having){let o=this.buildFilter(t.having,i);o.sql&&o.sql!=="TRUE"&&(p+=` HAVING ${o.sql}`,s.push(...o.params))}return{sql:p,params:s,projectionMap:a.length?a:void 0}}if(p+=this.buildGroupBy(t==null?void 0:t.groupBy,i),t!=null&&t.having){let o=this.buildFilter(t.having,i);o.sql&&o.sql!=="TRUE"&&(p+=` HAVING ${o.sql}`,s.push(...o.params))}if(t!=null&&t.sort&&t.sort.length){let o=this.buildSort(t.sort,i);o&&(p+=` ORDER BY ${o}`)}return(t==null?void 0:t.limit)!==void 0&&(p+=" LIMIT ?",s.push(t.limit)),(t==null?void 0:t.offset)!==void 0&&(p+=" OFFSET ?",s.push(t.offset)),{sql:p,params:s,projectionMap:a.length?a:void 0}}static buildInsert(e,t){let r=Object.keys(t),i=r.map(a=>this.escapeIdentifier(a)).join(", "),n=r.map(()=>"?").join(", "),s=r.map(a=>this.normalizeValue(t[a]));return{sql:`INSERT INTO ${this.escapeIdentifier(e)} (${i}) VALUES (${n})`,params:s}}static buildUpdate(e,t,r){let i=Object.keys(r);if(!i.length)throw new Error("Cannot build UPDATE with empty updates");let n=i.map(a=>`${this.escapeIdentifier(a)} = ?`).join(", "),s=i.map(a=>this.normalizeValue(r[a]));return{sql:`UPDATE ${this.escapeIdentifier(e)} SET ${n} WHERE id = ?`,params:[...s,t]}}static buildDelete(e,t){return{sql:`DELETE FROM ${this.escapeIdentifier(e)} WHERE id = ?`,params:[t]}}};var S=class{constructor(e){this.savepointDepth=0;this.schemaMap=new Map;this.metaInitialized=!1;var t;this.driver=e.driver,this.tableNamePrefix=(t=e.tableNamePrefix)!=null?t:"",this.tableNameResolver=e.tableNameMapper}setTableNameResolver(e){this.tableNameResolver=e}resolveTableName(e){return this.tableNameResolver?String(this.tableNameResolver(e)||"").trim()||e:!this.tableNamePrefix||e.startsWith(this.tableNamePrefix)?e:`${this.tableNamePrefix}${e}`}async ensureMetaInit(){this.metaInitialized||(await this.driver.execute(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS _schema_version (
|
|
3
3
|
version INTEGER NOT NULL
|
|
4
4
|
)
|
|
5
|
-
`),this.metaInitialized=!0)}async getSchemaVersion(){await this.ensureMetaInit();let e=await this.driver.execute("SELECT version FROM _schema_version LIMIT 1");return e.rows.length?Number(e.rows[0].version):(await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){await this.ensureMetaInit(),(await this.driver.execute("SELECT 1 FROM _schema_version LIMIT 1")).rows.length?await this.driver.execute("UPDATE _schema_version SET version = ?",[e]):await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${g(i.name)} ${k(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");await this.driver.execute(`CREATE TABLE IF NOT EXISTS ${g(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${g(n)} ON ${g(t)}(${g(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if((await this.driver.execute(`SELECT name FROM pragma_table_info(${y.escapeLiteral(r)})`)).rows.some(a=>a.name===t.name))return;let n=`ALTER TABLE ${g(r)} ADD COLUMN ${g(t.name)} ${k(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(await this.driver.execute(n),t.isIndexed){let a=`idx_${r}_${t.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${g(a)} ON ${g(r)}(${g(t.name)})`)}let s=this.schemaMap.get(e);s&&!s.columns.find(a=>a.name===t.name)&&(s.columns.push(t),this.schemaMap.set(e,s))}async get(e,t){var s;let r,i;return typeof t=="string"?i={id:t}:(r=t,i=r.filters),(s=(await this.query(e,{...r,filters:i,limit:1}))[0])!=null?s:null}async query(e,t){var u,m,h;let r=this.resolveTableName(e),i=(u=t==null?void 0:t.joins)!=null&&u.length?{...t,joins:t.joins.map(d=>({...d,table:this.resolveTableName(d.table)}))}:t,{sql:n,params:s,projectionMap:a}=y.buildSelect(r,i),c=(await this.driver.execute(n,s)).rows;if((m=t==null?void 0:t.aggregates)!=null&&m.length)return c;if(t!=null&&t.fields)return((h=t==null?void 0:t.resultShape)!=null?h:"flat")==="nested"&&(a!=null&&a.length)?c.map(b=>{let T={};for(let v of a)T[v.alias]||(T[v.alias]={}),T[v.alias][v.field]=b[v.key];return T}):c;let f=this.schemaMap.get(e);if(!f)return c;let o=Object.fromEntries(f.columns.map(d=>[d.name,d]));return c.map(d=>P(d,o))}async create(e,t){var o;let r=this.resolveTableName(e),{sql:i,params:n}=y.buildInsert(r,t),s=await this.driver.execute(i,n),a=(o=t==null?void 0:t.id)!=null?o:s.insertId!==void 0?String(s.insertId):void 0,p={...t};a!==void 0&&(p.id=a);let c=this.schemaMap.get(e);if(!c)return p;let f=Object.fromEntries(c.columns.map(u=>[u.name,u]));return P(p,f)}async update(e,t,r){if(!Object.keys(r).length){let p=await this.get(e,t);if(!p)throw new Error(`Record not found: ${e}#${t}`);return p}let i=this.resolveTableName(e),{sql:n,params:s}=y.buildUpdate(i,t,r);await this.driver.execute(n,s);let a=await this.get(e,t);if(!a)throw new Error(`Record not found after update: ${e}#${t}`);return a}async delete(e,t){let r=this.resolveTableName(e),{sql:i,params:n}=y.buildDelete(r,t);await this.driver.execute(i,n)}async bulkCreate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)i.push(await r.create(e,n));return i}):[]}async bulkUpdate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)Object.keys(n.updates).length&&i.push(await r.update(e,n.id,n.updates));return i}):[]}async transaction(e){let t=this.savepointDepth===0,r=t?"BEGIN":`SAVEPOINT sp${this.savepointDepth}`;await this.driver.execute(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return await this.driver.execute(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{await this.driver.execute(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};function g(l){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(l))throw new Error(`Invalid identifier: "${l}"`);return`"${l}"`}function k(l){switch(l){case"string":return"TEXT";case"string[]":return"TEXT";case"number":return"REAL";case"boolean":return"INTEGER";case"json":return"TEXT";case"date":return"TEXT";default:return"TEXT"}}function P(l,e){let t={};for(let[r,i]of Object.entries(l)){let n=e[r],s=i;if(i!=null&&n){if(n.type==="boolean")s=!!i;else if(n.type==="date"&&typeof i=="string"){let a=new Date(i);Number.isNaN(a.getTime())||(s=a)}else if((n.type==="json"||n.type==="string[]")&&typeof i=="string")try{s=JSON.parse(i)}catch{}}t[r]=s}return t}var B=!0;var A=class{constructor(e){this.documentsPath=e.documentsPath.replace(/\/$/,""),this.backend=e.backend}getDocumentPath(e){return`${this.documentsPath}/${e}`}async writeFile(e,t){await this.backend.writeFile(e,t)}async share(e){var t,r;await((r=(t=this.backend).share)==null?void 0:r.call(t,e))}};function V(l,e){if(!e||Object.keys(e).length===0)return l;let t=new URLSearchParams;for(let[i,n]of Object.entries(e))n!=null&&t.set(i,String(n));let r=t.toString();return r?l.includes("?")?`${l}&${r}`:`${l}?${r}`:l}var R=class{constructor(e={}){let t=e.fetch;if(t)this.fetchImpl=t;else{let r=globalThis.fetch;if(typeof r!="function")throw new Error("RnFetchHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch.");this.fetchImpl=r}}async request(e){var n,s;let t=V(e.url,e.query),r=typeof AbortController!="undefined"?new AbortController:null,i=r&&e.timeoutMs?setTimeout(()=>r.abort(),e.timeoutMs):null;try{let a=e.body!==void 0&&e.body!==null,p={...(n=e.headers)!=null?n:{}};a&&!p["content-type"]&&!p["Content-Type"]&&(p["content-type"]="application/json");let c=await this.fetchImpl(t,{method:e.method,headers:p,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),f={};c.headers.forEach((m,h)=>{f[h.toLowerCase()]=m});let u=((s=f["content-type"])!=null?s:"").includes("application/json")?await c.json():await c.text();return{status:c.status,headers:f,data:u}}finally{i!==null&&clearTimeout(i)}}};var j=!0;var w=class{constructor(e){this.backend=e.backend}configure(e){var t,r;(r=(t=this.backend).configure)==null||r.call(t,e)}createChannel(e){var t,r;(r=(t=this.backend).createChannel)==null||r.call(t,e)}localNotification(e){this.backend.localNotification(e)}};async function W(l){let t=new TextEncoder().encode(l),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(n=>n.toString(16).padStart(2,"0")).join("")}var I=class{constructor(e={}){this.envVars=e.envVars,this.isOnlineFn=e.isOnline,this.hashPinFn=e.hashPin}getEnvVar(e){var r;if(this.envVars)return this.envVars[e];let t=globalThis.process;return(r=t==null?void 0:t.env)==null?void 0:r[e]}isOnline(){if(this.isOnlineFn)return this.isOnlineFn();let e=globalThis.navigator;return e&&typeof e.onLine=="boolean"?e.onLine:!0}async hashPin(e){var r;if(this.hashPinFn)return this.hashPinFn(e);if((r=globalThis.crypto)==null?void 0:r.subtle)return W(e);throw new Error("RnPlatformAdapter: crypto.subtle tidak tersedia di runtime ini. Injeksikan implementasi hashPin via options.hashPin (misalnya @noble/hashes atau expo-crypto).")}async verifyPin(e,t){return await this.hashPin(e)===t}};function U(l){let e=l.query;if(!e||Object.keys(e).length===0)return l.url;let r=new URLSearchParams(e).toString();return l.url.includes("?")?`${l.url}&${r}`:`${l.url}?${r}`}var O=class{constructor(e={}){this.ws=null;this.connectionOptions=null;this.listeners=new Map;this.reconnectAttempts=0;this.reconnectTimeout=null;this.intentionalClose=!1;var r,i,n,s,a;this.reconnect=(r=e.reconnect)!=null?r:!0,this.maxReconnectAttempts=Math.max(0,(i=e.maxReconnectAttempts)!=null?i:5),this.reconnectDelayMs=Math.max(0,(n=e.reconnectDelayMs)!=null?n:500),this.maxReconnectDelayMs=Math.max(this.reconnectDelayMs,(s=e.maxReconnectDelayMs)!=null?s:3e4);let t=(a=e.webSocket)!=null?a:globalThis.WebSocket;if(typeof t!="function")throw new Error("RnWebSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket.");this.WebSocketCtor=t}connect(e){return this.connectionOptions=e,this.intentionalClose=!1,this.reconnectAttempts=0,this.openConnection(e)}async disconnect(){this.intentionalClose=!0,this.clearReconnectTimeout(),this.ws&&(this.ws.close(1e3,"client disconnect"),this.ws=null)}subscribe(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e))}}async publish(e,t){var i,n;if(!this.ws||this.ws.readyState!==this.ws.OPEN)throw new Error(`RnWebSocketAdapter: cannot publish "${e}" \u2014 not connected (readyState=${(n=(i=this.ws)==null?void 0:i.readyState)!=null?n:"null"}).`);let r={event:e,payload:t};this.ws.send(JSON.stringify(r))}isConnected(){return this.ws!==null&&this.ws.readyState===this.ws.OPEN}openConnection(e){return new Promise((t,r)=>{let i=U(e),n;try{n=new this.WebSocketCtor(i)}catch(s){r(s instanceof Error?s:new Error(String(s)));return}n.onopen=()=>{this.ws=n,this.reconnectAttempts=0,t()},n.onerror=()=>{this.ws||r(new Error("RnWebSocketAdapter: connection failed"))},n.onclose=()=>{this.ws===n&&(this.ws=null),!this.intentionalClose&&this.reconnect&&this.connectionOptions&&this.reconnectAttempts<this.maxReconnectAttempts&&this.scheduleReconnect()},n.onmessage=s=>{this.handleMessage(s.data)}})}handleMessage(e){if(typeof e!="string")return;let t;try{t=JSON.parse(e)}catch{return}if(typeof t!="object"||t===null||typeof t.event!="string")return;let{event:r,payload:i}=t,n=this.listeners.get(r);if(n)for(let s of n)try{s(i)}catch{}}scheduleReconnect(){this.clearReconnectTimeout();let e=++this.reconnectAttempts,t=Math.min(this.reconnectDelayMs*Math.pow(2,e-1),this.maxReconnectDelayMs);this.reconnectTimeout=setTimeout(()=>{!this.intentionalClose&&this.connectionOptions&&this.openConnection(this.connectionOptions).catch(()=>{})},t)}clearReconnectTimeout(){this.reconnectTimeout!==null&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null)}};var H=!0;var $=class{constructor(e){this.store=e.storage}getItem(e){return this.store.getItem(e)}setItem(e,t){return this.store.setItem(e,t)}removeItem(e){return this.store.removeItem(e)}};var z=!0;var x="OFPLATFORM_RN_AUTH_NOT_IMPLEMENTED: auth host support surface is aligned with ofplatform-web, but runtime implementation is intentionally pending host adoption.",C={platform:"react-native",implemented:!1,notes:"API scaffold aligned with ofplatform-web. Runtime implementation stays pending until a React Native host adopts the shared auth bridge boundary."},N=class{constructor(e){this.options=e;var t;this.serverBaseUrl=((t=e.serverBaseUrl)!=null?t:"").trim().replace(/\/+$/,""),this.cacheKey=e.cacheKey.trim()}get isServerConfigured(){return this.serverBaseUrl.length>0}get capability(){return C}get cacheNamespace(){return this.cacheKey}async login(e,t){throw new Error(x)}async restoreCachedEnvelope(){throw new Error(x)}async logout(e){throw new Error(x)}getStoredAccessToken(e){return null}clearCachedSessionEnvelope(e){}};var Q={platform:"react-native",ready:!0,notes:["All adapter domains implemented:","RnSqliteAdapter (db, injectable driver),","RnExportAdapter (export, injectable backend),","RnFetchHttpAdapter (http),","RnNotificationAdapter (notification, injectable backend),","RnPlatformAdapter (platform, injectable hashPin/isOnline/envVars),","RnWebSocketAdapter (socket),","AsyncStorageAdapter (storage).","Auth bridge surface is scaffolded for parity with ofplatform-web."].join(" ")};
|
|
5
|
+
`),this.metaInitialized=!0)}async getSchemaVersion(){await this.ensureMetaInit();let e=await this.driver.execute("SELECT version FROM _schema_version LIMIT 1");return e.rows.length?Number(e.rows[0].version):(await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){await this.ensureMetaInit(),(await this.driver.execute("SELECT 1 FROM _schema_version LIMIT 1")).rows.length?await this.driver.execute("UPDATE _schema_version SET version = ?",[e]):await this.driver.execute("INSERT INTO _schema_version (version) VALUES (?)",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${v(i.name)} ${N(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");await this.driver.execute(`CREATE TABLE IF NOT EXISTS ${v(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${v(n)} ON ${v(t)}(${v(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if((await this.driver.execute(`SELECT name FROM pragma_table_info(${b.escapeLiteral(r)})`)).rows.some(a=>a.name===t.name))return;let n=`ALTER TABLE ${v(r)} ADD COLUMN ${v(t.name)} ${N(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(await this.driver.execute(n),t.isIndexed){let a=`idx_${r}_${t.name}`;await this.driver.execute(`CREATE INDEX IF NOT EXISTS ${v(a)} ON ${v(r)}(${v(t.name)})`)}let s=this.schemaMap.get(e);s&&!s.columns.find(a=>a.name===t.name)&&(s.columns.push(t),this.schemaMap.set(e,s))}async get(e,t){var s;let r,i;return typeof t=="string"?i={id:t}:(r=t,i=r.filters),(s=(await this.query(e,{...r,filters:i,limit:1}))[0])!=null?s:null}async query(e,t){var c,d,m;let r=this.resolveTableName(e),i=(c=t==null?void 0:t.joins)!=null&&c.length?{...t,joins:t.joins.map(f=>({...f,table:this.resolveTableName(f.table)}))}:t,{sql:n,params:s,projectionMap:a}=b.buildSelect(r,i),p=(await this.driver.execute(n,s)).rows;if((d=t==null?void 0:t.aggregates)!=null&&d.length)return p;if(t!=null&&t.fields)return((m=t==null?void 0:t.resultShape)!=null?m:"flat")==="nested"&&(a!=null&&a.length)?p.map(g=>{let y={};for(let T of a)y[T.alias]||(y[T.alias]={}),y[T.alias][T.field]=g[T.key];return y}):p;let h=this.schemaMap.get(e);if(!h)return p;let o=Object.fromEntries(h.columns.map(f=>[f.name,f]));return p.map(f=>P(f,o))}async create(e,t){var o;let r=this.resolveTableName(e),{sql:i,params:n}=b.buildInsert(r,t),s=await this.driver.execute(i,n),a=(o=t==null?void 0:t.id)!=null?o:s.insertId!==void 0?String(s.insertId):void 0,u={...t};a!==void 0&&(u.id=a);let p=this.schemaMap.get(e);if(!p)return u;let h=Object.fromEntries(p.columns.map(c=>[c.name,c]));return P(u,h)}async update(e,t,r){if(!Object.keys(r).length){let u=await this.get(e,t);if(!u)throw new Error(`Record not found: ${e}#${t}`);return u}let i=this.resolveTableName(e),{sql:n,params:s}=b.buildUpdate(i,t,r);await this.driver.execute(n,s);let a=await this.get(e,t);if(!a)throw new Error(`Record not found after update: ${e}#${t}`);return a}async delete(e,t){let r=this.resolveTableName(e),{sql:i,params:n}=b.buildDelete(r,t);await this.driver.execute(i,n)}async bulkCreate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)i.push(await r.create(e,n));return i}):[]}async bulkUpdate(e,t){return t.length?this.transaction(async r=>{let i=[];for(let n of t)Object.keys(n.updates).length&&i.push(await r.update(e,n.id,n.updates));return i}):[]}async transaction(e){let t=this.savepointDepth===0,r=t?"BEGIN":`SAVEPOINT sp${this.savepointDepth}`;await this.driver.execute(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return await this.driver.execute(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{await this.driver.execute(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};function v(l){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(l))throw new Error(`Invalid identifier: "${l}"`);return`"${l}"`}function N(l){switch(l){case"string":return"TEXT";case"string[]":return"TEXT";case"number":return"REAL";case"boolean":return"INTEGER";case"json":return"TEXT";case"date":return"TEXT";default:return"TEXT"}}function P(l,e){let t={};for(let[r,i]of Object.entries(l)){let n=e[r],s=i;if(i!=null&&n){if(n.type==="boolean")s=!!i;else if(n.type==="date"&&typeof i=="string"){let a=new Date(i);Number.isNaN(a.getTime())||(s=a)}else if((n.type==="json"||n.type==="string[]")&&typeof i=="string")try{s=JSON.parse(i)}catch{}}t[r]=s}return t}var j=!0;var w=class{constructor(e){this.documentsPath=e.documentsPath.replace(/\/$/,""),this.backend=e.backend}getDocumentPath(e){return`${this.documentsPath}/${e}`}async writeFile(e,t){await this.backend.writeFile(e,t)}async share(e){var t,r;await((r=(t=this.backend).share)==null?void 0:r.call(t,e))}};function U(l,e){if(!e||Object.keys(e).length===0)return l;let t=new URLSearchParams;for(let[i,n]of Object.entries(e))n!=null&&t.set(i,String(n));let r=t.toString();return r?l.includes("?")?`${l}&${r}`:`${l}?${r}`:l}var I=class{constructor(e={}){let t=e.fetch;if(t)this.fetchImpl=t;else{let r=globalThis.fetch;if(typeof r!="function")throw new Error("RnFetchHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch.");this.fetchImpl=r}}async request(e){var n,s;let t=U(e.url,e.query),r=typeof AbortController!="undefined"?new AbortController:null,i=r&&e.timeoutMs?setTimeout(()=>r.abort(),e.timeoutMs):null;try{let a=e.body!==void 0&&e.body!==null,u={...(n=e.headers)!=null?n:{}};a&&!u["content-type"]&&!u["Content-Type"]&&(u["content-type"]="application/json");let p=await this.fetchImpl(t,{method:e.method,headers:u,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),h={};p.headers.forEach((d,m)=>{h[m.toLowerCase()]=d});let c=((s=h["content-type"])!=null?s:"").includes("application/json")?await p.json():await p.text();return{status:p.status,headers:h,data:c}}finally{i!==null&&clearTimeout(i)}}};var V=!0;var E=class{constructor(e){this.backend=e.backend}configure(e){var t,r;(r=(t=this.backend).configure)==null||r.call(t,e)}createChannel(e){var t,r;(r=(t=this.backend).createChannel)==null||r.call(t,e)}localNotification(e){this.backend.localNotification(e)}};async function W(l){let t=new TextEncoder().encode(l),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(n=>n.toString(16).padStart(2,"0")).join("")}var O=class{constructor(e={}){this.envVars=e.envVars,this.isOnlineFn=e.isOnline,this.hashPinFn=e.hashPin}getEnvVar(e){var r;if(this.envVars)return this.envVars[e];let t=globalThis.process;return(r=t==null?void 0:t.env)==null?void 0:r[e]}isOnline(){if(this.isOnlineFn)return this.isOnlineFn();let e=globalThis.navigator;return e&&typeof e.onLine=="boolean"?e.onLine:!0}async hashPin(e){var r;if(this.hashPinFn)return this.hashPinFn(e);if((r=globalThis.crypto)==null?void 0:r.subtle)return W(e);throw new Error("RnPlatformAdapter: crypto.subtle tidak tersedia di runtime ini. Injeksikan implementasi hashPin via options.hashPin (misalnya @noble/hashes atau expo-crypto).")}async verifyPin(e,t){return await this.hashPin(e)===t}};function H(l){let e=l.query;if(!e||Object.keys(e).length===0)return l.url;let r=new URLSearchParams(e).toString();return l.url.includes("?")?`${l.url}&${r}`:`${l.url}?${r}`}var k=class{constructor(e={}){this.ws=null;this.connectionOptions=null;this.listeners=new Map;this.reconnectAttempts=0;this.reconnectTimeout=null;this.intentionalClose=!1;var r,i,n,s,a;this.reconnect=(r=e.reconnect)!=null?r:!0,this.maxReconnectAttempts=Math.max(0,(i=e.maxReconnectAttempts)!=null?i:5),this.reconnectDelayMs=Math.max(0,(n=e.reconnectDelayMs)!=null?n:500),this.maxReconnectDelayMs=Math.max(this.reconnectDelayMs,(s=e.maxReconnectDelayMs)!=null?s:3e4);let t=(a=e.webSocket)!=null?a:globalThis.WebSocket;if(typeof t!="function")throw new Error("RnWebSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket.");this.WebSocketCtor=t}connect(e){return this.connectionOptions=e,this.intentionalClose=!1,this.reconnectAttempts=0,this.openConnection(e)}async disconnect(){this.intentionalClose=!0,this.clearReconnectTimeout(),this.ws&&(this.ws.close(1e3,"client disconnect"),this.ws=null)}subscribe(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e))}}async publish(e,t){var i,n;if(!this.ws||this.ws.readyState!==this.ws.OPEN)throw new Error(`RnWebSocketAdapter: cannot publish "${e}" \u2014 not connected (readyState=${(n=(i=this.ws)==null?void 0:i.readyState)!=null?n:"null"}).`);let r={event:e,payload:t};this.ws.send(JSON.stringify(r))}isConnected(){return this.ws!==null&&this.ws.readyState===this.ws.OPEN}openConnection(e){return new Promise((t,r)=>{let i=H(e),n;try{n=new this.WebSocketCtor(i)}catch(s){r(s instanceof Error?s:new Error(String(s)));return}n.onopen=()=>{this.ws=n,this.reconnectAttempts=0,t()},n.onerror=()=>{this.ws||r(new Error("RnWebSocketAdapter: connection failed"))},n.onclose=()=>{this.ws===n&&(this.ws=null),!this.intentionalClose&&this.reconnect&&this.connectionOptions&&this.reconnectAttempts<this.maxReconnectAttempts&&this.scheduleReconnect()},n.onmessage=s=>{this.handleMessage(s.data)}})}handleMessage(e){if(typeof e!="string")return;let t;try{t=JSON.parse(e)}catch{return}if(typeof t!="object"||t===null||typeof t.event!="string")return;let{event:r,payload:i}=t,n=this.listeners.get(r);if(n)for(let s of n)try{s(i)}catch{}}scheduleReconnect(){this.clearReconnectTimeout();let e=++this.reconnectAttempts,t=Math.min(this.reconnectDelayMs*Math.pow(2,e-1),this.maxReconnectDelayMs);this.reconnectTimeout=setTimeout(()=>{!this.intentionalClose&&this.connectionOptions&&this.openConnection(this.connectionOptions).catch(()=>{})},t)}clearReconnectTimeout(){this.reconnectTimeout!==null&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null)}};var z=!0;var x=class{constructor(e){this.store=e.storage}getItem(e){return this.store.getItem(e)}setItem(e,t){return this.store.setItem(e,t)}removeItem(e){return this.store.removeItem(e)}};var Q=!0;var A=require("ofauth-shared-core"),J=6e4;function C(l,e){var i,n,s,a,u;let t=new Date().toISOString(),r=l&&typeof l=="object"?l:{};return{sessionId:String((i=r.sessionId)!=null?i:""),identityId:String((n=r.identityId)!=null?n:""),assuranceLevel:String((s=r.assuranceLevel)!=null?s:"basic"),issuedAt:String((a=r.issuedAt)!=null?a:t),expiresAt:String((u=r.expiresAt)!=null?u:e)}}var D={platform:"react-native",implemented:!0,notes:"Runtime implementation aligned with ofplatform-web using injected async storage, fetch, and offline verifier dependencies."},$=class{constructor(e){this.options=e;var i,n,s,a,u,p;if(this.serverBaseUrl=((i=e.serverBaseUrl)!=null?i:"").trim().replace(/\/+$/,""),this.cacheKey=e.cacheKey.trim(),this.targetTenantId=((n=e.targetTenantId)==null?void 0:n.trim())||"",this.targetBranchId=((s=e.targetBranchId)==null?void 0:s.trim())||"",this.targetDomainId=((a=e.targetDomainId)==null?void 0:a.trim())||"",this.storage=e.storage,e.fetchImpl)this.fetchImpl=e.fetchImpl;else if(typeof globalThis.fetch=="function")this.fetchImpl=globalThis.fetch.bind(globalThis);else throw new Error("RnServerAuthoritativeAuthHostSupport requires a fetch implementation");if(this.isOnlineResolver=(u=e.isOnline)!=null?u:(()=>!0),!this.serverBaseUrl){this.serverBridge=null;return}let t={login:async({principal:h,secret:o})=>{var f,g,y,T;let c=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({principal:h,secret:o,...this.targetTenantId?{targetTenantId:this.targetTenantId}:{},...this.targetBranchId?{targetBranchId:this.targetBranchId}:{},...this.targetDomainId?{targetDomainId:this.targetDomainId}:{}})}),d=await c.json().catch(()=>({}));if(!c.ok)throw new A.AuthRejectionError(String((f=d.code)!=null?f:"AUTH_UNAUTHORIZED"));let m=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((g=d.accessToken)!=null?g:""),refreshToken:String((y=d.refreshToken)!=null?y:""),session:C(d.session,m),activeContext:(T=d.activeContext)!=null?T:null,activeRoleRef:d.activeRoleRef==null?"":String(d.activeRoleRef)}},refresh:async({refreshToken:h})=>{var m,f,g,y;let o=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:h})}),c=await o.json().catch(()=>({}));if(!o.ok)throw new A.AuthRejectionError(String((m=c.code)!=null?m:"AUTH_UNAUTHORIZED"));let d=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((f=c.accessToken)!=null?f:""),refreshToken:String((g=c.refreshToken)!=null?g:""),session:C(c.session,d),activeContext:(y=c.activeContext)!=null?y:null}},logout:async({accessToken:h,refreshToken:o})=>{let c={"Content-Type":"application/json"};h&&(c.Authorization=`Bearer ${h}`),await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/logout`,{method:"POST",headers:c,body:JSON.stringify({refreshToken:o})}).catch(()=>{})}},r={getCachedIdentity:async h=>{var o,c;return(c=(o=await this.readCacheRecord(h))==null?void 0:o.identity)!=null?c:null},setCachedIdentity:async h=>{let o=await this.readCacheRecord(h.principal);await this.writeCacheRecord(h.principal,{...o,identity:h})},clearCachedIdentity:async h=>{let o=await this.readCacheRecord(h);o&&await this.writeCacheRecord(h,{...o,identity:void 0})},getSessionEnvelope:async h=>{var o,c;return(c=(o=await this.readCacheRecord(h))==null?void 0:o.envelope)!=null?c:null},setSessionEnvelope:async(h,o)=>{let c=await this.readCacheRecord(h);await this.writeCacheRecord(h,{...c,envelope:o})},clearSessionEnvelope:async h=>{let o=await this.readCacheRecord(h);o&&await this.writeCacheRecord(h,{...o,envelope:void 0})}};this.serverBridge=(0,A.createServerAuthoritativeAuthBridge)({authority:t,cache:r,isOnline:()=>this.isOnlineResolver(),verifyOfflineSecret:(p=this.options.verifyOfflineSecret)!=null?p:(async()=>!1)})}async performAuthorityLogin(e,t,r){var h,o,c,d,m,f,g;let i=((h=r==null?void 0:r.targetTenantId)==null?void 0:h.trim())||this.targetTenantId,n=((o=r==null?void 0:r.targetBranchId)==null?void 0:o.trim())||this.targetBranchId,s=((c=r==null?void 0:r.targetDomainId)==null?void 0:c.trim())||this.targetDomainId,a=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({principal:e,secret:t,...i?{targetTenantId:i}:{},...n?{targetBranchId:n}:{},...s?{targetDomainId:s}:{}})}),u=await a.json().catch(()=>({}));if(!a.ok)throw new A.AuthRejectionError(String((d=u.code)!=null?d:"AUTH_UNAUTHORIZED"));let p=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((m=u.accessToken)!=null?m:""),refreshToken:String((f=u.refreshToken)!=null?f:""),session:C(u.session,p),activeContext:(g=u.activeContext)!=null?g:null,activeRoleRef:u.activeRoleRef==null?"":String(u.activeRoleRef)}}get isServerConfigured(){return this.serverBaseUrl.length>0}get capability(){return D}get cacheNamespace(){return this.cacheKey}async loadCacheMap(){try{let e=await this.storage.getItem(this.cacheKey);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}async saveCacheMap(e){try{await this.storage.setItem(this.cacheKey,JSON.stringify(e))}catch{}}async readCacheRecord(e){var r;return(r=(await this.loadCacheMap())[e])!=null?r:null}async writeCacheRecord(e,t){let r=await this.loadCacheMap(),i={};t.identity&&(i.identity=t.identity),t.envelope&&(i.envelope=t.envelope),!i.identity&&!i.envelope?delete r[e]:r[e]=i,await this.saveCacheMap(r)}async login(e,t){var i,n;if(!this.serverBridge)return{status:"rejected",reasonCode:"AUTH_BRIDGE_NOT_CONFIGURED"};let r=await this.serverBridge.login({principal:e,secret:t,verifyMethod:"pin"});return r.status==="authenticated"?{status:"authenticated",mode:(i=r.mode)!=null?i:"online"}:{status:"rejected",reasonCode:(n=r.reasonCode)!=null?n:"AUTH_UNAUTHORIZED"}}async loginWithTarget(e,t,r){var i,n,s;if(!this.serverBridge||!this.serverBaseUrl)return{status:"rejected",reasonCode:"AUTH_BRIDGE_NOT_CONFIGURED"};try{let a=await this.performAuthorityLogin(e,t,r),u=(i=await this.readCacheRecord(e))!=null?i:{};return await this.writeCacheRecord(e,{...u,envelope:{principal:e,accessToken:a.accessToken,refreshToken:a.refreshToken,assuranceLevel:a.session.assuranceLevel,issuedAt:a.session.issuedAt,expiresAt:a.session.expiresAt,activeRoleRef:(n=a.activeRoleRef)!=null?n:null,activeContext:(s=a.activeContext)!=null?s:null}}),{status:"authenticated",mode:"online"}}catch(a){return{status:"rejected",reasonCode:a instanceof A.AuthRejectionError?a.code:"AUTH_AUTHORITY_UNAVAILABLE"}}}async restoreCachedEnvelope(){var t,r,i;let e=await this.loadCacheMap();for(let n of Object.keys(e)){let s=(t=e[n])==null?void 0:t.envelope;if(!s)continue;let a=Date.parse(s.expiresAt),u=Number.isFinite(a),p=!u||a<=Date.now()+J;if(this.isOnlineResolver()&&p&&s.refreshToken&&this.serverBaseUrl)try{let h=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:s.refreshToken})}),o=await h.json().catch(()=>({}));if(h.ok&&o.accessToken){let c={...s,accessToken:String(o.accessToken),refreshToken:o.refreshToken?String(o.refreshToken):s.refreshToken,activeContext:(i=(r=o.activeContext)!=null?r:s.activeContext)!=null?i:null};return await this.writeCacheRecord(n,{...e[n],envelope:c}),{principal:n,envelope:c}}}catch{}if(u&&a>Date.now())return{principal:n,envelope:s}}return null}async logout(e){this.serverBridge&&await this.serverBridge.logout(e)}async getStoredAccessToken(e){var t,r,i;return(i=(r=(t=await this.readCacheRecord(e))==null?void 0:t.envelope)==null?void 0:r.accessToken)!=null?i:null}async clearCachedSessionEnvelope(e){let t=await this.readCacheRecord(e);t&&await this.writeCacheRecord(e,{...t,envelope:void 0})}};var G={platform:"react-native",ready:!0,notes:["All adapter domains implemented:","RnSqliteAdapter (db, injectable driver),","RnExportAdapter (export, injectable backend),","RnFetchHttpAdapter (http),","RnNotificationAdapter (notification, injectable backend),","RnPlatformAdapter (platform, injectable hashPin/isOnline/envVars),","RnWebSocketAdapter (socket),","AsyncStorageAdapter (storage).","Auth bridge runtime is implemented for parity with ofplatform-web."].join(" ")};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofplatform-rn",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "React Native platform adapters for of* host apps (SQLite, fetch, WebSocket, AsyncStorage).",
|
|
6
6
|
"author": {
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
"bundle": "node esbuild.config.js"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"ofcore": "0.2.0-alpha.
|
|
34
|
+
"ofcore": "0.2.0-alpha.1"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"ofauth-shared-core": "0.2.0-alpha.
|
|
37
|
+
"ofauth-shared-core": "0.2.0-alpha.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"esbuild": "^0.25.11",
|
|
41
|
-
"ofauth-shared-core": "0.2.0-alpha.
|
|
41
|
+
"ofauth-shared-core": "0.2.0-alpha.1",
|
|
42
42
|
"sql.js": "^1.14.1",
|
|
43
43
|
"typescript": "^5.9.3"
|
|
44
44
|
},
|