ofplatform-electron 0.1.0-alpha.1 → 0.1.0-alpha.3
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
CHANGED
|
@@ -12,6 +12,8 @@ Electron platform adapter package for `of*` ecosystem.
|
|
|
12
12
|
- `ElectronPlatformAdapter` (implements `PlatformAdapter`)
|
|
13
13
|
- `src/adapters/storage`:
|
|
14
14
|
- `ElectronStorageAdapter` (file-backed `StorageAdapter`)
|
|
15
|
+
- `src/auth`:
|
|
16
|
+
- `ElectronServerAuthoritativeAuthHostSupport` (shared auth bridge surface parity with `ofplatform-web`; runtime implementation intentionally scaffolded)
|
|
15
17
|
- `src/adapters/desktop`:
|
|
16
18
|
- `ElectronNotificationAdapter`
|
|
17
19
|
- `ElectronExportAdapter`
|
|
@@ -21,6 +23,7 @@ Electron platform adapter package for `of*` ecosystem.
|
|
|
21
23
|
Planned adapters:
|
|
22
24
|
- Electron SQLCipher hardening profile (follow-up from current SQLite adapter)
|
|
23
25
|
- Optional IPC-backed `HttpAdapter`/`SocketAdapter`
|
|
26
|
+
- Runtime-backed Electron auth host support that fulfills the scaffolded `src/auth` surface once host adoption starts
|
|
24
27
|
|
|
25
28
|
Design rule:
|
|
26
29
|
- Keep platform-specific implementation in platform packages, not in `ofcore`.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type AuthoritySessionEnvelope, type CachedIdentityEntry } from 'ofauth-shared-core';
|
|
2
|
+
import type { StorageAdapter } from 'ofcore';
|
|
3
|
+
export type PlatformAuthoritySessionEnvelope = AuthoritySessionEnvelope;
|
|
4
|
+
type CacheRecord = {
|
|
5
|
+
identity?: CachedIdentityEntry;
|
|
6
|
+
envelope?: PlatformAuthoritySessionEnvelope;
|
|
7
|
+
};
|
|
8
|
+
export type ElectronServerAuthoritativeAuthHostSupportOptions = {
|
|
9
|
+
serverBaseUrl?: string;
|
|
10
|
+
cacheKey: string;
|
|
11
|
+
targetTenantId?: string;
|
|
12
|
+
targetBranchId?: string;
|
|
13
|
+
targetDomainId?: string;
|
|
14
|
+
storage?: StorageAdapter;
|
|
15
|
+
fetchImpl?: typeof fetch;
|
|
16
|
+
isOnline?: () => boolean;
|
|
17
|
+
verifyOfflineSecret?: (params: {
|
|
18
|
+
principal: string;
|
|
19
|
+
secret: string;
|
|
20
|
+
}) => Promise<boolean>;
|
|
21
|
+
};
|
|
22
|
+
export type AuthorityLoginTarget = {
|
|
23
|
+
targetTenantId?: string;
|
|
24
|
+
targetBranchId?: string;
|
|
25
|
+
targetDomainId?: string;
|
|
26
|
+
};
|
|
27
|
+
export type ElectronServerAuthoritativeLoginResult = {
|
|
28
|
+
status: 'authenticated';
|
|
29
|
+
mode?: 'online' | 'offline';
|
|
30
|
+
} | {
|
|
31
|
+
status: 'rejected';
|
|
32
|
+
reasonCode?: string;
|
|
33
|
+
};
|
|
34
|
+
export type ElectronRestoredAuthEnvelope = {
|
|
35
|
+
principal: string;
|
|
36
|
+
envelope: PlatformAuthoritySessionEnvelope;
|
|
37
|
+
};
|
|
38
|
+
export type PlatformAuthSupportCapability = {
|
|
39
|
+
platform: 'electron';
|
|
40
|
+
implemented: boolean;
|
|
41
|
+
notes: string;
|
|
42
|
+
};
|
|
43
|
+
export declare const OFPLATFORM_ELECTRON_AUTH_STATUS: PlatformAuthSupportCapability;
|
|
44
|
+
export declare class ElectronServerAuthoritativeAuthHostSupport {
|
|
45
|
+
private readonly options;
|
|
46
|
+
private readonly serverBaseUrl;
|
|
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;
|
|
55
|
+
constructor(options: ElectronServerAuthoritativeAuthHostSupportOptions);
|
|
56
|
+
private performAuthorityLogin;
|
|
57
|
+
get isServerConfigured(): boolean;
|
|
58
|
+
get capability(): PlatformAuthSupportCapability;
|
|
59
|
+
get cacheNamespace(): string;
|
|
60
|
+
private loadCacheMap;
|
|
61
|
+
private saveCacheMap;
|
|
62
|
+
readCacheRecord(principal: string): Promise<CacheRecord | null>;
|
|
63
|
+
writeCacheRecord(principal: string, record: CacheRecord): Promise<void>;
|
|
64
|
+
clearCachedSessionEnvelope(principal: string): Promise<void>;
|
|
65
|
+
clearAllCachedSessionEnvelopes(): Promise<void>;
|
|
66
|
+
login(principal: string, secret: string): Promise<ElectronServerAuthoritativeLoginResult>;
|
|
67
|
+
loginWithTarget(principal: string, secret: string, target?: AuthorityLoginTarget): Promise<ElectronServerAuthoritativeLoginResult>;
|
|
68
|
+
logout(principal: string): Promise<void>;
|
|
69
|
+
restoreCachedEnvelope(): Promise<ElectronRestoredAuthEnvelope | null>;
|
|
70
|
+
getStoredAccessToken(principal: string): Promise<string | null>;
|
|
71
|
+
getStoredEnvelope(principal: string): Promise<PlatformAuthoritySessionEnvelope | null>;
|
|
72
|
+
}
|
|
73
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ElectronServerAuthoritativeAuthHostSupport';
|
package/dist/index.d.ts
CHANGED
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import N from"better-sqlite3";var y=class{static escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}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(c=>this.normalizeValue(c))}}if(a==="IS NULL"||a==="IS NOT NULL")return{sql:`${s} ${a}`,params:[]};if(a==="LIKE"){let l=("likeMode"in e?e.likeMode:"default")==="case-sensitive"?" COLLATE BINARY":"";return{sql:`${s} LIKE${l} ?`,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,c])=>({sql:`${`${this.escapeIdentifier(t)}.${this.escapeIdentifier(a)}`} = ?`,params:[this.normalizeValue(c)]}));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=[],c=[];if(t!=null&&t.aggregates&&t.aggregates.length>0)t.groupBy&&t.groupBy.forEach(o=>{let h=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field;c.push(`${this.escapeIdentifier(h.tableAlias)}.${this.escapeIdentifier(h.field)} AS ${this.escapeIdentifier(`${h.tableAlias}_${h.field}`)}`)}),t.aggregates.forEach(o=>{let h=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field,f=`${this.escapeIdentifier(h.tableAlias)}.${this.escapeIdentifier(h.field)}`;c.push(`${o.function}(${f}) AS ${this.escapeIdentifier(o.as)}`)});else if(t!=null&&t.fields){let o=0;for(let[h,f]of Object.entries(t.fields))for(let p of f){let m=((u=r==null?void 0:r.resultShape)!=null?u:"flat")==="nested"?`__c${o++}`:`${h}_${p}`;a.push({key:m,alias:h,field:p}),c.push(`${this.escapeIdentifier(h)}.${this.escapeIdentifier(p)} AS ${this.escapeIdentifier(m)}`)}}else c.push(`${this.escapeIdentifier(i)}.*`);let l=`SELECT ${c.join(", ")} FROM ${this.escapeIdentifier(e)} AS ${this.escapeIdentifier(i)}`;if(n.forEach(o=>{let h=(o.type||"inner").toUpperCase();if(h==="RIGHT"||h==="FULL")throw new Error(`SQLite adapter does not support ${h} JOIN`);let f=[];o.conditions.forEach(p=>{let g=this.buildValueExpr(p.left,i),m=this.buildValueExpr(p.right,i);f.push(`${g.sql} ${p.operator} ${m.sql}`),s.push(...g.params,...m.params)}),l+=` ${h} JOIN ${this.escapeIdentifier(o.table)} AS ${this.escapeIdentifier(o.alias)} ON ${f.join(" AND ")}`}),t!=null&&t.filters){let o=this.buildFilter(t.filters,i);o.sql&&o.sql!=="TRUE"&&(l+=` WHERE ${o.sql}`,s.push(...o.params))}if(t!=null&&t.aggregates&&t.aggregates.length>0){if(l+=this.buildGroupBy(t.groupBy,i),t.having){let o=this.buildFilter(t.having,i);o.sql&&o.sql!=="TRUE"&&(l+=` HAVING ${o.sql}`,s.push(...o.params))}return{sql:l,params:s,projectionMap:a.length?a:void 0}}if(l+=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"&&(l+=` HAVING ${o.sql}`,s.push(...o.params))}if(t!=null&&t.sort&&t.sort.length){let o=this.buildSort(t.sort,i);o&&(l+=` ORDER BY ${o}`)}return(t==null?void 0:t.limit)!==void 0&&(l+=" LIMIT ?",s.push(t.limit)),(t==null?void 0:t.offset)!==void 0&&(l+=" OFFSET ?",s.push(t.offset)),{sql:l,params:s,projectionMap:a.length?a:void 0}}static buildInsert(e,t){let r=Object.keys(t),i=r.map(c=>this.escapeIdentifier(c)).join(", "),n=r.map(()=>"?").join(", "),s=r.map(c=>this.normalizeValue(t[c]));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 query with empty updates payload");let n=i.map(c=>`${this.escapeIdentifier(c)} = ?`).join(", "),s=i.map(c=>this.normalizeValue(r[c]));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 T=class{constructor(e){this.db=new N(e)}initMetaTable(){this.db.exec(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS _meta (
|
|
3
3
|
key TEXT PRIMARY KEY,
|
|
4
4
|
value TEXT
|
|
@@ -6,4 +6,4 @@ import w from"better-sqlite3";var g=class{static escapeIdentifier(e){if(!/^[a-zA
|
|
|
6
6
|
CREATE TABLE IF NOT EXISTS schema_version (
|
|
7
7
|
version INTEGER NOT NULL
|
|
8
8
|
);
|
|
9
|
-
`)}run(e,t=[]){return this.db.prepare(e).run(...t)}get(e,t=[]){return this.db.prepare(e).get(...t)}all(e,t=[]){return this.db.prepare(e).all(...t)}transaction(e){return this.db.transaction(e)()}escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}mapType(e){switch(e){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"}}parseRow(e,t){let r={};for(let[i,n]of Object.entries(e!=null?e:{})){let s=t[i],a=n;if(n!=null&&s){if(s.type==="boolean")a=!!n;else if(s.type==="date"&&typeof n=="string"){let l=new Date(n);Number.isNaN(l.getTime())||(a=l)}else if((s.type==="json"||s.type==="string[]")&&typeof n=="string")try{a=JSON.parse(n)}catch(l){}}r[i]=a}return r}buildFilter(e,t="t0"){return g.buildFilter(e,t)}buildGroupBy(e,t="t0"){return g.buildGroupBy(e,t)}buildSort(e,t="t0"){return g.buildSort(e,t)}buildSelect(e,t){return g.buildSelect(e,t)}buildInsert(e,t){return g.buildInsert(e,t)}buildUpdate(e,t,r){return g.buildUpdate(e,t,r)}buildDelete(e,t){return g.buildDelete(e,t)}};var S=class{constructor(e){this.savepointDepth=0;this.schemaMap=new Map;var t;this.executor=new b(e.dbPath),this.executor.initMetaTable(),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 getSchemaVersion(){let e=this.executor.get("SELECT version FROM schema_version LIMIT 1");return e?e.version:(this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){if(!this.executor.get("SELECT 1 FROM schema_version LIMIT 1")){this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[e]);return}this.executor.run("UPDATE schema_version SET version = ?",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${this.executor.escapeIdentifier(i.name)} ${this.executor.mapType(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");this.executor.run(`CREATE TABLE IF NOT EXISTS ${this.executor.escapeIdentifier(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(n)} ON ${this.executor.escapeIdentifier(t)}(${this.executor.escapeIdentifier(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if(this.executor.all(`PRAGMA table_info(${this.executor.escapeIdentifier(r)})`).some(a=>a.name===t.name))return;let n=`ALTER TABLE ${this.executor.escapeIdentifier(r)} ADD COLUMN ${this.executor.escapeIdentifier(t.name)} ${this.executor.mapType(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(this.executor.run(n),t.isIndexed){let a=`idx_${r}_${t.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(a)} ON ${this.executor.escapeIdentifier(r)}(${this.executor.escapeIdentifier(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 o,u,f;let r=this.resolveTableName(e),i=(o=t==null?void 0:t.joins)!=null&&o.length?{...t,joins:t.joins.map(h=>({...h,table:this.resolveTableName(h.table)}))}:t,{sql:n,params:s,projectionMap:a}=this.executor.buildSelect(r,i),l=this.executor.all(n,s);if((u=t==null?void 0:t.aggregates)!=null&&u.length)return l;if(t!=null&&t.fields)return((f=t==null?void 0:t.resultShape)!=null?f:"flat")==="nested"&&(a!=null&&a.length)?l.map(y=>{let d={};for(let E of a)d[E.alias]||(d[E.alias]={}),d[E.alias][E.field]=y[E.key];return d}):l;let c=this.schemaMap.get(e);if(!c)return l;let m=Object.fromEntries(c.columns.map(h=>[h.name,h]));return l.map(h=>this.executor.parseRow(h,m))}async create(e,t){var o,u;let r=this.resolveTableName(e),{sql:i,params:n}=this.executor.buildInsert(r,t),s=this.executor.run(i,n),a=(u=t==null?void 0:t.id)!=null?u:(o=s.lastInsertRowid)==null?void 0:o.toString(),l=a?{...t,id:a}:{...t},c=this.schemaMap.get(e);if(!c)return l;let m=Object.fromEntries(c.columns.map(f=>[f.name,f]));return this.executor.parseRow(l,m)}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}=this.executor.buildUpdate(i,t,r);this.executor.run(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}=this.executor.buildDelete(r,t);this.executor.run(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 IMMEDIATE":`SAVEPOINT sp${this.savepointDepth}`;this.executor.run(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return this.executor.run(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{this.executor.run(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};import{createHash as R}from"node:crypto";var v=class{getEnvVar(e){return process.env[e]}isOnline(){return typeof navigator!="undefined"&&typeof navigator.onLine!="undefined"?navigator.onLine:!0}async hashPin(e){return R("sha256").update(e).digest("hex")}async verifyPin(e,t){return await this.hashPin(e)===t}};var A=class{constructor(e){this.options=e}configure(e){}createChannel(e){}localNotification(e){this.options.notify(e)}};import N from"node:fs/promises";import k from"node:path";var I=class{constructor(e){this.options=e}getDocumentPath(e){return k.join(this.options.documentsPath,e)}async writeFile(e,t){await N.writeFile(e,t,"utf8")}async share(e){var t,r;await((r=(t=this.options).revealFile)==null?void 0:r.call(t,e))}};function P(p,e){if(!e||Object.keys(e).length===0)return p;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?p.includes("?")?`${p}&${r}`:`${p}?${r}`:p}var x=class{constructor(e={}){let t=e.fetch;if(t)this.fetchImpl=t;else{let r=globalThis.fetch;if(typeof r!="function")throw new Error("ElectronHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch, or ensure the app is running on Electron \u2265 20 / Node.js \u2265 18.");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 c=await this.fetchImpl(t,{method:e.method,headers:l,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),m={};c.headers.forEach((f,h)=>{m[h.toLowerCase()]=f});let u=((s=m["content-type"])!=null?s:"").includes("application/json")?await c.json():await c.text();return{status:c.status,headers:m,data:u}}finally{i!==null&&clearTimeout(i)}}};var ie=!0;function L(p){let e=p.query;if(!e||Object.keys(e).length===0)return p.url;let r=new URLSearchParams(e).toString();return p.url.includes("?")?`${p.url}&${r}`:`${p.url}?${r}`}var $=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("ElectronSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket. In the Electron main process you can use the `ws` package.");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(`ElectronSocketAdapter: 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("ElectronSocketAdapter: 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 oe=!0;import T from"node:fs";import C from"node:path";var O=class{constructor(e){var r;let t=(r=e.fileName)!=null?r:"storage.json";T.mkdirSync(e.storageDir,{recursive:!0}),this.filePath=C.join(e.storageDir,t);try{this.data=JSON.parse(T.readFileSync(this.filePath,"utf-8"))}catch{this.data={}}}async getItem(e){let t=this.data[e];return t!==void 0?t:null}async setItem(e,t){this.data[e]=t,await T.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}async removeItem(e){delete this.data[e],await T.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}};var de={platform:"electron",ready:!0,notes:"All adapter domains implemented: SQLiteAdapter (db), ElectronHttpAdapter (http), ElectronSocketAdapter (socket), ElectronStorageAdapter (storage), ElectronPlatformAdapter (platform), ElectronExportAdapter + ElectronNotificationAdapter (desktop)."};export{I as ElectronExportAdapter,x as ElectronHttpAdapter,A as ElectronNotificationAdapter,v as ElectronPlatformAdapter,$ as ElectronSocketAdapter,O as ElectronStorageAdapter,ie as OFPLATFORM_ELECTRON_HTTP_ADAPTERS_READY,oe as OFPLATFORM_ELECTRON_SOCKET_ADAPTERS_READY,de as OFPLATFORM_ELECTRON_STATUS,S as SQLiteAdapter,b as SQLiteExecutor,g as SQLiteQueryBuilder};
|
|
9
|
+
`)}run(e,t=[]){return this.db.prepare(e).run(...t)}get(e,t=[]){return this.db.prepare(e).get(...t)}all(e,t=[]){return this.db.prepare(e).all(...t)}transaction(e){return this.db.transaction(e)()}escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}mapType(e){switch(e){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"}}parseRow(e,t){let r={};for(let[i,n]of Object.entries(e!=null?e:{})){let s=t[i],a=n;if(n!=null&&s){if(s.type==="boolean")a=!!n;else if(s.type==="date"&&typeof n=="string"){let c=new Date(n);Number.isNaN(c.getTime())||(a=c)}else if((s.type==="json"||s.type==="string[]")&&typeof n=="string")try{a=JSON.parse(n)}catch(c){}}r[i]=a}return r}buildFilter(e,t="t0"){return y.buildFilter(e,t)}buildGroupBy(e,t="t0"){return y.buildGroupBy(e,t)}buildSort(e,t="t0"){return y.buildSort(e,t)}buildSelect(e,t){return y.buildSelect(e,t)}buildInsert(e,t){return y.buildInsert(e,t)}buildUpdate(e,t,r){return y.buildUpdate(e,t,r)}buildDelete(e,t){return y.buildDelete(e,t)}};var A=class{constructor(e){this.savepointDepth=0;this.schemaMap=new Map;var t;this.executor=new T(e.dbPath),this.executor.initMetaTable(),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 getSchemaVersion(){let e=this.executor.get("SELECT version FROM schema_version LIMIT 1");return e?e.version:(this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){if(!this.executor.get("SELECT 1 FROM schema_version LIMIT 1")){this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[e]);return}this.executor.run("UPDATE schema_version SET version = ?",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${this.executor.escapeIdentifier(i.name)} ${this.executor.mapType(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");this.executor.run(`CREATE TABLE IF NOT EXISTS ${this.executor.escapeIdentifier(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(n)} ON ${this.executor.escapeIdentifier(t)}(${this.executor.escapeIdentifier(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if(this.executor.all(`PRAGMA table_info(${this.executor.escapeIdentifier(r)})`).some(a=>a.name===t.name))return;let n=`ALTER TABLE ${this.executor.escapeIdentifier(r)} ADD COLUMN ${this.executor.escapeIdentifier(t.name)} ${this.executor.mapType(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(this.executor.run(n),t.isIndexed){let a=`idx_${r}_${t.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(a)} ON ${this.executor.escapeIdentifier(r)}(${this.executor.escapeIdentifier(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 o,h,f;let r=this.resolveTableName(e),i=(o=t==null?void 0:t.joins)!=null&&o.length?{...t,joins:t.joins.map(p=>({...p,table:this.resolveTableName(p.table)}))}:t,{sql:n,params:s,projectionMap:a}=this.executor.buildSelect(r,i),c=this.executor.all(n,s);if((h=t==null?void 0:t.aggregates)!=null&&h.length)return c;if(t!=null&&t.fields)return((f=t==null?void 0:t.resultShape)!=null?f:"flat")==="nested"&&(a!=null&&a.length)?c.map(g=>{let m={};for(let v of a)m[v.alias]||(m[v.alias]={}),m[v.alias][v.field]=g[v.key];return m}):c;let l=this.schemaMap.get(e);if(!l)return c;let u=Object.fromEntries(l.columns.map(p=>[p.name,p]));return c.map(p=>this.executor.parseRow(p,u))}async create(e,t){var o,h;let r=this.resolveTableName(e),{sql:i,params:n}=this.executor.buildInsert(r,t),s=this.executor.run(i,n),a=(h=t==null?void 0:t.id)!=null?h:(o=s.lastInsertRowid)==null?void 0:o.toString(),c=a?{...t,id:a}:{...t},l=this.schemaMap.get(e);if(!l)return c;let u=Object.fromEntries(l.columns.map(f=>[f.name,f]));return this.executor.parseRow(c,u)}async update(e,t,r){if(!Object.keys(r).length){let c=await this.get(e,t);if(!c)throw new Error(`Record not found: ${e}#${t}`);return c}let i=this.resolveTableName(e),{sql:n,params:s}=this.executor.buildUpdate(i,t,r);this.executor.run(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}=this.executor.buildDelete(r,t);this.executor.run(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 IMMEDIATE":`SAVEPOINT sp${this.savepointDepth}`;this.executor.run(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return this.executor.run(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{this.executor.run(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};import{createHash as k}from"node:crypto";var I=class{getEnvVar(e){return process.env[e]}isOnline(){return typeof navigator!="undefined"&&typeof navigator.onLine!="undefined"?navigator.onLine:!0}async hashPin(e){return k("sha256").update(e).digest("hex")}async verifyPin(e,t){return await this.hashPin(e)===t}};var R=class{constructor(e){this.options=e}configure(e){}createChannel(e){}localNotification(e){this.options.notify(e)}};import P from"node:fs/promises";import D from"node:path";var w=class{constructor(e){this.options=e}getDocumentPath(e){return D.join(this.options.documentsPath,e)}async writeFile(e,t){await P.writeFile(e,t,"utf8")}async share(e){var t,r;await((r=(t=this.options).revealFile)==null?void 0:r.call(t,e))}};function L(d,e){if(!e||Object.keys(e).length===0)return d;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?d.includes("?")?`${d}&${r}`:`${d}?${r}`:d}var x=class{constructor(e={}){let t=e.fetch;if(t)this.fetchImpl=t;else{let r=globalThis.fetch;if(typeof r!="function")throw new Error("ElectronHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch, or ensure the app is running on Electron \u2265 20 / Node.js \u2265 18.");this.fetchImpl=r}}async request(e){var n,s;let t=L(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,c={...(n=e.headers)!=null?n:{}};a&&!c["content-type"]&&!c["Content-Type"]&&(c["content-type"]="application/json");let l=await this.fetchImpl(t,{method:e.method,headers:c,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),u={};l.headers.forEach((f,p)=>{u[p.toLowerCase()]=f});let h=((s=u["content-type"])!=null?s:"").includes("application/json")?await l.json():await l.text();return{status:l.status,headers:u,data:h}}finally{i!==null&&clearTimeout(i)}}};var ce=!0;function M(d){let e=d.query;if(!e||Object.keys(e).length===0)return d.url;let r=new URLSearchParams(e).toString();return d.url.includes("?")?`${d.url}&${r}`:`${d.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("ElectronSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket. In the Electron main process you can use the `ws` package.");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(`ElectronSocketAdapter: 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=M(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("ElectronSocketAdapter: 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 pe=!0;import E from"node:fs";import B from"node:path";var C=class{constructor(e){var r;let t=(r=e.fileName)!=null?r:"storage.json";E.mkdirSync(e.storageDir,{recursive:!0}),this.filePath=B.join(e.storageDir,t);try{this.data=JSON.parse(E.readFileSync(this.filePath,"utf-8"))}catch{this.data={}}}async getItem(e){let t=this.data[e];return t!==void 0?t:null}async setItem(e,t){this.data[e]=t,await E.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}async removeItem(e){delete this.data[e],await E.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}};import{AuthRejectionError as S,createServerAuthoritativeAuthBridge as q}from"ofauth-shared-core";var U={platform:"electron",implemented:!0,notes:"API and Runtime are fully implemented for use with Electron Desktop apps."};function b(d,e){var i,n,s,a,c;let t=new Date().toISOString(),r=d&&typeof d=="object"?d:{};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((c=r.expiresAt)!=null?c:e)}}var $=class{constructor(e){this.options=e;var i,n,s,a,c;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("ElectronServerAuthoritativeAuthHostSupport requires a fetch implementation");if(this.isOnlineResolver=(c=e.isOnline)!=null?c:(()=>!0),!this.serverBaseUrl){this.serverBridge=null;return}let t={login:async({principal:l,secret:u})=>{var p,g,m,v;let o=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({principal:l,secret:u,...this.targetTenantId?{targetTenantId:this.targetTenantId}:{},...this.targetBranchId?{targetBranchId:this.targetBranchId}:{},...this.targetDomainId?{targetDomainId:this.targetDomainId}:{}})}),h=await o.json().catch(()=>({}));if(!o.ok)throw new S(String((p=h.code)!=null?p:"AUTH_UNAUTHORIZED"));let f=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((g=h.accessToken)!=null?g:""),refreshToken:String((m=h.refreshToken)!=null?m:""),session:b(h.session,f),activeContext:(v=h.activeContext)!=null?v:null,activeRoleRef:h.activeRoleRef==null?"":String(h.activeRoleRef)}},refresh:async({refreshToken:l})=>{var f,p,g,m;let u=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:l})}),o=await u.json().catch(()=>({}));if(!u.ok)throw new S(String((f=o.code)!=null?f:"AUTH_UNAUTHORIZED"));let h=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((p=o.accessToken)!=null?p:""),refreshToken:String((g=o.refreshToken)!=null?g:""),session:b(o.session,h),activeContext:(m=o.activeContext)!=null?m:null}},logout:async({accessToken:l,refreshToken:u})=>{let o={"Content-Type":"application/json"};l&&(o.Authorization=`Bearer ${l}`),await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/logout`,{method:"POST",headers:o,body:JSON.stringify({refreshToken:u})}).catch(()=>{})}},r={getCachedIdentity:async l=>{var u,o;return(o=(u=await this.readCacheRecord(l))==null?void 0:u.identity)!=null?o:null},setCachedIdentity:async l=>{let u=await this.readCacheRecord(l.principal);await this.writeCacheRecord(l.principal,{...u,identity:l})},clearCachedIdentity:async l=>{let u=await this.readCacheRecord(l);u&&await this.writeCacheRecord(l,{...u,identity:void 0})},getSessionEnvelope:async l=>{var u,o;return(o=(u=await this.readCacheRecord(l))==null?void 0:u.envelope)!=null?o:null},setSessionEnvelope:async(l,u)=>{let o=await this.readCacheRecord(l);await this.writeCacheRecord(l,{...o,envelope:u})},clearSessionEnvelope:async l=>{let u=await this.readCacheRecord(l);u&&await this.writeCacheRecord(l,{...u,envelope:void 0})}};this.serverBridge=q({authority:t,cache:r,isOnline:()=>this.isOnlineResolver(),verifyOfflineSecret:this.options.verifyOfflineSecret||(async()=>!1)})}async performAuthorityLogin(e,t,r){var u,o,h,f,p,g,m;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=((h=r==null?void 0:r.targetDomainId)==null?void 0:h.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}:{}})}),c=await a.json().catch(()=>({}));if(!a.ok)throw new S(String((f=c.code)!=null?f:"AUTH_UNAUTHORIZED"));let l=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((p=c.accessToken)!=null?p:""),refreshToken:String((g=c.refreshToken)!=null?g:""),session:b(c.session,l),activeContext:(m=c.activeContext)!=null?m:null,activeRoleRef:c.activeRoleRef==null?"":String(c.activeRoleRef)}}get isServerConfigured(){return this.serverBaseUrl.length>0}get capability(){return U}get cacheNamespace(){return this.cacheKey}async loadCacheMap(){if(!this.storage)return{};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){if(this.storage)try{Object.keys(e).length===0?await this.storage.removeItem(this.cacheKey):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 clearCachedSessionEnvelope(e){let t=await this.readCacheRecord(e);t&&await this.writeCacheRecord(e,{...t,envelope:void 0})}async clearAllCachedSessionEnvelopes(){let e=await this.loadCacheMap();for(let t of Object.keys(e)){let r=e[t];r&&(e[t]=r.identity?{identity:r.identity}:{},e[t].identity||delete e[t])}await this.saveCacheMap(e)}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),c=(i=await this.readCacheRecord(e))!=null?i:{};return await this.writeCacheRecord(e,{...c,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 S?a.code:"AUTH_AUTHORITY_UNAVAILABLE"}}}async logout(e){this.serverBridge&&await this.serverBridge.logout(e)}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;if(this.isOnlineResolver()&&s.refreshToken&&this.serverBaseUrl)try{let c=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:s.refreshToken})}),l=await c.json().catch(()=>({}));if(c.ok&&l.accessToken){let u={...s,accessToken:String(l.accessToken),refreshToken:l.refreshToken?String(l.refreshToken):s.refreshToken,activeContext:(i=(r=l.activeContext)!=null?r:s.activeContext)!=null?i:null};return await this.writeCacheRecord(n,{...e[n],envelope:u}),{principal:n,envelope:u}}}catch{}let a=Date.parse(s.expiresAt);if(Number.isFinite(a)&&a>Date.now())return{principal:n,envelope:s}}return null}async getStoredAccessToken(e){var r,i;let t=await this.readCacheRecord(e);return(i=(r=t==null?void 0:t.envelope)==null?void 0:r.accessToken)!=null?i:null}async getStoredEnvelope(e){var r;let t=await this.readCacheRecord(e);return(r=t==null?void 0:t.envelope)!=null?r:null}};var Ie={platform:"electron",ready:!0,notes:"All adapter domains implemented: SQLiteAdapter (db), ElectronHttpAdapter (http), ElectronSocketAdapter (socket), ElectronStorageAdapter (storage), ElectronPlatformAdapter (platform), ElectronExportAdapter + ElectronNotificationAdapter (desktop). Auth bridge surface is scaffolded for parity with ofplatform-web."};export{w as ElectronExportAdapter,x as ElectronHttpAdapter,R as ElectronNotificationAdapter,I as ElectronPlatformAdapter,$ as ElectronServerAuthoritativeAuthHostSupport,O as ElectronSocketAdapter,C as ElectronStorageAdapter,U as OFPLATFORM_ELECTRON_AUTH_STATUS,ce as OFPLATFORM_ELECTRON_HTTP_ADAPTERS_READY,pe as OFPLATFORM_ELECTRON_SOCKET_ADAPTERS_READY,Ie as OFPLATFORM_ELECTRON_STATUS,A as SQLiteAdapter,T as SQLiteExecutor,y as SQLiteQueryBuilder};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var j=Object.create;var A=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var W=(u,e)=>{for(var t in e)A(u,t,{get:e[t],enumerable:!0})},P=(u,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of _(e))!H.call(u,i)&&i!==t&&A(u,i,{get:()=>e[i],enumerable:!(r=F(e,i))||r.enumerable});return u};var E=(u,e,t)=>(t=u!=null?j(V(u)):{},P(e||!u||!u.__esModule?A(t,"default",{value:u,enumerable:!0}):t,u)),Q=u=>P(A({},"__esModule",{value:!0}),u);var Y={};W(Y,{ElectronExportAdapter:()=>x,ElectronHttpAdapter:()=>O,ElectronNotificationAdapter:()=>w,ElectronPlatformAdapter:()=>R,ElectronServerAuthoritativeAuthHostSupport:()=>k,ElectronSocketAdapter:()=>C,ElectronStorageAdapter:()=>$,OFPLATFORM_ELECTRON_AUTH_STATUS:()=>U,OFPLATFORM_ELECTRON_HTTP_ADAPTERS_READY:()=>J,OFPLATFORM_ELECTRON_SOCKET_ADAPTERS_READY:()=>K,OFPLATFORM_ELECTRON_STATUS:()=>X,SQLiteAdapter:()=>I,SQLiteExecutor:()=>S,SQLiteQueryBuilder:()=>y});module.exports=Q(Y);var D=E(require("better-sqlite3"));var y=class{static escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}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(c=>this.normalizeValue(c))}}if(a==="IS NULL"||a==="IS NOT NULL")return{sql:`${s} ${a}`,params:[]};if(a==="LIKE"){let l=("likeMode"in e?e.likeMode:"default")==="case-sensitive"?" COLLATE BINARY":"";return{sql:`${s} LIKE${l} ?`,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,c])=>({sql:`${`${this.escapeIdentifier(t)}.${this.escapeIdentifier(a)}`} = ?`,params:[this.normalizeValue(c)]}));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=[],c=[];if(t!=null&&t.aggregates&&t.aggregates.length>0)t.groupBy&&t.groupBy.forEach(o=>{let p=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field;c.push(`${this.escapeIdentifier(p.tableAlias)}.${this.escapeIdentifier(p.field)} AS ${this.escapeIdentifier(`${p.tableAlias}_${p.field}`)}`)}),t.aggregates.forEach(o=>{let p=typeof o.field=="string"?{tableAlias:i,field:o.field}:o.field,f=`${this.escapeIdentifier(p.tableAlias)}.${this.escapeIdentifier(p.field)}`;c.push(`${o.function}(${f}) AS ${this.escapeIdentifier(o.as)}`)});else if(t!=null&&t.fields){let o=0;for(let[p,f]of Object.entries(t.fields))for(let d of f){let m=((h=r==null?void 0:r.resultShape)!=null?h:"flat")==="nested"?`__c${o++}`:`${p}_${d}`;a.push({key:m,alias:p,field:d}),c.push(`${this.escapeIdentifier(p)}.${this.escapeIdentifier(d)} AS ${this.escapeIdentifier(m)}`)}}else c.push(`${this.escapeIdentifier(i)}.*`);let l=`SELECT ${c.join(", ")} FROM ${this.escapeIdentifier(e)} AS ${this.escapeIdentifier(i)}`;if(n.forEach(o=>{let p=(o.type||"inner").toUpperCase();if(p==="RIGHT"||p==="FULL")throw new Error(`SQLite adapter does not support ${p} JOIN`);let f=[];o.conditions.forEach(d=>{let g=this.buildValueExpr(d.left,i),m=this.buildValueExpr(d.right,i);f.push(`${g.sql} ${d.operator} ${m.sql}`),s.push(...g.params,...m.params)}),l+=` ${p} JOIN ${this.escapeIdentifier(o.table)} AS ${this.escapeIdentifier(o.alias)} ON ${f.join(" AND ")}`}),t!=null&&t.filters){let o=this.buildFilter(t.filters,i);o.sql&&o.sql!=="TRUE"&&(l+=` WHERE ${o.sql}`,s.push(...o.params))}if(t!=null&&t.aggregates&&t.aggregates.length>0){if(l+=this.buildGroupBy(t.groupBy,i),t.having){let o=this.buildFilter(t.having,i);o.sql&&o.sql!=="TRUE"&&(l+=` HAVING ${o.sql}`,s.push(...o.params))}return{sql:l,params:s,projectionMap:a.length?a:void 0}}if(l+=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"&&(l+=` HAVING ${o.sql}`,s.push(...o.params))}if(t!=null&&t.sort&&t.sort.length){let o=this.buildSort(t.sort,i);o&&(l+=` ORDER BY ${o}`)}return(t==null?void 0:t.limit)!==void 0&&(l+=" LIMIT ?",s.push(t.limit)),(t==null?void 0:t.offset)!==void 0&&(l+=" OFFSET ?",s.push(t.offset)),{sql:l,params:s,projectionMap:a.length?a:void 0}}static buildInsert(e,t){let r=Object.keys(t),i=r.map(c=>this.escapeIdentifier(c)).join(", "),n=r.map(()=>"?").join(", "),s=r.map(c=>this.normalizeValue(t[c]));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 query with empty updates payload");let n=i.map(c=>`${this.escapeIdentifier(c)} = ?`).join(", "),s=i.map(c=>this.normalizeValue(r[c]));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.db=new D.default(e)}initMetaTable(){this.db.exec(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS _meta (
|
|
3
3
|
key TEXT PRIMARY KEY,
|
|
4
4
|
value TEXT
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
CREATE TABLE IF NOT EXISTS schema_version (
|
|
7
7
|
version INTEGER NOT NULL
|
|
8
8
|
);
|
|
9
|
-
`)}run(e,t=[]){return this.db.prepare(e).run(...t)}get(e,t=[]){return this.db.prepare(e).get(...t)}all(e,t=[]){return this.db.prepare(e).all(...t)}transaction(e){return this.db.transaction(e)()}escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}mapType(e){switch(e){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"}}parseRow(e,t){let r={};for(let[i,n]of Object.entries(e!=null?e:{})){let s=t[i],a=n;if(n!=null&&s){if(s.type==="boolean")a=!!n;else if(s.type==="date"&&typeof n=="string"){let l=new Date(n);Number.isNaN(l.getTime())||(a=l)}else if((s.type==="json"||s.type==="string[]")&&typeof n=="string")try{a=JSON.parse(n)}catch(l){}}r[i]=a}return r}buildFilter(e,t="t0"){return m.buildFilter(e,t)}buildGroupBy(e,t="t0"){return m.buildGroupBy(e,t)}buildSort(e,t="t0"){return m.buildSort(e,t)}buildSelect(e,t){return m.buildSelect(e,t)}buildInsert(e,t){return m.buildInsert(e,t)}buildUpdate(e,t,r){return m.buildUpdate(e,t,r)}buildDelete(e,t){return m.buildDelete(e,t)}};var A=class{constructor(e){this.savepointDepth=0;this.schemaMap=new Map;var t;this.executor=new T(e.dbPath),this.executor.initMetaTable(),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 getSchemaVersion(){let e=this.executor.get("SELECT version FROM schema_version LIMIT 1");return e?e.version:(this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){if(!this.executor.get("SELECT 1 FROM schema_version LIMIT 1")){this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[e]);return}this.executor.run("UPDATE schema_version SET version = ?",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${this.executor.escapeIdentifier(i.name)} ${this.executor.mapType(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");this.executor.run(`CREATE TABLE IF NOT EXISTS ${this.executor.escapeIdentifier(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(n)} ON ${this.executor.escapeIdentifier(t)}(${this.executor.escapeIdentifier(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if(this.executor.all(`PRAGMA table_info(${this.executor.escapeIdentifier(r)})`).some(a=>a.name===t.name))return;let n=`ALTER TABLE ${this.executor.escapeIdentifier(r)} ADD COLUMN ${this.executor.escapeIdentifier(t.name)} ${this.executor.mapType(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(this.executor.run(n),t.isIndexed){let a=`idx_${r}_${t.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(a)} ON ${this.executor.escapeIdentifier(r)}(${this.executor.escapeIdentifier(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 o,p,f;let r=this.resolveTableName(e),i=(o=t==null?void 0:t.joins)!=null&&o.length?{...t,joins:t.joins.map(h=>({...h,table:this.resolveTableName(h.table)}))}:t,{sql:n,params:s,projectionMap:a}=this.executor.buildSelect(r,i),l=this.executor.all(n,s);if((p=t==null?void 0:t.aggregates)!=null&&p.length)return l;if(t!=null&&t.fields)return((f=t==null?void 0:t.resultShape)!=null?f:"flat")==="nested"&&(a!=null&&a.length)?l.map(y=>{let g={};for(let E of a)g[E.alias]||(g[E.alias]={}),g[E.alias][E.field]=y[E.key];return g}):l;let u=this.schemaMap.get(e);if(!u)return l;let d=Object.fromEntries(u.columns.map(h=>[h.name,h]));return l.map(h=>this.executor.parseRow(h,d))}async create(e,t){var o,p;let r=this.resolveTableName(e),{sql:i,params:n}=this.executor.buildInsert(r,t),s=this.executor.run(i,n),a=(p=t==null?void 0:t.id)!=null?p:(o=s.lastInsertRowid)==null?void 0:o.toString(),l=a?{...t,id:a}:{...t},u=this.schemaMap.get(e);if(!u)return l;let d=Object.fromEntries(u.columns.map(f=>[f.name,f]));return this.executor.parseRow(l,d)}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}=this.executor.buildUpdate(i,t,r);this.executor.run(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}=this.executor.buildDelete(r,t);this.executor.run(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 IMMEDIATE":`SAVEPOINT sp${this.savepointDepth}`;this.executor.run(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return this.executor.run(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{this.executor.run(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};var P=require("node:crypto"),I=class{getEnvVar(e){return process.env[e]}isOnline(){return typeof navigator!="undefined"&&typeof navigator.onLine!="undefined"?navigator.onLine:!0}async hashPin(e){return(0,P.createHash)("sha256").update(e).digest("hex")}async verifyPin(e,t){return await this.hashPin(e)===t}};var x=class{constructor(e){this.options=e}configure(e){}createChannel(e){}localNotification(e){this.options.notify(e)}};var L=b(require("node:fs/promises")),C=b(require("node:path")),$=class{constructor(e){this.options=e}getDocumentPath(e){return C.default.join(this.options.documentsPath,e)}async writeFile(e,t){await L.default.writeFile(e,t,"utf8")}async share(e){var t,r;await((r=(t=this.options).revealFile)==null?void 0:r.call(t,e))}};function _(c,e){if(!e||Object.keys(e).length===0)return c;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?c.includes("?")?`${c}&${r}`:`${c}?${r}`:c}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("ElectronHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch, or ensure the app is running on Electron \u2265 20 / Node.js \u2265 18.");this.fetchImpl=r}}async request(e){var n,s;let t=_(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 u=await this.fetchImpl(t,{method:e.method,headers:l,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),d={};u.headers.forEach((f,h)=>{d[h.toLowerCase()]=f});let p=((s=d["content-type"])!=null?s:"").includes("application/json")?await u.json():await u.text();return{status:u.status,headers:d,data:p}}finally{i!==null&&clearTimeout(i)}}};var U=!0;function Q(c){let e=c.query;if(!e||Object.keys(e).length===0)return c.url;let r=new URLSearchParams(e).toString();return c.url.includes("?")?`${c.url}&${r}`:`${c.url}?${r}`}var w=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("ElectronSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket. In the Electron main process you can use the `ws` package.");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(`ElectronSocketAdapter: 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=Q(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("ElectronSocketAdapter: 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 S=b(require("node:fs")),M=b(require("node:path")),R=class{constructor(e){var r;let t=(r=e.fileName)!=null?r:"storage.json";S.default.mkdirSync(e.storageDir,{recursive:!0}),this.filePath=M.default.join(e.storageDir,t);try{this.data=JSON.parse(S.default.readFileSync(this.filePath,"utf-8"))}catch{this.data={}}}async getItem(e){let t=this.data[e];return t!==void 0?t:null}async setItem(e,t){this.data[e]=t,await S.default.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}async removeItem(e){delete this.data[e],await S.default.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}};var z={platform:"electron",ready:!0,notes:"All adapter domains implemented: SQLiteAdapter (db), ElectronHttpAdapter (http), ElectronSocketAdapter (socket), ElectronStorageAdapter (storage), ElectronPlatformAdapter (platform), ElectronExportAdapter + ElectronNotificationAdapter (desktop)."};0&&(module.exports={ElectronExportAdapter,ElectronHttpAdapter,ElectronNotificationAdapter,ElectronPlatformAdapter,ElectronSocketAdapter,ElectronStorageAdapter,OFPLATFORM_ELECTRON_HTTP_ADAPTERS_READY,OFPLATFORM_ELECTRON_SOCKET_ADAPTERS_READY,OFPLATFORM_ELECTRON_STATUS,SQLiteAdapter,SQLiteExecutor,SQLiteQueryBuilder});
|
|
9
|
+
`)}run(e,t=[]){return this.db.prepare(e).run(...t)}get(e,t=[]){return this.db.prepare(e).get(...t)}all(e,t=[]){return this.db.prepare(e).all(...t)}transaction(e){return this.db.transaction(e)()}escapeIdentifier(e){if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw new Error(`Invalid identifier: "${e}"`);return`"${e}"`}mapType(e){switch(e){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"}}parseRow(e,t){let r={};for(let[i,n]of Object.entries(e!=null?e:{})){let s=t[i],a=n;if(n!=null&&s){if(s.type==="boolean")a=!!n;else if(s.type==="date"&&typeof n=="string"){let c=new Date(n);Number.isNaN(c.getTime())||(a=c)}else if((s.type==="json"||s.type==="string[]")&&typeof n=="string")try{a=JSON.parse(n)}catch(c){}}r[i]=a}return r}buildFilter(e,t="t0"){return y.buildFilter(e,t)}buildGroupBy(e,t="t0"){return y.buildGroupBy(e,t)}buildSort(e,t="t0"){return y.buildSort(e,t)}buildSelect(e,t){return y.buildSelect(e,t)}buildInsert(e,t){return y.buildInsert(e,t)}buildUpdate(e,t,r){return y.buildUpdate(e,t,r)}buildDelete(e,t){return y.buildDelete(e,t)}};var I=class{constructor(e){this.savepointDepth=0;this.schemaMap=new Map;var t;this.executor=new S(e.dbPath),this.executor.initMetaTable(),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 getSchemaVersion(){let e=this.executor.get("SELECT version FROM schema_version LIMIT 1");return e?e.version:(this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[0]),0)}async setSchemaVersion(e){if(!this.executor.get("SELECT 1 FROM schema_version LIMIT 1")){this.executor.run("INSERT INTO schema_version (version) VALUES (?)",[e]);return}this.executor.run("UPDATE schema_version SET version = ?",[e])}async addTable(e){let t=this.resolveTableName(e.name),r=e.columns.map(i=>{let n=`${this.executor.escapeIdentifier(i.name)} ${this.executor.mapType(i.type)}`;return i.isOptional||(n+=" NOT NULL"),i.name==="id"&&(n+=" PRIMARY KEY"),n}).join(", ");this.executor.run(`CREATE TABLE IF NOT EXISTS ${this.executor.escapeIdentifier(t)} (${r})`);for(let i of e.columns){if(!i.isIndexed)continue;let n=`idx_${t}_${i.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(n)} ON ${this.executor.escapeIdentifier(t)}(${this.executor.escapeIdentifier(i.name)})`)}this.schemaMap.set(e.name,e)}async addColumn(e,t){let r=this.resolveTableName(e);if(this.executor.all(`PRAGMA table_info(${this.executor.escapeIdentifier(r)})`).some(a=>a.name===t.name))return;let n=`ALTER TABLE ${this.executor.escapeIdentifier(r)} ADD COLUMN ${this.executor.escapeIdentifier(t.name)} ${this.executor.mapType(t.type)}`;if(!t.isOptional){let a=t.type==="boolean"?"0":t.type==="number"?"0.0":"''";n+=` DEFAULT ${a} NOT NULL`}if(this.executor.run(n),t.isIndexed){let a=`idx_${r}_${t.name}`;this.executor.run(`CREATE INDEX IF NOT EXISTS ${this.executor.escapeIdentifier(a)} ON ${this.executor.escapeIdentifier(r)}(${this.executor.escapeIdentifier(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 o,p,f;let r=this.resolveTableName(e),i=(o=t==null?void 0:t.joins)!=null&&o.length?{...t,joins:t.joins.map(d=>({...d,table:this.resolveTableName(d.table)}))}:t,{sql:n,params:s,projectionMap:a}=this.executor.buildSelect(r,i),c=this.executor.all(n,s);if((p=t==null?void 0:t.aggregates)!=null&&p.length)return c;if(t!=null&&t.fields)return((f=t==null?void 0:t.resultShape)!=null?f:"flat")==="nested"&&(a!=null&&a.length)?c.map(g=>{let m={};for(let v of a)m[v.alias]||(m[v.alias]={}),m[v.alias][v.field]=g[v.key];return m}):c;let l=this.schemaMap.get(e);if(!l)return c;let h=Object.fromEntries(l.columns.map(d=>[d.name,d]));return c.map(d=>this.executor.parseRow(d,h))}async create(e,t){var o,p;let r=this.resolveTableName(e),{sql:i,params:n}=this.executor.buildInsert(r,t),s=this.executor.run(i,n),a=(p=t==null?void 0:t.id)!=null?p:(o=s.lastInsertRowid)==null?void 0:o.toString(),c=a?{...t,id:a}:{...t},l=this.schemaMap.get(e);if(!l)return c;let h=Object.fromEntries(l.columns.map(f=>[f.name,f]));return this.executor.parseRow(c,h)}async update(e,t,r){if(!Object.keys(r).length){let c=await this.get(e,t);if(!c)throw new Error(`Record not found: ${e}#${t}`);return c}let i=this.resolveTableName(e),{sql:n,params:s}=this.executor.buildUpdate(i,t,r);this.executor.run(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}=this.executor.buildDelete(r,t);this.executor.run(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 IMMEDIATE":`SAVEPOINT sp${this.savepointDepth}`;this.executor.run(r),this.savepointDepth+=1;try{let i=await e(this),n=t?"COMMIT":`RELEASE SAVEPOINT sp${this.savepointDepth-1}`;return this.executor.run(n),i}catch(i){let n=t?"ROLLBACK":`ROLLBACK TO SAVEPOINT sp${this.savepointDepth-1}`;try{this.executor.run(n)}catch(s){}throw i}finally{this.savepointDepth-=1}}};var L=require("node:crypto"),R=class{getEnvVar(e){return process.env[e]}isOnline(){return typeof navigator!="undefined"&&typeof navigator.onLine!="undefined"?navigator.onLine:!0}async hashPin(e){return(0,L.createHash)("sha256").update(e).digest("hex")}async verifyPin(e,t){return await this.hashPin(e)===t}};var w=class{constructor(e){this.options=e}configure(e){}createChannel(e){}localNotification(e){this.options.notify(e)}};var M=E(require("node:fs/promises")),B=E(require("node:path")),x=class{constructor(e){this.options=e}getDocumentPath(e){return B.default.join(this.options.documentsPath,e)}async writeFile(e,t){await M.default.writeFile(e,t,"utf8")}async share(e){var t,r;await((r=(t=this.options).revealFile)==null?void 0:r.call(t,e))}};function G(u,e){if(!e||Object.keys(e).length===0)return u;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?u.includes("?")?`${u}&${r}`:`${u}?${r}`:u}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("ElectronHttpAdapter: globalThis.fetch is not available. Pass a fetch implementation via options.fetch, or ensure the app is running on Electron \u2265 20 / Node.js \u2265 18.");this.fetchImpl=r}}async request(e){var n,s;let t=G(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,c={...(n=e.headers)!=null?n:{}};a&&!c["content-type"]&&!c["Content-Type"]&&(c["content-type"]="application/json");let l=await this.fetchImpl(t,{method:e.method,headers:c,body:a?JSON.stringify(e.body):void 0,signal:r==null?void 0:r.signal}),h={};l.headers.forEach((f,d)=>{h[d.toLowerCase()]=f});let p=((s=h["content-type"])!=null?s:"").includes("application/json")?await l.json():await l.text();return{status:l.status,headers:h,data:p}}finally{i!==null&&clearTimeout(i)}}};var J=!0;function z(u){let e=u.query;if(!e||Object.keys(e).length===0)return u.url;let r=new URLSearchParams(e).toString();return u.url.includes("?")?`${u.url}&${r}`:`${u.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("ElectronSocketAdapter: globalThis.WebSocket is not available. Pass a WebSocket constructor via options.webSocket. In the Electron main process you can use the `ws` package.");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(`ElectronSocketAdapter: 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=z(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("ElectronSocketAdapter: 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 K=!0;var b=E(require("node:fs")),q=E(require("node:path")),$=class{constructor(e){var r;let t=(r=e.fileName)!=null?r:"storage.json";b.default.mkdirSync(e.storageDir,{recursive:!0}),this.filePath=q.default.join(e.storageDir,t);try{this.data=JSON.parse(b.default.readFileSync(this.filePath,"utf-8"))}catch{this.data={}}}async getItem(e){let t=this.data[e];return t!==void 0?t:null}async setItem(e,t){this.data[e]=t,await b.default.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}async removeItem(e){delete this.data[e],await b.default.promises.writeFile(this.filePath,JSON.stringify(this.data,null,2),"utf-8")}};var T=require("ofauth-shared-core"),U={platform:"electron",implemented:!0,notes:"API and Runtime are fully implemented for use with Electron Desktop apps."};function N(u,e){var i,n,s,a,c;let t=new Date().toISOString(),r=u&&typeof u=="object"?u:{};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((c=r.expiresAt)!=null?c:e)}}var k=class{constructor(e){this.options=e;var i,n,s,a,c;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("ElectronServerAuthoritativeAuthHostSupport requires a fetch implementation");if(this.isOnlineResolver=(c=e.isOnline)!=null?c:(()=>!0),!this.serverBaseUrl){this.serverBridge=null;return}let t={login:async({principal:l,secret:h})=>{var d,g,m,v;let o=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({principal:l,secret:h,...this.targetTenantId?{targetTenantId:this.targetTenantId}:{},...this.targetBranchId?{targetBranchId:this.targetBranchId}:{},...this.targetDomainId?{targetDomainId:this.targetDomainId}:{}})}),p=await o.json().catch(()=>({}));if(!o.ok)throw new T.AuthRejectionError(String((d=p.code)!=null?d:"AUTH_UNAUTHORIZED"));let f=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((g=p.accessToken)!=null?g:""),refreshToken:String((m=p.refreshToken)!=null?m:""),session:N(p.session,f),activeContext:(v=p.activeContext)!=null?v:null,activeRoleRef:p.activeRoleRef==null?"":String(p.activeRoleRef)}},refresh:async({refreshToken:l})=>{var f,d,g,m;let h=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:l})}),o=await h.json().catch(()=>({}));if(!h.ok)throw new T.AuthRejectionError(String((f=o.code)!=null?f:"AUTH_UNAUTHORIZED"));let p=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((d=o.accessToken)!=null?d:""),refreshToken:String((g=o.refreshToken)!=null?g:""),session:N(o.session,p),activeContext:(m=o.activeContext)!=null?m:null}},logout:async({accessToken:l,refreshToken:h})=>{let o={"Content-Type":"application/json"};l&&(o.Authorization=`Bearer ${l}`),await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/logout`,{method:"POST",headers:o,body:JSON.stringify({refreshToken:h})}).catch(()=>{})}},r={getCachedIdentity:async l=>{var h,o;return(o=(h=await this.readCacheRecord(l))==null?void 0:h.identity)!=null?o:null},setCachedIdentity:async l=>{let h=await this.readCacheRecord(l.principal);await this.writeCacheRecord(l.principal,{...h,identity:l})},clearCachedIdentity:async l=>{let h=await this.readCacheRecord(l);h&&await this.writeCacheRecord(l,{...h,identity:void 0})},getSessionEnvelope:async l=>{var h,o;return(o=(h=await this.readCacheRecord(l))==null?void 0:h.envelope)!=null?o:null},setSessionEnvelope:async(l,h)=>{let o=await this.readCacheRecord(l);await this.writeCacheRecord(l,{...o,envelope:h})},clearSessionEnvelope:async l=>{let h=await this.readCacheRecord(l);h&&await this.writeCacheRecord(l,{...h,envelope:void 0})}};this.serverBridge=(0,T.createServerAuthoritativeAuthBridge)({authority:t,cache:r,isOnline:()=>this.isOnlineResolver(),verifyOfflineSecret:this.options.verifyOfflineSecret||(async()=>!1)})}async performAuthorityLogin(e,t,r){var h,o,p,f,d,g,m;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=((p=r==null?void 0:r.targetDomainId)==null?void 0:p.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}:{}})}),c=await a.json().catch(()=>({}));if(!a.ok)throw new T.AuthRejectionError(String((f=c.code)!=null?f:"AUTH_UNAUTHORIZED"));let l=new Date(Date.now()+15*6e4).toISOString();return{accessToken:String((d=c.accessToken)!=null?d:""),refreshToken:String((g=c.refreshToken)!=null?g:""),session:N(c.session,l),activeContext:(m=c.activeContext)!=null?m:null,activeRoleRef:c.activeRoleRef==null?"":String(c.activeRoleRef)}}get isServerConfigured(){return this.serverBaseUrl.length>0}get capability(){return U}get cacheNamespace(){return this.cacheKey}async loadCacheMap(){if(!this.storage)return{};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){if(this.storage)try{Object.keys(e).length===0?await this.storage.removeItem(this.cacheKey):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 clearCachedSessionEnvelope(e){let t=await this.readCacheRecord(e);t&&await this.writeCacheRecord(e,{...t,envelope:void 0})}async clearAllCachedSessionEnvelopes(){let e=await this.loadCacheMap();for(let t of Object.keys(e)){let r=e[t];r&&(e[t]=r.identity?{identity:r.identity}:{},e[t].identity||delete e[t])}await this.saveCacheMap(e)}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),c=(i=await this.readCacheRecord(e))!=null?i:{};return await this.writeCacheRecord(e,{...c,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 T.AuthRejectionError?a.code:"AUTH_AUTHORITY_UNAVAILABLE"}}}async logout(e){this.serverBridge&&await this.serverBridge.logout(e)}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;if(this.isOnlineResolver()&&s.refreshToken&&this.serverBaseUrl)try{let c=await this.fetchImpl(`${this.serverBaseUrl}/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:s.refreshToken})}),l=await c.json().catch(()=>({}));if(c.ok&&l.accessToken){let h={...s,accessToken:String(l.accessToken),refreshToken:l.refreshToken?String(l.refreshToken):s.refreshToken,activeContext:(i=(r=l.activeContext)!=null?r:s.activeContext)!=null?i:null};return await this.writeCacheRecord(n,{...e[n],envelope:h}),{principal:n,envelope:h}}}catch{}let a=Date.parse(s.expiresAt);if(Number.isFinite(a)&&a>Date.now())return{principal:n,envelope:s}}return null}async getStoredAccessToken(e){var r,i;let t=await this.readCacheRecord(e);return(i=(r=t==null?void 0:t.envelope)==null?void 0:r.accessToken)!=null?i:null}async getStoredEnvelope(e){var r;let t=await this.readCacheRecord(e);return(r=t==null?void 0:t.envelope)!=null?r:null}};var X={platform:"electron",ready:!0,notes:"All adapter domains implemented: SQLiteAdapter (db), ElectronHttpAdapter (http), ElectronSocketAdapter (socket), ElectronStorageAdapter (storage), ElectronPlatformAdapter (platform), ElectronExportAdapter + ElectronNotificationAdapter (desktop). Auth bridge surface is scaffolded for parity with ofplatform-web."};0&&(module.exports={ElectronExportAdapter,ElectronHttpAdapter,ElectronNotificationAdapter,ElectronPlatformAdapter,ElectronServerAuthoritativeAuthHostSupport,ElectronSocketAdapter,ElectronStorageAdapter,OFPLATFORM_ELECTRON_AUTH_STATUS,OFPLATFORM_ELECTRON_HTTP_ADAPTERS_READY,OFPLATFORM_ELECTRON_SOCKET_ADAPTERS_READY,OFPLATFORM_ELECTRON_STATUS,SQLiteAdapter,SQLiteExecutor,SQLiteQueryBuilder});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofplatform-electron",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Electron platform adapters for of* host apps.",
|
|
6
6
|
"author": {
|
|
@@ -32,11 +32,15 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"better-sqlite3": "^11.8.1",
|
|
35
|
-
"ofcore": "0.2.0-alpha.
|
|
35
|
+
"ofcore": "0.2.0-alpha.1"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"ofauth-shared-core": "0.2.0-alpha.1"
|
|
36
39
|
},
|
|
37
40
|
"devDependencies": {
|
|
38
41
|
"@types/better-sqlite3": "^7.6.12",
|
|
39
42
|
"esbuild": "^0.25.11",
|
|
43
|
+
"ofauth-shared-core": "0.2.0-alpha.1",
|
|
40
44
|
"typescript": "^5.9.3"
|
|
41
45
|
},
|
|
42
46
|
"publishConfig": {
|