ofcore 0.1.0-alpha.0 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contracts/ResponseEnvelope.d.ts +1 -0
- package/dist/defaults/InMemoryDbAdapter.d.ts +3 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +1 -1
- package/dist/ports/DbAdapter.d.ts +10 -0
- package/dist/utils/serviceHelpers.d.ts +5 -0
- package/package.json +3 -2
|
@@ -25,3 +25,4 @@ export interface FailureEnvelope {
|
|
|
25
25
|
}
|
|
26
26
|
export type ResponseEnvelope<T> = SuccessEnvelope<T> | FailureEnvelope;
|
|
27
27
|
export declare function isFailureEnvelope<T>(value: ResponseEnvelope<T>): value is FailureEnvelope;
|
|
28
|
+
export declare function unwrap<T>(envelope: ResponseEnvelope<T>): T;
|
|
@@ -6,6 +6,9 @@ import { DbAdapter, TableSchema, ColumnDefinition, DbSchema, QueryOptions, Liter
|
|
|
6
6
|
export declare class InMemoryDbAdapter implements DbAdapter {
|
|
7
7
|
schema: DbSchema;
|
|
8
8
|
private data;
|
|
9
|
+
private tableNameResolver;
|
|
10
|
+
setTableNameResolver(resolver: (logicalTableName: string) => string): void;
|
|
11
|
+
resolveTableName(logicalTableName: string): string;
|
|
9
12
|
/**
|
|
10
13
|
* Initialize with a full schema (e.g., from `schemas`).
|
|
11
14
|
*/
|
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var C=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var Q=(o,t)=>{for(var e in t)C(o,e,{get:t[e],enumerable:!0})},G=(o,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of W(t))!J.call(o,n)&&n!==e&&C(o,n,{get:()=>t[n],enumerable:!(r=B(t,n))||r.enumerable});return o};var K=o=>G(C({},"__esModule",{value:!0}),o);var pt={};Q(pt,{ConsoleLoggerAdapter:()=>H,CoreAdapterRegistry:()=>k,CoreRuntime:()=>T,CoreRuntimeBuilder:()=>R,DefaultExportAdapter:()=>_,DefaultHttpAdapter:()=>I,DefaultPlatformAdapter:()=>P,ExponentialBackoffHttpPolicy:()=>F,InMemoryDbAdapter:()=>D,InMemorySocketAdapter:()=>M,MemoryActivitySink:()=>L,MemoryStorageAdapter:()=>$,NoRetryHttpPolicy:()=>w,NoopActivitySink:()=>x,NoopChecksumAdapter:()=>S,NoopEncryptionAdapter:()=>V,NoopNotificationAdapter:()=>O,applyPendingMigrations:()=>it,areChecksumsEqual:()=>Z,asReadonlyStore:()=>ct,createStore:()=>at,executeHttpRequestWithRetry:()=>Y,isContractVersionCompatible:()=>et,isFailureEnvelope:()=>tt,migrations:()=>U,normalizeChecksum:()=>E,runDbAdapterContractHarness:()=>st});module.exports=K(pt);var P=class{constructor(t){}getEnvVar(t){let e=globalThis.process;if(typeof e!="undefined"&&e.env)return e.env[t]}isOnline(){return typeof globalThis.navigator!="undefined"&&typeof globalThis.navigator.onLine!="undefined"?!!globalThis.navigator.onLine:!0}async hashPin(t){return`sha256:${t}`}async verifyPin(t,e){return await this.hashPin(t)===e}};async function X(o){o<=0||await new Promise(t=>setTimeout(t,o))}async function Y(o,t,e={}){var s;let r=e.policy,n=(s=e.sleep)!=null?s:X,i=1;for(;;)try{let a=await o.request(t);if(!r)return a;let p={request:t,attempt:i,response:a};if(!r.shouldRetry(p))return a;let c=Math.max(0,r.nextDelayMs(p));await n(c),i+=1}catch(a){if(!r)throw a;let p={request:t,attempt:i,error:a};if(!r.shouldRetry(p))throw a;let c=Math.max(0,r.nextDelayMs(p));await n(c),i+=1}}function E(o){return String(o||"").trim().toLowerCase()}function Z(o,t){return E(o)===E(t)}function tt(o){return typeof(o==null?void 0:o.error)=="object"&&o!==null}function et(o,t,e){return e===o?!0:t.includes(e)}var D=class{constructor(){this.schema={version:0,tables:[]};this.data={};this.transactionDepth=0;this.snapshots=[]}async setUpWithSchema(t){this.schema={...t},this.data={},t.tables.forEach(e=>{this.data[e.name]=[]})}normalizeForComparison(t){if(t instanceof Date)return t.getTime();if(typeof t=="boolean")return t?1:0;if(typeof t=="string"||typeof t=="number"||t==null)return t;if(Array.isArray(t))return t.map(e=>this.normalizeForComparison(e));if(typeof t=="object"&&t!==null)try{return JSON.stringify(t)}catch{return String(t)}return t}evalValueExpr(t,e,r,n="t0"){if(r.type==="column"){let i=r.tableAlias||n,s=i===n?t:e[i]||{};return this.normalizeForComparison(s[r.field])}if(r.type==="literal")return this.normalizeForComparison(r.value);throw new Error(`Unsupported ValueExpression type: ${r.type}`)}buildFieldCondition(t,e){if("field"in t){let n={type:"column",tableAlias:t.alias||e,field:t.field},i={type:"literal",value:t.value};return{left:n,operator:t.operator||"=",right:i,...t.operator==="BETWEEN"?{}:{likeMode:t.likeMode}}}if("left"in t)return t;throw new Error("Invalid FieldCondition")}matchFilterExpression(t,e,r,n="t0"){if(r&&typeof r=="object"&&!Array.isArray(r)&&"and"in r)return r.and.every(i=>this.matchFilterExpression(t,e,i,n));if(r&&typeof r=="object"&&!Array.isArray(r)&&"or"in r)return r.or.some(i=>this.matchFilterExpression(t,e,i,n));if(r!==null&&typeof r=="object"&&!Array.isArray(r)){if("left"in r||"field"in r){let i=this.buildFieldCondition(r,n),s=this.evalValueExpr(t,e,i.left,n),a=this.evalValueExpr(t,e,i.right,n);if(i.operator==="IS NULL")return s==null;if(i.operator==="IS NOT NULL")return s!=null;if(i.operator==="IN"||i.operator==="NOT IN"){if(!Array.isArray(a))throw new Error("IN/NOT IN requires array on right side");let p=a.includes(s);return i.operator==="IN"?p:!p}switch(i.operator){case"=":return s===a;case"!=":return s!==a;case"<":return s<a;case"<=":return s<=a;case">":return s>a;case">=":return s>=a;case"LIKE":{if(typeof s!="string"||typeof a!="string")return!1;let p=a.replace(/%/g,".*").replace(/_/g,"."),c=i.likeMode;return new RegExp(`^${p}$`,c==="case-insensitive"?"i":"").test(s)}default:throw new Error(`Unsupported operator: ${i.operator}`)}}return Object.entries(r).every(([i,s])=>{let a=this.normalizeForComparison(t[i]),p=this.normalizeForComparison(s);return a===p})}throw new Error(`Invalid filter expression: ${JSON.stringify(r)}`)}simulateJoins(t,e,r){if(r.length===0)return e.map(i=>({record:i,joined:{}}));let n=[];for(let i of e){let s={},a=!0;for(let p of r){let c=p.table,d=this.data[c]||[],m=null;if(p.conditions.length===1){let l=p.conditions[0];if(l.operator==="="&&l.left.type==="column"&&l.right.type==="column"){let g=l.left.tableAlias||"t0",f=l.right.tableAlias;if(g==="t0"&&f===p.alias){let y=l.left.field,u=l.right.field,h=i[y];m=d.find(A=>this.normalizeForComparison(A[u])===this.normalizeForComparison(h))}}}if(!m&&(p.type==="inner"||p.type===void 0)){a=!1;break}s[p.alias]=m||null}a&&n.push({record:i,joined:s})}return n}extractField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let i=r.tableAlias||n,s=i===n?t:e[i]||{};return this.normalizeForComparison(s[r.field])}extractAggregateField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let i=r.tableAlias||n,s=i===n?t:e[i]||{};return this.normalizeForComparison(s[r.field])}async getSchemaVersion(){return this.schema.version}async setSchemaVersion(t){this.schema.version=t}async addTable(t){this.data[t.name]||(this.data[t.name]=[]),this.schema.tables.find(e=>e.name===t.name)||this.schema.tables.push(t)}async addColumn(t,e){}async get(t,e){var n;if(typeof e=="string"){let s=(this.data[t]||[]).find(a=>a.id===e);return s||null}return(n=(await this.query(t,{...e,limit:1}))[0])!=null?n:null}async query(t,e={}){var c;let n=[...this.data[t]||[]],i=this.simulateJoins(t,n,e.joins||[]);if(e.filters&&(i=i.filter(({record:d,joined:m})=>this.matchFilterExpression(d,m,e.filters,"t0"))),e.aggregates&&e.aggregates.length>0){let d={};for(let m of e.aggregates){let l=i;m.filter&&(l=l.filter(({record:u,joined:h})=>this.matchFilterExpression(u,h,m.filter,"t0")));let g=l.map(({record:u,joined:h})=>this.extractAggregateField(u,h,m.field,"t0")),f=g.map(u=>typeof u=="number"?u:Number(u)).filter(u=>Number.isFinite(u)),y=null;switch(m.function){case"COUNT":y=g.filter(u=>u!=null).length;break;case"SUM":y=f.reduce((u,h)=>u+h,0);break;case"AVG":y=f.length?f.reduce((u,h)=>u+h,0)/f.length:0;break;case"MIN":y=f.length?Math.min(...f):null;break;case"MAX":y=f.length?Math.max(...f):null;break;default:throw new Error(`Unsupported aggregate function: ${m.function}`)}d[m.as]=y}return[d]}let s=i.map(({record:d,joined:m})=>{if(e.fields){let l={};for(let[g,f]of Object.entries(e.fields)){let y=g==="t0"?d:m[g]||{};for(let u of f)l[`${g}_${u}`]=y[u]}return l}return d});e.sort&&e.sort.length>0&&s.sort((d,m)=>{for(let l of e.sort){let g=this.extractField(d,{},l.field,"t0"),f=this.extractField(m,{},l.field,"t0");if(g<f)return l.direction==="asc"?-1:1;if(g>f)return l.direction==="asc"?1:-1}return 0});let a=(c=e.offset)!=null?c:0,p=e.limit!=null?a+e.limit:void 0;return s.slice(a,p)}async create(t,e){this.data[t]||(this.data[t]=[]);let r={...e};return this.data[t].push(r),r}async update(t,e,r){let n=this.data[t]||[],i=n.findIndex(a=>a.id===e);if(i===-1)throw new Error(`Record not found: ${t} with id ${e}`);let s={...n[i],...r};return n[i]=s,s}async delete(t,e){let r=this.data[t]||[],n=r.findIndex(i=>i.id===e);n>=0&&r.splice(n,1)}async bulkCreate(t,e){this.data[t]||(this.data[t]=[]);let r=[...this.data[t]];try{let n=[];for(let i of e){let s={...i};this.data[t].push(s),n.push(s)}return n}catch(n){throw this.data[t]=r,n}}async bulkUpdate(t,e){let r=[...this.data[t]||[]];try{let n=[];for(let{id:i,updates:s}of e){let a=await this.update(t,i,s);n.push(a)}return n}catch(n){throw this.data[t]=r,n}}takeSnapshot(){let t={};for(let e in this.data)t[e]=[...this.data[e]];return t}async transaction(t){let e=this.transactionDepth===0;e&&this.snapshots.push(this.takeSnapshot()),this.transactionDepth++;try{let r=await t(this);return e&&this.snapshots.pop(),this.transactionDepth--,r}catch(r){if(e){let n=this.snapshots.pop();n&&(this.data=n)}throw this.transactionDepth--,r}}};var H=class{constructor(t){}logInfo(t,e){console.log(t,e)}logWarn(t,e){console.warn(t,e)}logError(t,e){console.error(t,e)}};function rt(o,t){if(!t||Object.keys(t).length===0)return o;let e=new URLSearchParams;for(let[n,i]of Object.entries(t))i!=null&&e.set(n,String(i));let r=e.toString();return r?o.includes("?")?`${o}&${r}`:`${o}?${r}`:o}var I=class{constructor(t){this.fetchImpl=t}async request(t){var s,a,p,c,d,m,l,g,f;let e=(s=this.fetchImpl)!=null?s:globalThis.fetch;if(typeof e!="function")throw new Error("DefaultHttpAdapter requires fetch implementation");let r=rt(t.url,t.query),n=typeof AbortController!="undefined"?new AbortController:null,i=n&&t.timeoutMs?setTimeout(()=>n.abort(),t.timeoutMs):null;try{let y=t.body!==void 0&&t.body!==null,u={...(a=t.headers)!=null?a:{}};y&&!u["content-type"]&&(u["content-type"]="application/json");let h=await e(r,{method:t.method,headers:u,body:y?JSON.stringify(t.body):void 0,signal:n==null?void 0:n.signal}),A={};(c=(p=h.headers)==null?void 0:p.forEach)==null||c.call(p,(z,q)=>{A[q.toLowerCase()]=z});let j=((d=A["content-type"])!=null?d:"").includes("application/json")?await((l=(m=h.json)==null?void 0:m.call(h))!=null?l:Promise.resolve(void 0)):await((f=(g=h.text)==null?void 0:g.call(h))!=null?f:Promise.resolve(""));return{status:h.status,headers:A,data:j}}finally{i&&clearTimeout(i)}}};var w=class{constructor(t){}shouldRetry(t){return!1}nextDelayMs(t){return 0}};var nt=[408,425,429,500,502,503,504],F=class{constructor(t={}){var e,r,n,i;this.maxAttempts=Math.max(1,(e=t.maxAttempts)!=null?e:3),this.baseDelayMs=Math.max(0,(r=t.baseDelayMs)!=null?r:250),this.maxDelayMs=Math.max(this.baseDelayMs,(n=t.maxDelayMs)!=null?n:3e3),this.retryableStatusCodes=new Set((i=t.retryableStatusCodes)!=null?i:nt)}shouldRetry(t){var r,n;if(t.attempt>=this.maxAttempts)return!1;if(t.error)return!0;let e=(n=(r=t.response)==null?void 0:r.status)!=null?n:0;return this.retryableStatusCodes.has(e)}nextDelayMs(t){let e=Math.max(0,t.attempt-1),r=this.baseDelayMs*Math.pow(2,e);return Math.min(this.maxDelayMs,r)}};var M=class{constructor(){this.connected=!1;this.listeners=new Map}async connect(t){this.connectionOptions=t,this.connected=!0}async disconnect(){this.connected=!1}subscribe(t,e){this.listeners.has(t)||this.listeners.set(t,new Set);let r=this.listeners.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&this.listeners.delete(t)}}async publish(t,e){if(!this.connected)throw new Error(`InMemorySocketAdapter is not connected (event=${t})`);let r=this.listeners.get(t);if(!(!r||r.size===0))for(let n of r)n(e)}isConnected(){return this.connected}getConnectionOptions(){return this.connectionOptions}};var O=class{constructor(t){}configure(t){}createChannel(t){}localNotification(t){}};var V=class{constructor(t){}encrypt(t,e){return String(t)}decrypt(t,e){return String(t)}};var S=class{constructor(t){}compute(t){return""}verify(t,e){return String(e||"").trim()===""}};var x=class{constructor(t){}publish(t){}};var L=class{constructor(t){this.records=[]}publish(t){this.records.push(t)}getRecords(){return[...this.records]}clear(){this.records.length=0}};var _=class{constructor(t){}getDocumentPath(t){return t}async writeFile(t,e){throw new Error("exportAdapter.writeFile is not implemented for this platform")}async share(t){throw new Error("exportAdapter.share is not implemented for this platform")}};var $=class{constructor(t){this.map=new Map}getItem(t){var e;return(e=this.map.get(t))!=null?e:null}setItem(t,e){this.map.set(t,e)}removeItem(t){this.map.delete(t)}};var U=[];async function it(o,t){if(typeof o.getSchemaVersion!="function"||typeof o.setSchemaVersion!="function"){let e="Adapter does not support schema versioning (getSchemaVersion/setSchemaVersion required)";throw t.logError(new Error(e),{message:e}),new Error(e)}t.logInfo("Starting database migration process");try{let e=[...U].sort((i,s)=>i.toVersion-s.toVersion),r=e.length>0?e[e.length-1].toVersion:0,n=await o.getSchemaVersion();if((n==null||n<0)&&(n=0),n>=r){t.logInfo(`Database is already up-to-date at v${n}`);return}t.logInfo(`Migrating database from v${n} to v${r}`);for(let i of e)i.toVersion>n&&(t.logInfo(`Applying migration: v${i.toVersion}`),await i.up(o),await o.setSchemaVersion(i.toVersion),n=i.toVersion);t.logInfo("Database migration completed successfully")}catch(e){throw t.logError(e,{message:"Database migration failed"}),e}}function v(o,t){if(!o)throw new Error(t)}function b(o,t){return`${o}-${t}`}function ot(o){let t=[{name:"id",type:"string"},{name:"name",type:"string"},{name:"age",type:"number"},{name:"tenantId",type:"string"},{name:"isActive",type:"boolean"}];return{name:`${o}_users`,columns:t,skipMetadataColumns:!0}}async function st(o,t={}){var u;let e=((u=t.prefix)!=null?u:`dbadapter_${Date.now()}`).replace(/[^a-zA-Z0-9_]/g,"_"),r=`${e}_users`;await o.setSchemaVersion(7);let n=await o.getSchemaVersion();v(n===7,`Expected schema version 7, got ${n}`),await o.addTable(ot(e)),await o.addColumn(r,{name:"email",type:"string",isOptional:!0}),await o.create(r,{id:b(e,"u1"),name:"Alice",age:31,tenantId:"tenant-1",isActive:!0,email:"alice@example.com"}),await o.create(r,{id:b(e,"u2"),name:"Bob",age:24,tenantId:"tenant-1",isActive:!1,email:"bob@example.com"}),await o.bulkCreate(r,[{id:b(e,"u3"),name:"Carla",age:29,tenantId:"tenant-2",isActive:!0,email:"carla@example.com"},{id:b(e,"u4"),name:"Dian",age:22,tenantId:"tenant-2",isActive:!0}]);let i=await o.get(r,b(e,"u1"));v((i==null?void 0:i.name)==="Alice","Expected get(table, id) to return Alice");let s=await o.query(r,{filters:{tenantId:"tenant-1"},sort:[{field:"age",direction:"desc"}]});v(s.length===2,`Expected 2 tenant-1 users, got ${s.length}`),v(s[0].age>=s[1].age,"Expected sorted by age desc");let a={and:[{field:"tenantId",value:"tenant-2"},{field:"isActive",value:!0}]},p=await o.query(r,{filters:a,sort:[{field:"name",direction:"asc"}]});v(p.length===2,`Expected 2 active tenant-2 users, got ${p.length}`);let c={filters:{and:[{field:"id",value:b(e,"u2")},{field:"tenantId",value:"tenant-1"}]}},d=await o.get(r,c);v((d==null?void 0:d.name)==="Bob","Expected get(table, options) to resolve Bob");let m=await o.update(r,b(e,"u1"),{age:32});v(m.age===32,`Expected age updated to 32, got ${m.age}`);let l=await o.bulkUpdate(r,[{id:b(e,"u3"),updates:{age:30}},{id:b(e,"u4"),updates:{age:23}}]);v(l.length===2,`Expected 2 bulk-updated rows, got ${l.length}`);let g=await o.query(r,{sort:[{field:"age",direction:"asc"}],limit:2,offset:1});v(g.length===2,`Expected 2 paged rows, got ${g.length}`);try{throw await o.transaction(async h=>{throw await h.create(r,{id:b(e,"tx_rollback"),name:"TxRollback",age:40,tenantId:"tenant-1",isActive:!0}),new Error("rollback-intent")}),new Error("Expected transaction rollback to throw")}catch(h){let A=h instanceof Error?h.message:String(h);v(A.includes("rollback-intent"),`Expected rollback-intent error, got ${A}`)}let f=await o.get(r,b(e,"tx_rollback"));v(f===null,"Expected rolled back record to not exist"),await o.delete(r,b(e,"u2"));let y=await o.get(r,b(e,"u2"));v(y===null,"Expected deleted record to be null")}var k=class{constructor(t,e){this.extensions=new Map;var r,n,i,s,a,p,c,d,m,l,g,f,y;this.platformAdapter=(r=e.platformAdapter)==null?void 0:r.call(e,t),this.dbAdapter=(n=e.dbAdapter)==null?void 0:n.call(e,t),this.loggerAdapter=(i=e.loggerAdapter)==null?void 0:i.call(e,t),this.httpAdapter=(s=e.httpAdapter)==null?void 0:s.call(e,t),this.httpRetryPolicy=(p=(a=e.httpRetryPolicy)==null?void 0:a.call(e,t))!=null?p:new w(t),this.socketAdapter=(c=e.socketAdapter)==null?void 0:c.call(e,t),this.encryptionAdapter=(d=e.encryptionAdapter)==null?void 0:d.call(e,t),this.checksumAdapter=(l=(m=e.checksumAdapter)==null?void 0:m.call(e,t))!=null?l:new S(t),this.activitySink=(f=(g=e.activitySink)==null?void 0:g.call(e,t))!=null?f:new x(t);for(let[u,h]of Object.entries((y=e.extensions)!=null?y:{}))this.extensions.set(u,h(t))}getExtension(t){return this.extensions.get(t)}clear(){this.extensions.clear()}};function N(o){return!!o&&typeof o.shutdown=="function"}var T=class{constructor(){this.correlationCounter=0;this.started=!1;this.pluginsLoaded=!1;this.pendingPlugins=[];this.hooks={}}static builder(){return new R}setHooks(t){this.hooks={...this.hooks,...t}}use(t,e,r=[]){if(!t.trim())throw new Error("plugin name is required");return this.pendingPlugins.some(n=>n.name===t)?this:(this.pendingPlugins.push({name:t,init:e,deps:r}),this)}async init(t={runMigrations:!0,useSeedData:!1}){if(!this.registry)throw new Error("CoreRuntime registry is not initialized. Call builder().build() first.");if(t.runMigrations!==!1&&this.hooks.runMigrations&&await this.hooks.runMigrations(this),this.hooks.onInit&&await this.hooks.onInit(this),!this.domainServices&&this.hooks.createDomainServices&&(this.domainServices=await this.hooks.createDomainServices(this)),!this.integrationServices&&this.hooks.createIntegrationServices&&(this.integrationServices=await this.hooks.createIntegrationServices(this)),!this.pluginsLoaded){let n=this.resolvePluginLevels();for(let i of n)await Promise.all(i.map(s=>s.init(this)));this.pluginsLoaded=!0}t.useSeedData===!0&&this.hooks.runSeed&&await this.hooks.runSeed(this)}async start(t={}){if(this.started)throw new Error("CoreRuntime already started");try{await this.init(t),this.started=!0}catch(e){throw this.started=!1,e}}async stop(){var t;this.started&&(this.hooks.onStop&&await this.hooks.onStop(this),N(this.integrationServices)&&await this.integrationServices.shutdown(),N(this.domainServices)&&await this.domainServices.shutdown(),(t=this.registry)==null||t.clear(),this.started=!1)}async reset(){await this.stop(),this.domainServices=void 0,this.integrationServices=void 0,this.pendingPlugins=[],this.pluginsLoaded=!1,this.hooks={}}async restart(){let t=[...this.pendingPlugins],e={...this.hooks};await this.reset(),this.pendingPlugins=t,this.hooks=e,await this.start()}isStarted(){return this.started}createCorrelationId(t="cid"){return this.correlationCounter+=1,`${t}-${Date.now()}-${this.correlationCounter}`}logInfo(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logInfo(t,e)}logWarn(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logWarn(t,e)}logError(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logError(t,e)}async emitActivity(t){var e;(e=this.registry)!=null&&e.activitySink&&await this.registry.activitySink.publish(t)}resolvePluginLevels(){var s,a,p;if(this.pendingPlugins.length===0)return[];let t=new Map,e=new Map,r=new Map;for(let c of this.pendingPlugins){if(t.has(c.name))throw new Error(`Duplicate plugin name: ${c.name}`);t.set(c.name,[]),e.set(c.name,0),r.set(c.name,c)}for(let c of this.pendingPlugins)for(let d of c.deps){if(!t.has(d))throw new Error(`Plugin "${c.name}" depends on unknown plugin "${d}"`);t.get(d).push(c.name),e.set(c.name,((s=e.get(c.name))!=null?s:0)+1)}let n=[],i=Array.from(e.entries()).filter(([,c])=>c===0).map(([c])=>c);for(;i.length>0;){let c=i.map(m=>r.get(m));n.push(c);let d=[];for(let m of i)for(let l of(a=t.get(m))!=null?a:[]){let g=((p=e.get(l))!=null?p:0)-1;e.set(l,g),g===0&&d.push(l)}i=d}if(n.flat().length!==this.pendingPlugins.length)throw new Error("Circular dependency detected among plugins");return n}},R=class{constructor(){this.runtime=new T;this.adapterOptions={};this.hooks={}}withPlatformAdapter(t){return this.adapterOptions.platformAdapter=t,this}withDbAdapter(t){return this.adapterOptions.dbAdapter=t,this}withHttpAdapter(t){return this.adapterOptions.httpAdapter=t,this}withHttpRetryPolicy(t){return this.adapterOptions.httpRetryPolicy=t,this}withSocketAdapter(t){return this.adapterOptions.socketAdapter=t,this}withEncryptionAdapter(t){return this.adapterOptions.encryptionAdapter=t,this}withChecksumAdapter(t){return this.adapterOptions.checksumAdapter=t,this}withActivitySink(t){return this.adapterOptions.activitySink=t,this}withLoggerAdapter(t){return this.adapterOptions.loggerAdapter=t,this}withExtension(t,e){var r;return this.adapterOptions.extensions=(r=this.adapterOptions.extensions)!=null?r:{},this.adapterOptions.extensions[t]=e,this}withHooks(t){return this.hooks={...this.hooks,...t},this}build(){return this.runtime.setHooks(this.hooks),this.runtime.registry=new k(this.runtime,this.adapterOptions),this.runtime}};function at(o){let t=o,e=new Set,r=(n,i)=>{for(let s of e)s(n,i)};return{getState(){return t},setState(n){let i=t;return t=typeof n=="function"?n(t):{...t,...n},r(t,i),t},reset(n){let i=t;return t=n!=null?n:o,r(t,i),t},subscribe(n){return e.add(n),()=>{e.delete(n)}}}}function ct(o){return{getState:o.getState,subscribe:o.subscribe}}
|
|
1
|
+
"use strict";var H=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var tt=Object.prototype.hasOwnProperty;var et=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:!0})},rt=(i,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Z(t))!tt.call(i,n)&&n!==e&&H(i,n,{get:()=>t[n],enumerable:!(r=Y(t,n))||r.enumerable});return i};var nt=i=>rt(H({},"__esModule",{value:!0}),i);var wt={};et(wt,{ConsoleLoggerAdapter:()=>V,CoreAdapterRegistry:()=>P,CoreRuntime:()=>D,CoreRuntimeBuilder:()=>I,DefaultExportAdapter:()=>z,DefaultHttpAdapter:()=>L,DefaultPlatformAdapter:()=>F,ExponentialBackoffHttpPolicy:()=>$,InMemoryDbAdapter:()=>O,InMemorySocketAdapter:()=>_,MemoryActivitySink:()=>U,MemoryStorageAdapter:()=>q,NoRetryHttpPolicy:()=>T,NoopActivitySink:()=>E,NoopChecksumAdapter:()=>R,NoopEncryptionAdapter:()=>j,NoopNotificationAdapter:()=>N,applyPendingMigrations:()=>dt,areChecksumsEqual:()=>st,asReadonlyStore:()=>ft,cloneValue:()=>vt,createStore:()=>gt,executeHttpRequestWithRetry:()=>ot,isContractVersionCompatible:()=>ct,isFailureEnvelope:()=>K,makeIdFactory:()=>bt,migrations:()=>B,normalizeChecksum:()=>M,nowIso:()=>yt,runDbAdapterContractHarness:()=>ht,toAndFilter:()=>At,unwrap:()=>at});module.exports=nt(wt);var F=class{constructor(t){}getEnvVar(t){let e=globalThis.process;if(typeof e!="undefined"&&e.env)return e.env[t]}isOnline(){return typeof globalThis.navigator!="undefined"&&typeof globalThis.navigator.onLine!="undefined"?!!globalThis.navigator.onLine:!0}async hashPin(t){return`sha256:${t}`}async verifyPin(t,e){return await this.hashPin(t)===e}};async function it(i){i<=0||await new Promise(t=>setTimeout(t,i))}async function ot(i,t,e={}){var s;let r=e.policy,n=(s=e.sleep)!=null?s:it,o=1;for(;;)try{let a=await i.request(t);if(!r)return a;let c={request:t,attempt:o,response:a};if(!r.shouldRetry(c))return a;let l=Math.max(0,r.nextDelayMs(c));await n(l),o+=1}catch(a){if(!r)throw a;let c={request:t,attempt:o,error:a};if(!r.shouldRetry(c))throw a;let l=Math.max(0,r.nextDelayMs(c));await n(l),o+=1}}function M(i){return String(i||"").trim().toLowerCase()}function st(i,t){return M(i)===M(t)}function K(i){return typeof(i==null?void 0:i.error)=="object"&&i!==null}function at(i){if(K(i))throw new Error(i.error.message||i.error.code);return i.data}function ct(i,t,e){return e===i?!0:t.includes(e)}var O=class{constructor(){this.schema={version:0,tables:[]};this.data={};this.tableNameResolver=t=>t;this.transactionDepth=0;this.snapshots=[]}setTableNameResolver(t){this.tableNameResolver=t}resolveTableName(t){return this.tableNameResolver(t)}async setUpWithSchema(t){this.schema={...t},this.data={},t.tables.forEach(e=>{this.data[e.name]=[]})}normalizeForComparison(t){if(t instanceof Date)return t.getTime();if(typeof t=="boolean")return t?1:0;if(typeof t=="string"||typeof t=="number"||t==null)return t;if(Array.isArray(t))return t.map(e=>this.normalizeForComparison(e));if(typeof t=="object"&&t!==null)try{return JSON.stringify(t)}catch{return String(t)}return t}evalValueExpr(t,e,r,n="t0"){if(r.type==="column"){let o=r.tableAlias||n,s=o===n?t:e[o]||{};return this.normalizeForComparison(s[r.field])}if(r.type==="literal")return this.normalizeForComparison(r.value);throw new Error(`Unsupported ValueExpression type: ${r.type}`)}buildFieldCondition(t,e){if("field"in t){let n={type:"column",tableAlias:t.alias||e,field:t.field},o={type:"literal",value:t.value};return{left:n,operator:t.operator||"=",right:o,...t.operator==="BETWEEN"?{}:{likeMode:t.likeMode}}}if("left"in t)return t;throw new Error("Invalid FieldCondition")}matchFilterExpression(t,e,r,n="t0"){if(r&&typeof r=="object"&&!Array.isArray(r)&&"and"in r)return r.and.every(o=>this.matchFilterExpression(t,e,o,n));if(r&&typeof r=="object"&&!Array.isArray(r)&&"or"in r)return r.or.some(o=>this.matchFilterExpression(t,e,o,n));if(r!==null&&typeof r=="object"&&!Array.isArray(r)){if("left"in r||"field"in r){let o=this.buildFieldCondition(r,n),s=this.evalValueExpr(t,e,o.left,n),a=this.evalValueExpr(t,e,o.right,n);if(o.operator==="IS NULL")return s==null;if(o.operator==="IS NOT NULL")return s!=null;if(o.operator==="IN"||o.operator==="NOT IN"){if(!Array.isArray(a))throw new Error("IN/NOT IN requires array on right side");let c=a.includes(s);return o.operator==="IN"?c:!c}switch(o.operator){case"=":return s===a;case"!=":return s!==a;case"<":return s<a;case"<=":return s<=a;case">":return s>a;case">=":return s>=a;case"LIKE":{if(typeof s!="string"||typeof a!="string")return!1;let c=a.replace(/%/g,".*").replace(/_/g,"."),l=o.likeMode;return new RegExp(`^${c}$`,l==="case-insensitive"?"i":"").test(s)}default:throw new Error(`Unsupported operator: ${o.operator}`)}}return Object.entries(r).every(([o,s])=>{let a=this.normalizeForComparison(t[o]),c=this.normalizeForComparison(s);return a===c})}throw new Error(`Invalid filter expression: ${JSON.stringify(r)}`)}simulateJoins(t,e,r){if(r.length===0)return e.map(o=>({record:o,joined:{}}));let n=[];for(let o of e){let s={},a=!0;for(let c of r){let l=this.resolveTableName(c.table),y=this.data[l]||[],u=null;if(c.conditions.length===1){let d=c.conditions[0];if(d.operator==="="&&d.left.type==="column"&&d.right.type==="column"){let g=d.left.tableAlias||"t0",A=d.right.tableAlias;if(g==="t0"&&A===c.alias){let m=d.left.field,h=d.right.field,p=o[m];u=y.find(b=>this.normalizeForComparison(b[h])===this.normalizeForComparison(p))}}}if(!u&&(c.type==="inner"||c.type===void 0)){a=!1;break}s[c.alias]=u||null}a&&n.push({record:o,joined:s})}return n}extractField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let o=r.tableAlias||n,s=o===n?t:e[o]||{};return this.normalizeForComparison(s[r.field])}extractAggregateField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let o=r.tableAlias||n,s=o===n?t:e[o]||{};return this.normalizeForComparison(s[r.field])}async getSchemaVersion(){return this.schema.version}async setSchemaVersion(t){this.schema.version=t}async addTable(t){let e=this.resolveTableName(t.name);this.data[e]||(this.data[e]=[]),this.schema.tables.find(r=>r.name===t.name)||this.schema.tables.push(t)}async addColumn(t,e){}async get(t,e){var o;let r=this.resolveTableName(t);if(typeof e=="string"){let a=(this.data[r]||[]).find(c=>c.id===e);return a||null}return(o=(await this.query(t,{...e,limit:1}))[0])!=null?o:null}async query(t,e={}){var y;let r=this.resolveTableName(t),n="t0",o=[...this.data[r]||[]],s=this.simulateJoins(r,o,e.joins||[]);if(e.filters&&(s=s.filter(({record:u,joined:d})=>this.matchFilterExpression(u,d,e.filters,n))),e.aggregates&&e.aggregates.length>0){let u={};for(let d of e.aggregates){let g=s;d.filter&&(g=g.filter(({record:p,joined:b})=>this.matchFilterExpression(p,b,d.filter,n)));let A=g.map(({record:p,joined:b})=>this.extractAggregateField(p,b,d.field,n)),m=A.map(p=>typeof p=="number"?p:Number(p)).filter(p=>Number.isFinite(p)),h=null;switch(d.function){case"COUNT":h=A.filter(p=>p!=null).length;break;case"SUM":h=m.reduce((p,b)=>p+b,0);break;case"AVG":h=m.length?m.reduce((p,b)=>p+b,0)/m.length:0;break;case"MIN":h=m.length?Math.min(...m):null;break;case"MAX":h=m.length?Math.max(...m):null;break;default:throw new Error(`Unsupported aggregate function: ${d.function}`)}u[d.as]=h}return[u]}let a=s.map(({record:u,joined:d})=>{var g;if(e.fields){if(((g=e.resultShape)!=null?g:"flat")==="nested"){let h={};for(let[p,b]of Object.entries(e.fields)){let w=p===n?u:d[p]||{},x={};for(let k of b)x[k]=w[k];h[p]=x}return h}let m={};for(let[h,p]of Object.entries(e.fields)){let b=h===n?u:d[h]||{};for(let w of p)m[`${h}_${w}`]=b[w]}return m}return u});e.sort&&e.sort.length>0&&a.sort((u,d)=>{for(let g of e.sort){let A=this.extractField(u,{},g.field,n),m=this.extractField(d,{},g.field,n);if(A<m)return g.direction==="asc"?-1:1;if(A>m)return g.direction==="asc"?1:-1}return 0});let c=(y=e.offset)!=null?y:0,l=e.limit!=null?c+e.limit:void 0;return a.slice(c,l)}async create(t,e){let r=this.resolveTableName(t);this.data[r]||(this.data[r]=[]);let n={...e};return this.data[r].push(n),n}async update(t,e,r){let n=this.resolveTableName(t),o=this.data[n]||[],s=o.findIndex(c=>c.id===e);if(s===-1)throw new Error(`Record not found: ${t} with id ${e}`);let a={...o[s],...r};return o[s]=a,a}async delete(t,e){let r=this.resolveTableName(t),n=this.data[r]||[],o=n.findIndex(s=>s.id===e);o>=0&&n.splice(o,1)}async bulkCreate(t,e){let r=this.resolveTableName(t);this.data[r]||(this.data[r]=[]);let n=[...this.data[r]];try{let o=[];for(let s of e){let a={...s};this.data[r].push(a),o.push(a)}return o}catch(o){throw this.data[r]=n,o}}async bulkUpdate(t,e){let r=this.resolveTableName(t),n=[...this.data[r]||[]];try{let o=[];for(let{id:s,updates:a}of e){let c=await this.update(t,s,a);o.push(c)}return o}catch(o){throw this.data[r]=n,o}}takeSnapshot(){let t={};for(let e in this.data)t[e]=[...this.data[e]];return t}async transaction(t){let e=this.transactionDepth===0;e&&this.snapshots.push(this.takeSnapshot()),this.transactionDepth++;try{let r=await t(this);return e&&this.snapshots.pop(),this.transactionDepth--,r}catch(r){if(e){let n=this.snapshots.pop();n&&(this.data=n)}throw this.transactionDepth--,r}}};var V=class{constructor(t){}logInfo(t,e){console.log(t,e)}logWarn(t,e){console.warn(t,e)}logError(t,e){console.error(t,e)}};function lt(i,t){if(!t||Object.keys(t).length===0)return i;let e=new URLSearchParams;for(let[n,o]of Object.entries(t))o!=null&&e.set(n,String(o));let r=e.toString();return r?i.includes("?")?`${i}&${r}`:`${i}?${r}`:i}var L=class{constructor(t){this.fetchImpl=t}async request(t){var s,a,c,l,y,u,d,g,A;let e=(s=this.fetchImpl)!=null?s:globalThis.fetch;if(typeof e!="function")throw new Error("DefaultHttpAdapter requires fetch implementation");let r=lt(t.url,t.query),n=typeof AbortController!="undefined"?new AbortController:null,o=n&&t.timeoutMs?setTimeout(()=>n.abort(),t.timeoutMs):null;try{let m=t.body!==void 0&&t.body!==null,h={...(a=t.headers)!=null?a:{}};m&&!h["content-type"]&&(h["content-type"]="application/json");let p=await e(r,{method:t.method,headers:h,body:m?JSON.stringify(t.body):void 0,signal:n==null?void 0:n.signal}),b={};(l=(c=p.headers)==null?void 0:c.forEach)==null||l.call(c,(k,C)=>{b[C.toLowerCase()]=k});let x=((y=b["content-type"])!=null?y:"").includes("application/json")?await((d=(u=p.json)==null?void 0:u.call(p))!=null?d:Promise.resolve(void 0)):await((A=(g=p.text)==null?void 0:g.call(p))!=null?A:Promise.resolve(""));return{status:p.status,headers:b,data:x}}finally{o&&clearTimeout(o)}}};var T=class{constructor(t){}shouldRetry(t){return!1}nextDelayMs(t){return 0}};var pt=[408,425,429,500,502,503,504],$=class{constructor(t={}){var e,r,n,o;this.maxAttempts=Math.max(1,(e=t.maxAttempts)!=null?e:3),this.baseDelayMs=Math.max(0,(r=t.baseDelayMs)!=null?r:250),this.maxDelayMs=Math.max(this.baseDelayMs,(n=t.maxDelayMs)!=null?n:3e3),this.retryableStatusCodes=new Set((o=t.retryableStatusCodes)!=null?o:pt)}shouldRetry(t){var r,n;if(t.attempt>=this.maxAttempts)return!1;if(t.error)return!0;let e=(n=(r=t.response)==null?void 0:r.status)!=null?n:0;return this.retryableStatusCodes.has(e)}nextDelayMs(t){let e=Math.max(0,t.attempt-1),r=this.baseDelayMs*Math.pow(2,e);return Math.min(this.maxDelayMs,r)}};var _=class{constructor(){this.connected=!1;this.listeners=new Map}async connect(t){this.connectionOptions=t,this.connected=!0}async disconnect(){this.connected=!1}subscribe(t,e){this.listeners.has(t)||this.listeners.set(t,new Set);let r=this.listeners.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&this.listeners.delete(t)}}async publish(t,e){if(!this.connected)throw new Error(`InMemorySocketAdapter is not connected (event=${t})`);let r=this.listeners.get(t);if(!(!r||r.size===0))for(let n of r)n(e)}isConnected(){return this.connected}getConnectionOptions(){return this.connectionOptions}};var N=class{constructor(t){}configure(t){}createChannel(t){}localNotification(t){}};var j=class{constructor(t){}encrypt(t,e){return String(t)}decrypt(t,e){return String(t)}};var R=class{constructor(t){}compute(t){return""}verify(t,e){return String(e||"").trim()===""}};var E=class{constructor(t){}publish(t){}};var U=class{constructor(t){this.records=[]}publish(t){this.records.push(t)}getRecords(){return[...this.records]}clear(){this.records.length=0}};var z=class{constructor(t){}getDocumentPath(t){return t}async writeFile(t,e){throw new Error("exportAdapter.writeFile is not implemented for this platform")}async share(t){throw new Error("exportAdapter.share is not implemented for this platform")}};var q=class{constructor(t){this.map=new Map}getItem(t){var e;return(e=this.map.get(t))!=null?e:null}setItem(t,e){this.map.set(t,e)}removeItem(t){this.map.delete(t)}};var B=[];async function dt(i,t){if(typeof i.getSchemaVersion!="function"||typeof i.setSchemaVersion!="function"){let e="Adapter does not support schema versioning (getSchemaVersion/setSchemaVersion required)";throw t.logError(new Error(e),{message:e}),new Error(e)}t.logInfo("Starting database migration process");try{let e=[...B].sort((o,s)=>o.toVersion-s.toVersion),r=e.length>0?e[e.length-1].toVersion:0,n=await i.getSchemaVersion();if((n==null||n<0)&&(n=0),n>=r){t.logInfo(`Database is already up-to-date at v${n}`);return}t.logInfo(`Migrating database from v${n} to v${r}`);for(let o of e)o.toVersion>n&&(t.logInfo(`Applying migration: v${o.toVersion}`),await o.up(i),await i.setSchemaVersion(o.toVersion),n=o.toVersion);t.logInfo("Database migration completed successfully")}catch(e){throw t.logError(e,{message:"Database migration failed"}),e}}function v(i,t){if(!i)throw new Error(t)}function f(i,t){return`${i}-${t}`}function ut(i){let t=[{name:"id",type:"string"},{name:"name",type:"string"},{name:"age",type:"number"},{name:"tenantId",type:"string"},{name:"isActive",type:"boolean"}];return{name:`${i}_users`,columns:t,skipMetadataColumns:!0}}function mt(i){let t=[{name:"id",type:"string"},{name:"userId",type:"string",isIndexed:!0},{name:"nickname",type:"string"}];return{name:`${i}_profiles`,columns:t,skipMetadataColumns:!0}}async function ht(i,t={}){var w,x,k,C,J,W,Q;let e=((w=t.prefix)!=null?w:`dbadapter_${Date.now()}`).replace(/[^a-zA-Z0-9_]/g,"_"),r=`${e}_users`,n=`${e}_profiles`;await i.setSchemaVersion(7);let o=await i.getSchemaVersion();v(o===7,`Expected schema version 7, got ${o}`),await i.addTable(ut(e)),await i.addTable(mt(e)),await i.addColumn(r,{name:"email",type:"string",isOptional:!0}),await i.create(r,{id:f(e,"u1"),name:"Alice",age:31,tenantId:"tenant-1",isActive:!0,email:"alice@example.com"}),await i.create(r,{id:f(e,"u2"),name:"Bob",age:24,tenantId:"tenant-1",isActive:!1,email:"bob@example.com"}),await i.bulkCreate(r,[{id:f(e,"u3"),name:"Carla",age:29,tenantId:"tenant-2",isActive:!0,email:"carla@example.com"},{id:f(e,"u4"),name:"Dian",age:22,tenantId:"tenant-2",isActive:!0}]),await i.bulkCreate(n,[{id:f(e,"p1"),userId:f(e,"u1"),nickname:"alice-nick"},{id:f(e,"p2"),userId:f(e,"u3"),nickname:"carla-nick"}]);let s=await i.get(r,f(e,"u1"));v((s==null?void 0:s.name)==="Alice","Expected get(table, id) to return Alice");let a=await i.query(r,{filters:{tenantId:"tenant-1"},sort:[{field:"age",direction:"desc"}]});v(a.length===2,`Expected 2 tenant-1 users, got ${a.length}`),v(a[0].age>=a[1].age,"Expected sorted by age desc");let c={and:[{field:"tenantId",value:"tenant-2"},{field:"isActive",value:!0}]},l=await i.query(r,{filters:c,sort:[{field:"name",direction:"asc"}]});v(l.length===2,`Expected 2 active tenant-2 users, got ${l.length}`);let y={filters:{and:[{field:"id",value:f(e,"u2")},{field:"tenantId",value:"tenant-1"}]}},u=await i.get(r,y);v((u==null?void 0:u.name)==="Bob","Expected get(table, options) to resolve Bob");let d=await i.update(r,f(e,"u1"),{age:32});v(d.age===32,`Expected age updated to 32, got ${d.age}`);let g=await i.bulkUpdate(r,[{id:f(e,"u3"),updates:{age:30}},{id:f(e,"u4"),updates:{age:23}}]);v(g.length===2,`Expected 2 bulk-updated rows, got ${g.length}`);let A=await i.query(r,{sort:[{field:"age",direction:"asc"}],limit:2,offset:1});v(A.length===2,`Expected 2 paged rows, got ${A.length}`);let m=await i.query(r,{fields:{t0:["id","name"],p:["nickname"]},joins:[{table:n,alias:"p",type:"left",conditions:[{left:{type:"column",tableAlias:"t0",field:"id"},operator:"=",right:{type:"column",tableAlias:"p",field:"userId"}}]}],filters:{field:"id",value:f(e,"u1")},resultShape:"flat"});v(m.length===1,`Expected one projected flat row, got ${m.length}`),v(((x=m[0])==null?void 0:x.t0_id)===f(e,"u1"),"Expected flat projected key t0_id"),v(((k=m[0])==null?void 0:k.p_nickname)==="alice-nick","Expected flat projected key p_nickname");let h=await i.query(r,{fields:{t0:["id","name"],p:["nickname"]},joins:[{table:n,alias:"p",type:"left",conditions:[{left:{type:"column",tableAlias:"t0",field:"id"},operator:"=",right:{type:"column",tableAlias:"p",field:"userId"}}]}],filters:{field:"id",value:f(e,"u1")},resultShape:"nested"});v(h.length===1,`Expected one projected nested row, got ${h.length}`),v(((J=(C=h[0])==null?void 0:C.t0)==null?void 0:J.id)===f(e,"u1"),"Expected nested row t0.id"),v(((Q=(W=h[0])==null?void 0:W.p)==null?void 0:Q.nickname)==="alice-nick","Expected nested row p.nickname");try{throw await i.transaction(async S=>{throw await S.create(r,{id:f(e,"tx_rollback"),name:"TxRollback",age:40,tenantId:"tenant-1",isActive:!0}),new Error("rollback-intent")}),new Error("Expected transaction rollback to throw")}catch(S){let G=S instanceof Error?S.message:String(S);v(G.includes("rollback-intent"),`Expected rollback-intent error, got ${G}`)}let p=await i.get(r,f(e,"tx_rollback"));v(p===null,"Expected rolled back record to not exist"),await i.delete(r,f(e,"u2"));let b=await i.get(r,f(e,"u2"));v(b===null,"Expected deleted record to be null")}var P=class{constructor(t,e){this.extensions=new Map;var r,n,o,s,a,c,l,y,u,d,g,A,m;this.platformAdapter=(r=e.platformAdapter)==null?void 0:r.call(e,t),this.dbAdapter=(n=e.dbAdapter)==null?void 0:n.call(e,t),this.loggerAdapter=(o=e.loggerAdapter)==null?void 0:o.call(e,t),this.httpAdapter=(s=e.httpAdapter)==null?void 0:s.call(e,t),this.httpRetryPolicy=(c=(a=e.httpRetryPolicy)==null?void 0:a.call(e,t))!=null?c:new T(t),this.socketAdapter=(l=e.socketAdapter)==null?void 0:l.call(e,t),this.encryptionAdapter=(y=e.encryptionAdapter)==null?void 0:y.call(e,t),this.checksumAdapter=(d=(u=e.checksumAdapter)==null?void 0:u.call(e,t))!=null?d:new R(t),this.activitySink=(A=(g=e.activitySink)==null?void 0:g.call(e,t))!=null?A:new E(t);for(let[h,p]of Object.entries((m=e.extensions)!=null?m:{}))this.extensions.set(h,p(t))}getExtension(t){return this.extensions.get(t)}clear(){this.extensions.clear()}};function X(i){return!!i&&typeof i.shutdown=="function"}var D=class{constructor(){this.correlationCounter=0;this.started=!1;this.pluginsLoaded=!1;this.pendingPlugins=[];this.hooks={}}static builder(){return new I}setHooks(t){this.hooks={...this.hooks,...t}}use(t,e,r=[]){if(!t.trim())throw new Error("plugin name is required");return this.pendingPlugins.some(n=>n.name===t)?this:(this.pendingPlugins.push({name:t,init:e,deps:r}),this)}async init(t={runMigrations:!0,useSeedData:!1}){if(!this.registry)throw new Error("CoreRuntime registry is not initialized. Call builder().build() first.");if(t.runMigrations!==!1&&this.hooks.runMigrations&&await this.hooks.runMigrations(this),this.hooks.onInit&&await this.hooks.onInit(this),!this.domainServices&&this.hooks.createDomainServices&&(this.domainServices=await this.hooks.createDomainServices(this)),!this.integrationServices&&this.hooks.createIntegrationServices&&(this.integrationServices=await this.hooks.createIntegrationServices(this)),!this.pluginsLoaded){let n=this.resolvePluginLevels();for(let o of n)await Promise.all(o.map(s=>s.init(this)));this.pluginsLoaded=!0}t.useSeedData===!0&&this.hooks.runSeed&&await this.hooks.runSeed(this)}async start(t={}){if(this.started)throw new Error("CoreRuntime already started");try{await this.init(t),this.started=!0}catch(e){throw this.started=!1,e}}async stop(){var t;this.started&&(this.hooks.onStop&&await this.hooks.onStop(this),X(this.integrationServices)&&await this.integrationServices.shutdown(),X(this.domainServices)&&await this.domainServices.shutdown(),(t=this.registry)==null||t.clear(),this.started=!1)}async reset(){await this.stop(),this.domainServices=void 0,this.integrationServices=void 0,this.pendingPlugins=[],this.pluginsLoaded=!1,this.hooks={}}async restart(){let t=[...this.pendingPlugins],e={...this.hooks};await this.reset(),this.pendingPlugins=t,this.hooks=e,await this.start()}isStarted(){return this.started}createCorrelationId(t="cid"){return this.correlationCounter+=1,`${t}-${Date.now()}-${this.correlationCounter}`}logInfo(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logInfo(t,e)}logWarn(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logWarn(t,e)}logError(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logError(t,e)}async emitActivity(t){var e;(e=this.registry)!=null&&e.activitySink&&await this.registry.activitySink.publish(t)}resolvePluginLevels(){var s,a,c;if(this.pendingPlugins.length===0)return[];let t=new Map,e=new Map,r=new Map;for(let l of this.pendingPlugins){if(t.has(l.name))throw new Error(`Duplicate plugin name: ${l.name}`);t.set(l.name,[]),e.set(l.name,0),r.set(l.name,l)}for(let l of this.pendingPlugins)for(let y of l.deps){if(!t.has(y))throw new Error(`Plugin "${l.name}" depends on unknown plugin "${y}"`);t.get(y).push(l.name),e.set(l.name,((s=e.get(l.name))!=null?s:0)+1)}let n=[],o=Array.from(e.entries()).filter(([,l])=>l===0).map(([l])=>l);for(;o.length>0;){let l=o.map(u=>r.get(u));n.push(l);let y=[];for(let u of o)for(let d of(a=t.get(u))!=null?a:[]){let g=((c=e.get(d))!=null?c:0)-1;e.set(d,g),g===0&&y.push(d)}o=y}if(n.flat().length!==this.pendingPlugins.length)throw new Error("Circular dependency detected among plugins");return n}},I=class{constructor(){this.runtime=new D;this.adapterOptions={};this.hooks={}}withPlatformAdapter(t){return this.adapterOptions.platformAdapter=t,this}withDbAdapter(t){return this.adapterOptions.dbAdapter=t,this}withHttpAdapter(t){return this.adapterOptions.httpAdapter=t,this}withHttpRetryPolicy(t){return this.adapterOptions.httpRetryPolicy=t,this}withSocketAdapter(t){return this.adapterOptions.socketAdapter=t,this}withEncryptionAdapter(t){return this.adapterOptions.encryptionAdapter=t,this}withChecksumAdapter(t){return this.adapterOptions.checksumAdapter=t,this}withActivitySink(t){return this.adapterOptions.activitySink=t,this}withLoggerAdapter(t){return this.adapterOptions.loggerAdapter=t,this}withExtension(t,e){var r;return this.adapterOptions.extensions=(r=this.adapterOptions.extensions)!=null?r:{},this.adapterOptions.extensions[t]=e,this}withHooks(t){return this.hooks={...this.hooks,...t},this}build(){return this.runtime.setHooks(this.hooks),this.runtime.registry=new P(this.runtime,this.adapterOptions),this.runtime}};function gt(i){let t=i,e=new Set,r=(n,o)=>{for(let s of e)s(n,o)};return{getState(){return t},setState(n){let o=t;return t=typeof n=="function"?n(t):{...t,...n},r(t,o),t},reset(n){let o=t;return t=n!=null?n:i,r(t,o),t},subscribe(n){return e.add(n),()=>{e.delete(n)}}}}function ft(i){return{getState:i.getState,subscribe:i.subscribe}}function yt(){return new Date().toISOString()}function bt(i){let t=0;return()=>(t+=1,`${i}-${Date.now()}-${t}`)}function vt(i){return JSON.parse(JSON.stringify(i))}function At(i){if(i.length!==0)return i.length===1?i[0]:{and:i}}
|
package/dist/index.d.ts
CHANGED
package/dist/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var C=class{constructor(t){}getEnvVar(t){let e=globalThis.process;if(typeof e!="undefined"&&e.env)return e.env[t]}isOnline(){return typeof globalThis.navigator!="undefined"&&typeof globalThis.navigator.onLine!="undefined"?!!globalThis.navigator.onLine:!0}async hashPin(t){return`sha256:${t}`}async verifyPin(t,e){return await this.hashPin(t)===e}};async function q(o){o<=0||await new Promise(t=>setTimeout(t,o))}async function K(o,t,e={}){var s;let r=e.policy,n=(s=e.sleep)!=null?s:q,i=1;for(;;)try{let a=await o.request(t);if(!r)return a;let p={request:t,attempt:i,response:a};if(!r.shouldRetry(p))return a;let c=Math.max(0,r.nextDelayMs(p));await n(c),i+=1}catch(a){if(!r)throw a;let p={request:t,attempt:i,error:a};if(!r.shouldRetry(p))throw a;let c=Math.max(0,r.nextDelayMs(p));await n(c),i+=1}}function P(o){return String(o||"").trim().toLowerCase()}function Y(o,t){return P(o)===P(t)}function tt(o){return typeof(o==null?void 0:o.error)=="object"&&o!==null}function rt(o,t,e){return e===o?!0:t.includes(e)}var E=class{constructor(){this.schema={version:0,tables:[]};this.data={};this.transactionDepth=0;this.snapshots=[]}async setUpWithSchema(t){this.schema={...t},this.data={},t.tables.forEach(e=>{this.data[e.name]=[]})}normalizeForComparison(t){if(t instanceof Date)return t.getTime();if(typeof t=="boolean")return t?1:0;if(typeof t=="string"||typeof t=="number"||t==null)return t;if(Array.isArray(t))return t.map(e=>this.normalizeForComparison(e));if(typeof t=="object"&&t!==null)try{return JSON.stringify(t)}catch{return String(t)}return t}evalValueExpr(t,e,r,n="t0"){if(r.type==="column"){let i=r.tableAlias||n,s=i===n?t:e[i]||{};return this.normalizeForComparison(s[r.field])}if(r.type==="literal")return this.normalizeForComparison(r.value);throw new Error(`Unsupported ValueExpression type: ${r.type}`)}buildFieldCondition(t,e){if("field"in t){let n={type:"column",tableAlias:t.alias||e,field:t.field},i={type:"literal",value:t.value};return{left:n,operator:t.operator||"=",right:i,...t.operator==="BETWEEN"?{}:{likeMode:t.likeMode}}}if("left"in t)return t;throw new Error("Invalid FieldCondition")}matchFilterExpression(t,e,r,n="t0"){if(r&&typeof r=="object"&&!Array.isArray(r)&&"and"in r)return r.and.every(i=>this.matchFilterExpression(t,e,i,n));if(r&&typeof r=="object"&&!Array.isArray(r)&&"or"in r)return r.or.some(i=>this.matchFilterExpression(t,e,i,n));if(r!==null&&typeof r=="object"&&!Array.isArray(r)){if("left"in r||"field"in r){let i=this.buildFieldCondition(r,n),s=this.evalValueExpr(t,e,i.left,n),a=this.evalValueExpr(t,e,i.right,n);if(i.operator==="IS NULL")return s==null;if(i.operator==="IS NOT NULL")return s!=null;if(i.operator==="IN"||i.operator==="NOT IN"){if(!Array.isArray(a))throw new Error("IN/NOT IN requires array on right side");let p=a.includes(s);return i.operator==="IN"?p:!p}switch(i.operator){case"=":return s===a;case"!=":return s!==a;case"<":return s<a;case"<=":return s<=a;case">":return s>a;case">=":return s>=a;case"LIKE":{if(typeof s!="string"||typeof a!="string")return!1;let p=a.replace(/%/g,".*").replace(/_/g,"."),c=i.likeMode;return new RegExp(`^${p}$`,c==="case-insensitive"?"i":"").test(s)}default:throw new Error(`Unsupported operator: ${i.operator}`)}}return Object.entries(r).every(([i,s])=>{let a=this.normalizeForComparison(t[i]),p=this.normalizeForComparison(s);return a===p})}throw new Error(`Invalid filter expression: ${JSON.stringify(r)}`)}simulateJoins(t,e,r){if(r.length===0)return e.map(i=>({record:i,joined:{}}));let n=[];for(let i of e){let s={},a=!0;for(let p of r){let c=p.table,d=this.data[c]||[],m=null;if(p.conditions.length===1){let l=p.conditions[0];if(l.operator==="="&&l.left.type==="column"&&l.right.type==="column"){let g=l.left.tableAlias||"t0",f=l.right.tableAlias;if(g==="t0"&&f===p.alias){let y=l.left.field,u=l.right.field,h=i[y];m=d.find(A=>this.normalizeForComparison(A[u])===this.normalizeForComparison(h))}}}if(!m&&(p.type==="inner"||p.type===void 0)){a=!1;break}s[p.alias]=m||null}a&&n.push({record:i,joined:s})}return n}extractField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let i=r.tableAlias||n,s=i===n?t:e[i]||{};return this.normalizeForComparison(s[r.field])}extractAggregateField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let i=r.tableAlias||n,s=i===n?t:e[i]||{};return this.normalizeForComparison(s[r.field])}async getSchemaVersion(){return this.schema.version}async setSchemaVersion(t){this.schema.version=t}async addTable(t){this.data[t.name]||(this.data[t.name]=[]),this.schema.tables.find(e=>e.name===t.name)||this.schema.tables.push(t)}async addColumn(t,e){}async get(t,e){var n;if(typeof e=="string"){let s=(this.data[t]||[]).find(a=>a.id===e);return s||null}return(n=(await this.query(t,{...e,limit:1}))[0])!=null?n:null}async query(t,e={}){var c;let n=[...this.data[t]||[]],i=this.simulateJoins(t,n,e.joins||[]);if(e.filters&&(i=i.filter(({record:d,joined:m})=>this.matchFilterExpression(d,m,e.filters,"t0"))),e.aggregates&&e.aggregates.length>0){let d={};for(let m of e.aggregates){let l=i;m.filter&&(l=l.filter(({record:u,joined:h})=>this.matchFilterExpression(u,h,m.filter,"t0")));let g=l.map(({record:u,joined:h})=>this.extractAggregateField(u,h,m.field,"t0")),f=g.map(u=>typeof u=="number"?u:Number(u)).filter(u=>Number.isFinite(u)),y=null;switch(m.function){case"COUNT":y=g.filter(u=>u!=null).length;break;case"SUM":y=f.reduce((u,h)=>u+h,0);break;case"AVG":y=f.length?f.reduce((u,h)=>u+h,0)/f.length:0;break;case"MIN":y=f.length?Math.min(...f):null;break;case"MAX":y=f.length?Math.max(...f):null;break;default:throw new Error(`Unsupported aggregate function: ${m.function}`)}d[m.as]=y}return[d]}let s=i.map(({record:d,joined:m})=>{if(e.fields){let l={};for(let[g,f]of Object.entries(e.fields)){let y=g==="t0"?d:m[g]||{};for(let u of f)l[`${g}_${u}`]=y[u]}return l}return d});e.sort&&e.sort.length>0&&s.sort((d,m)=>{for(let l of e.sort){let g=this.extractField(d,{},l.field,"t0"),f=this.extractField(m,{},l.field,"t0");if(g<f)return l.direction==="asc"?-1:1;if(g>f)return l.direction==="asc"?1:-1}return 0});let a=(c=e.offset)!=null?c:0,p=e.limit!=null?a+e.limit:void 0;return s.slice(a,p)}async create(t,e){this.data[t]||(this.data[t]=[]);let r={...e};return this.data[t].push(r),r}async update(t,e,r){let n=this.data[t]||[],i=n.findIndex(a=>a.id===e);if(i===-1)throw new Error(`Record not found: ${t} with id ${e}`);let s={...n[i],...r};return n[i]=s,s}async delete(t,e){let r=this.data[t]||[],n=r.findIndex(i=>i.id===e);n>=0&&r.splice(n,1)}async bulkCreate(t,e){this.data[t]||(this.data[t]=[]);let r=[...this.data[t]];try{let n=[];for(let i of e){let s={...i};this.data[t].push(s),n.push(s)}return n}catch(n){throw this.data[t]=r,n}}async bulkUpdate(t,e){let r=[...this.data[t]||[]];try{let n=[];for(let{id:i,updates:s}of e){let a=await this.update(t,i,s);n.push(a)}return n}catch(n){throw this.data[t]=r,n}}takeSnapshot(){let t={};for(let e in this.data)t[e]=[...this.data[e]];return t}async transaction(t){let e=this.transactionDepth===0;e&&this.snapshots.push(this.takeSnapshot()),this.transactionDepth++;try{let r=await t(this);return e&&this.snapshots.pop(),this.transactionDepth--,r}catch(r){if(e){let n=this.snapshots.pop();n&&(this.data=n)}throw this.transactionDepth--,r}}};var D=class{constructor(t){}logInfo(t,e){console.log(t,e)}logWarn(t,e){console.warn(t,e)}logError(t,e){console.error(t,e)}};function B(o,t){if(!t||Object.keys(t).length===0)return o;let e=new URLSearchParams;for(let[n,i]of Object.entries(t))i!=null&&e.set(n,String(i));let r=e.toString();return r?o.includes("?")?`${o}&${r}`:`${o}?${r}`:o}var H=class{constructor(t){this.fetchImpl=t}async request(t){var s,a,p,c,d,m,l,g,f;let e=(s=this.fetchImpl)!=null?s:globalThis.fetch;if(typeof e!="function")throw new Error("DefaultHttpAdapter requires fetch implementation");let r=B(t.url,t.query),n=typeof AbortController!="undefined"?new AbortController:null,i=n&&t.timeoutMs?setTimeout(()=>n.abort(),t.timeoutMs):null;try{let y=t.body!==void 0&&t.body!==null,u={...(a=t.headers)!=null?a:{}};y&&!u["content-type"]&&(u["content-type"]="application/json");let h=await e(r,{method:t.method,headers:u,body:y?JSON.stringify(t.body):void 0,signal:n==null?void 0:n.signal}),A={};(c=(p=h.headers)==null?void 0:p.forEach)==null||c.call(p,(j,z)=>{A[z.toLowerCase()]=j});let N=((d=A["content-type"])!=null?d:"").includes("application/json")?await((l=(m=h.json)==null?void 0:m.call(h))!=null?l:Promise.resolve(void 0)):await((f=(g=h.text)==null?void 0:g.call(h))!=null?f:Promise.resolve(""));return{status:h.status,headers:A,data:N}}finally{i&&clearTimeout(i)}}};var w=class{constructor(t){}shouldRetry(t){return!1}nextDelayMs(t){return 0}};var W=[408,425,429,500,502,503,504],I=class{constructor(t={}){var e,r,n,i;this.maxAttempts=Math.max(1,(e=t.maxAttempts)!=null?e:3),this.baseDelayMs=Math.max(0,(r=t.baseDelayMs)!=null?r:250),this.maxDelayMs=Math.max(this.baseDelayMs,(n=t.maxDelayMs)!=null?n:3e3),this.retryableStatusCodes=new Set((i=t.retryableStatusCodes)!=null?i:W)}shouldRetry(t){var r,n;if(t.attempt>=this.maxAttempts)return!1;if(t.error)return!0;let e=(n=(r=t.response)==null?void 0:r.status)!=null?n:0;return this.retryableStatusCodes.has(e)}nextDelayMs(t){let e=Math.max(0,t.attempt-1),r=this.baseDelayMs*Math.pow(2,e);return Math.min(this.maxDelayMs,r)}};var F=class{constructor(){this.connected=!1;this.listeners=new Map}async connect(t){this.connectionOptions=t,this.connected=!0}async disconnect(){this.connected=!1}subscribe(t,e){this.listeners.has(t)||this.listeners.set(t,new Set);let r=this.listeners.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&this.listeners.delete(t)}}async publish(t,e){if(!this.connected)throw new Error(`InMemorySocketAdapter is not connected (event=${t})`);let r=this.listeners.get(t);if(!(!r||r.size===0))for(let n of r)n(e)}isConnected(){return this.connected}getConnectionOptions(){return this.connectionOptions}};var M=class{constructor(t){}configure(t){}createChannel(t){}localNotification(t){}};var O=class{constructor(t){}encrypt(t,e){return String(t)}decrypt(t,e){return String(t)}};var S=class{constructor(t){}compute(t){return""}verify(t,e){return String(e||"").trim()===""}};var x=class{constructor(t){}publish(t){}};var V=class{constructor(t){this.records=[]}publish(t){this.records.push(t)}getRecords(){return[...this.records]}clear(){this.records.length=0}};var L=class{constructor(t){}getDocumentPath(t){return t}async writeFile(t,e){throw new Error("exportAdapter.writeFile is not implemented for this platform")}async share(t){throw new Error("exportAdapter.share is not implemented for this platform")}};var _=class{constructor(t){this.map=new Map}getItem(t){var e;return(e=this.map.get(t))!=null?e:null}setItem(t,e){this.map.set(t,e)}removeItem(t){this.map.delete(t)}};var $=[];async function vt(o,t){if(typeof o.getSchemaVersion!="function"||typeof o.setSchemaVersion!="function"){let e="Adapter does not support schema versioning (getSchemaVersion/setSchemaVersion required)";throw t.logError(new Error(e),{message:e}),new Error(e)}t.logInfo("Starting database migration process");try{let e=[...$].sort((i,s)=>i.toVersion-s.toVersion),r=e.length>0?e[e.length-1].toVersion:0,n=await o.getSchemaVersion();if((n==null||n<0)&&(n=0),n>=r){t.logInfo(`Database is already up-to-date at v${n}`);return}t.logInfo(`Migrating database from v${n} to v${r}`);for(let i of e)i.toVersion>n&&(t.logInfo(`Applying migration: v${i.toVersion}`),await i.up(o),await o.setSchemaVersion(i.toVersion),n=i.toVersion);t.logInfo("Database migration completed successfully")}catch(e){throw t.logError(e,{message:"Database migration failed"}),e}}function v(o,t){if(!o)throw new Error(t)}function b(o,t){return`${o}-${t}`}function J(o){let t=[{name:"id",type:"string"},{name:"name",type:"string"},{name:"age",type:"number"},{name:"tenantId",type:"string"},{name:"isActive",type:"boolean"}];return{name:`${o}_users`,columns:t,skipMetadataColumns:!0}}async function wt(o,t={}){var u;let e=((u=t.prefix)!=null?u:`dbadapter_${Date.now()}`).replace(/[^a-zA-Z0-9_]/g,"_"),r=`${e}_users`;await o.setSchemaVersion(7);let n=await o.getSchemaVersion();v(n===7,`Expected schema version 7, got ${n}`),await o.addTable(J(e)),await o.addColumn(r,{name:"email",type:"string",isOptional:!0}),await o.create(r,{id:b(e,"u1"),name:"Alice",age:31,tenantId:"tenant-1",isActive:!0,email:"alice@example.com"}),await o.create(r,{id:b(e,"u2"),name:"Bob",age:24,tenantId:"tenant-1",isActive:!1,email:"bob@example.com"}),await o.bulkCreate(r,[{id:b(e,"u3"),name:"Carla",age:29,tenantId:"tenant-2",isActive:!0,email:"carla@example.com"},{id:b(e,"u4"),name:"Dian",age:22,tenantId:"tenant-2",isActive:!0}]);let i=await o.get(r,b(e,"u1"));v((i==null?void 0:i.name)==="Alice","Expected get(table, id) to return Alice");let s=await o.query(r,{filters:{tenantId:"tenant-1"},sort:[{field:"age",direction:"desc"}]});v(s.length===2,`Expected 2 tenant-1 users, got ${s.length}`),v(s[0].age>=s[1].age,"Expected sorted by age desc");let a={and:[{field:"tenantId",value:"tenant-2"},{field:"isActive",value:!0}]},p=await o.query(r,{filters:a,sort:[{field:"name",direction:"asc"}]});v(p.length===2,`Expected 2 active tenant-2 users, got ${p.length}`);let c={filters:{and:[{field:"id",value:b(e,"u2")},{field:"tenantId",value:"tenant-1"}]}},d=await o.get(r,c);v((d==null?void 0:d.name)==="Bob","Expected get(table, options) to resolve Bob");let m=await o.update(r,b(e,"u1"),{age:32});v(m.age===32,`Expected age updated to 32, got ${m.age}`);let l=await o.bulkUpdate(r,[{id:b(e,"u3"),updates:{age:30}},{id:b(e,"u4"),updates:{age:23}}]);v(l.length===2,`Expected 2 bulk-updated rows, got ${l.length}`);let g=await o.query(r,{sort:[{field:"age",direction:"asc"}],limit:2,offset:1});v(g.length===2,`Expected 2 paged rows, got ${g.length}`);try{throw await o.transaction(async h=>{throw await h.create(r,{id:b(e,"tx_rollback"),name:"TxRollback",age:40,tenantId:"tenant-1",isActive:!0}),new Error("rollback-intent")}),new Error("Expected transaction rollback to throw")}catch(h){let A=h instanceof Error?h.message:String(h);v(A.includes("rollback-intent"),`Expected rollback-intent error, got ${A}`)}let f=await o.get(r,b(e,"tx_rollback"));v(f===null,"Expected rolled back record to not exist"),await o.delete(r,b(e,"u2"));let y=await o.get(r,b(e,"u2"));v(y===null,"Expected deleted record to be null")}var k=class{constructor(t,e){this.extensions=new Map;var r,n,i,s,a,p,c,d,m,l,g,f,y;this.platformAdapter=(r=e.platformAdapter)==null?void 0:r.call(e,t),this.dbAdapter=(n=e.dbAdapter)==null?void 0:n.call(e,t),this.loggerAdapter=(i=e.loggerAdapter)==null?void 0:i.call(e,t),this.httpAdapter=(s=e.httpAdapter)==null?void 0:s.call(e,t),this.httpRetryPolicy=(p=(a=e.httpRetryPolicy)==null?void 0:a.call(e,t))!=null?p:new w(t),this.socketAdapter=(c=e.socketAdapter)==null?void 0:c.call(e,t),this.encryptionAdapter=(d=e.encryptionAdapter)==null?void 0:d.call(e,t),this.checksumAdapter=(l=(m=e.checksumAdapter)==null?void 0:m.call(e,t))!=null?l:new S(t),this.activitySink=(f=(g=e.activitySink)==null?void 0:g.call(e,t))!=null?f:new x(t);for(let[u,h]of Object.entries((y=e.extensions)!=null?y:{}))this.extensions.set(u,h(t))}getExtension(t){return this.extensions.get(t)}clear(){this.extensions.clear()}};function U(o){return!!o&&typeof o.shutdown=="function"}var T=class{constructor(){this.correlationCounter=0;this.started=!1;this.pluginsLoaded=!1;this.pendingPlugins=[];this.hooks={}}static builder(){return new R}setHooks(t){this.hooks={...this.hooks,...t}}use(t,e,r=[]){if(!t.trim())throw new Error("plugin name is required");return this.pendingPlugins.some(n=>n.name===t)?this:(this.pendingPlugins.push({name:t,init:e,deps:r}),this)}async init(t={runMigrations:!0,useSeedData:!1}){if(!this.registry)throw new Error("CoreRuntime registry is not initialized. Call builder().build() first.");if(t.runMigrations!==!1&&this.hooks.runMigrations&&await this.hooks.runMigrations(this),this.hooks.onInit&&await this.hooks.onInit(this),!this.domainServices&&this.hooks.createDomainServices&&(this.domainServices=await this.hooks.createDomainServices(this)),!this.integrationServices&&this.hooks.createIntegrationServices&&(this.integrationServices=await this.hooks.createIntegrationServices(this)),!this.pluginsLoaded){let n=this.resolvePluginLevels();for(let i of n)await Promise.all(i.map(s=>s.init(this)));this.pluginsLoaded=!0}t.useSeedData===!0&&this.hooks.runSeed&&await this.hooks.runSeed(this)}async start(t={}){if(this.started)throw new Error("CoreRuntime already started");try{await this.init(t),this.started=!0}catch(e){throw this.started=!1,e}}async stop(){var t;this.started&&(this.hooks.onStop&&await this.hooks.onStop(this),U(this.integrationServices)&&await this.integrationServices.shutdown(),U(this.domainServices)&&await this.domainServices.shutdown(),(t=this.registry)==null||t.clear(),this.started=!1)}async reset(){await this.stop(),this.domainServices=void 0,this.integrationServices=void 0,this.pendingPlugins=[],this.pluginsLoaded=!1,this.hooks={}}async restart(){let t=[...this.pendingPlugins],e={...this.hooks};await this.reset(),this.pendingPlugins=t,this.hooks=e,await this.start()}isStarted(){return this.started}createCorrelationId(t="cid"){return this.correlationCounter+=1,`${t}-${Date.now()}-${this.correlationCounter}`}logInfo(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logInfo(t,e)}logWarn(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logWarn(t,e)}logError(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logError(t,e)}async emitActivity(t){var e;(e=this.registry)!=null&&e.activitySink&&await this.registry.activitySink.publish(t)}resolvePluginLevels(){var s,a,p;if(this.pendingPlugins.length===0)return[];let t=new Map,e=new Map,r=new Map;for(let c of this.pendingPlugins){if(t.has(c.name))throw new Error(`Duplicate plugin name: ${c.name}`);t.set(c.name,[]),e.set(c.name,0),r.set(c.name,c)}for(let c of this.pendingPlugins)for(let d of c.deps){if(!t.has(d))throw new Error(`Plugin "${c.name}" depends on unknown plugin "${d}"`);t.get(d).push(c.name),e.set(c.name,((s=e.get(c.name))!=null?s:0)+1)}let n=[],i=Array.from(e.entries()).filter(([,c])=>c===0).map(([c])=>c);for(;i.length>0;){let c=i.map(m=>r.get(m));n.push(c);let d=[];for(let m of i)for(let l of(a=t.get(m))!=null?a:[]){let g=((p=e.get(l))!=null?p:0)-1;e.set(l,g),g===0&&d.push(l)}i=d}if(n.flat().length!==this.pendingPlugins.length)throw new Error("Circular dependency detected among plugins");return n}},R=class{constructor(){this.runtime=new T;this.adapterOptions={};this.hooks={}}withPlatformAdapter(t){return this.adapterOptions.platformAdapter=t,this}withDbAdapter(t){return this.adapterOptions.dbAdapter=t,this}withHttpAdapter(t){return this.adapterOptions.httpAdapter=t,this}withHttpRetryPolicy(t){return this.adapterOptions.httpRetryPolicy=t,this}withSocketAdapter(t){return this.adapterOptions.socketAdapter=t,this}withEncryptionAdapter(t){return this.adapterOptions.encryptionAdapter=t,this}withChecksumAdapter(t){return this.adapterOptions.checksumAdapter=t,this}withActivitySink(t){return this.adapterOptions.activitySink=t,this}withLoggerAdapter(t){return this.adapterOptions.loggerAdapter=t,this}withExtension(t,e){var r;return this.adapterOptions.extensions=(r=this.adapterOptions.extensions)!=null?r:{},this.adapterOptions.extensions[t]=e,this}withHooks(t){return this.hooks={...this.hooks,...t},this}build(){return this.runtime.setHooks(this.hooks),this.runtime.registry=new k(this.runtime,this.adapterOptions),this.runtime}};function Ct(o){let t=o,e=new Set,r=(n,i)=>{for(let s of e)s(n,i)};return{getState(){return t},setState(n){let i=t;return t=typeof n=="function"?n(t):{...t,...n},r(t,i),t},reset(n){let i=t;return t=n!=null?n:o,r(t,i),t},subscribe(n){return e.add(n),()=>{e.delete(n)}}}}function Pt(o){return{getState:o.getState,subscribe:o.subscribe}}export{D as ConsoleLoggerAdapter,k as CoreAdapterRegistry,T as CoreRuntime,R as CoreRuntimeBuilder,L as DefaultExportAdapter,H as DefaultHttpAdapter,C as DefaultPlatformAdapter,I as ExponentialBackoffHttpPolicy,E as InMemoryDbAdapter,F as InMemorySocketAdapter,V as MemoryActivitySink,_ as MemoryStorageAdapter,w as NoRetryHttpPolicy,x as NoopActivitySink,S as NoopChecksumAdapter,O as NoopEncryptionAdapter,M as NoopNotificationAdapter,vt as applyPendingMigrations,Y as areChecksumsEqual,Pt as asReadonlyStore,Ct as createStore,K as executeHttpRequestWithRetry,rt as isContractVersionCompatible,tt as isFailureEnvelope,$ as migrations,P as normalizeChecksum,wt as runDbAdapterContractHarness};
|
|
1
|
+
var V=class{constructor(t){}getEnvVar(t){let e=globalThis.process;if(typeof e!="undefined"&&e.env)return e.env[t]}isOnline(){return typeof globalThis.navigator!="undefined"&&typeof globalThis.navigator.onLine!="undefined"?!!globalThis.navigator.onLine:!0}async hashPin(t){return`sha256:${t}`}async verifyPin(t,e){return await this.hashPin(t)===e}};async function K(i){i<=0||await new Promise(t=>setTimeout(t,i))}async function nt(i,t,e={}){var s;let r=e.policy,n=(s=e.sleep)!=null?s:K,o=1;for(;;)try{let a=await i.request(t);if(!r)return a;let c={request:t,attempt:o,response:a};if(!r.shouldRetry(c))return a;let l=Math.max(0,r.nextDelayMs(c));await n(l),o+=1}catch(a){if(!r)throw a;let c={request:t,attempt:o,error:a};if(!r.shouldRetry(c))throw a;let l=Math.max(0,r.nextDelayMs(c));await n(l),o+=1}}function L(i){return String(i||"").trim().toLowerCase()}function ot(i,t){return L(i)===L(t)}function X(i){return typeof(i==null?void 0:i.error)=="object"&&i!==null}function at(i){if(X(i))throw new Error(i.error.message||i.error.code);return i.data}function lt(i,t,e){return e===i?!0:t.includes(e)}var $=class{constructor(){this.schema={version:0,tables:[]};this.data={};this.tableNameResolver=t=>t;this.transactionDepth=0;this.snapshots=[]}setTableNameResolver(t){this.tableNameResolver=t}resolveTableName(t){return this.tableNameResolver(t)}async setUpWithSchema(t){this.schema={...t},this.data={},t.tables.forEach(e=>{this.data[e.name]=[]})}normalizeForComparison(t){if(t instanceof Date)return t.getTime();if(typeof t=="boolean")return t?1:0;if(typeof t=="string"||typeof t=="number"||t==null)return t;if(Array.isArray(t))return t.map(e=>this.normalizeForComparison(e));if(typeof t=="object"&&t!==null)try{return JSON.stringify(t)}catch{return String(t)}return t}evalValueExpr(t,e,r,n="t0"){if(r.type==="column"){let o=r.tableAlias||n,s=o===n?t:e[o]||{};return this.normalizeForComparison(s[r.field])}if(r.type==="literal")return this.normalizeForComparison(r.value);throw new Error(`Unsupported ValueExpression type: ${r.type}`)}buildFieldCondition(t,e){if("field"in t){let n={type:"column",tableAlias:t.alias||e,field:t.field},o={type:"literal",value:t.value};return{left:n,operator:t.operator||"=",right:o,...t.operator==="BETWEEN"?{}:{likeMode:t.likeMode}}}if("left"in t)return t;throw new Error("Invalid FieldCondition")}matchFilterExpression(t,e,r,n="t0"){if(r&&typeof r=="object"&&!Array.isArray(r)&&"and"in r)return r.and.every(o=>this.matchFilterExpression(t,e,o,n));if(r&&typeof r=="object"&&!Array.isArray(r)&&"or"in r)return r.or.some(o=>this.matchFilterExpression(t,e,o,n));if(r!==null&&typeof r=="object"&&!Array.isArray(r)){if("left"in r||"field"in r){let o=this.buildFieldCondition(r,n),s=this.evalValueExpr(t,e,o.left,n),a=this.evalValueExpr(t,e,o.right,n);if(o.operator==="IS NULL")return s==null;if(o.operator==="IS NOT NULL")return s!=null;if(o.operator==="IN"||o.operator==="NOT IN"){if(!Array.isArray(a))throw new Error("IN/NOT IN requires array on right side");let c=a.includes(s);return o.operator==="IN"?c:!c}switch(o.operator){case"=":return s===a;case"!=":return s!==a;case"<":return s<a;case"<=":return s<=a;case">":return s>a;case">=":return s>=a;case"LIKE":{if(typeof s!="string"||typeof a!="string")return!1;let c=a.replace(/%/g,".*").replace(/_/g,"."),l=o.likeMode;return new RegExp(`^${c}$`,l==="case-insensitive"?"i":"").test(s)}default:throw new Error(`Unsupported operator: ${o.operator}`)}}return Object.entries(r).every(([o,s])=>{let a=this.normalizeForComparison(t[o]),c=this.normalizeForComparison(s);return a===c})}throw new Error(`Invalid filter expression: ${JSON.stringify(r)}`)}simulateJoins(t,e,r){if(r.length===0)return e.map(o=>({record:o,joined:{}}));let n=[];for(let o of e){let s={},a=!0;for(let c of r){let l=this.resolveTableName(c.table),y=this.data[l]||[],u=null;if(c.conditions.length===1){let d=c.conditions[0];if(d.operator==="="&&d.left.type==="column"&&d.right.type==="column"){let g=d.left.tableAlias||"t0",A=d.right.tableAlias;if(g==="t0"&&A===c.alias){let m=d.left.field,h=d.right.field,p=o[m];u=y.find(b=>this.normalizeForComparison(b[h])===this.normalizeForComparison(p))}}}if(!u&&(c.type==="inner"||c.type===void 0)){a=!1;break}s[c.alias]=u||null}a&&n.push({record:o,joined:s})}return n}extractField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let o=r.tableAlias||n,s=o===n?t:e[o]||{};return this.normalizeForComparison(s[r.field])}extractAggregateField(t,e,r,n="t0"){if(typeof r=="string")return this.normalizeForComparison(t[r]);let o=r.tableAlias||n,s=o===n?t:e[o]||{};return this.normalizeForComparison(s[r.field])}async getSchemaVersion(){return this.schema.version}async setSchemaVersion(t){this.schema.version=t}async addTable(t){let e=this.resolveTableName(t.name);this.data[e]||(this.data[e]=[]),this.schema.tables.find(r=>r.name===t.name)||this.schema.tables.push(t)}async addColumn(t,e){}async get(t,e){var o;let r=this.resolveTableName(t);if(typeof e=="string"){let a=(this.data[r]||[]).find(c=>c.id===e);return a||null}return(o=(await this.query(t,{...e,limit:1}))[0])!=null?o:null}async query(t,e={}){var y;let r=this.resolveTableName(t),n="t0",o=[...this.data[r]||[]],s=this.simulateJoins(r,o,e.joins||[]);if(e.filters&&(s=s.filter(({record:u,joined:d})=>this.matchFilterExpression(u,d,e.filters,n))),e.aggregates&&e.aggregates.length>0){let u={};for(let d of e.aggregates){let g=s;d.filter&&(g=g.filter(({record:p,joined:b})=>this.matchFilterExpression(p,b,d.filter,n)));let A=g.map(({record:p,joined:b})=>this.extractAggregateField(p,b,d.field,n)),m=A.map(p=>typeof p=="number"?p:Number(p)).filter(p=>Number.isFinite(p)),h=null;switch(d.function){case"COUNT":h=A.filter(p=>p!=null).length;break;case"SUM":h=m.reduce((p,b)=>p+b,0);break;case"AVG":h=m.length?m.reduce((p,b)=>p+b,0)/m.length:0;break;case"MIN":h=m.length?Math.min(...m):null;break;case"MAX":h=m.length?Math.max(...m):null;break;default:throw new Error(`Unsupported aggregate function: ${d.function}`)}u[d.as]=h}return[u]}let a=s.map(({record:u,joined:d})=>{var g;if(e.fields){if(((g=e.resultShape)!=null?g:"flat")==="nested"){let h={};for(let[p,b]of Object.entries(e.fields)){let w=p===n?u:d[p]||{},x={};for(let k of b)x[k]=w[k];h[p]=x}return h}let m={};for(let[h,p]of Object.entries(e.fields)){let b=h===n?u:d[h]||{};for(let w of p)m[`${h}_${w}`]=b[w]}return m}return u});e.sort&&e.sort.length>0&&a.sort((u,d)=>{for(let g of e.sort){let A=this.extractField(u,{},g.field,n),m=this.extractField(d,{},g.field,n);if(A<m)return g.direction==="asc"?-1:1;if(A>m)return g.direction==="asc"?1:-1}return 0});let c=(y=e.offset)!=null?y:0,l=e.limit!=null?c+e.limit:void 0;return a.slice(c,l)}async create(t,e){let r=this.resolveTableName(t);this.data[r]||(this.data[r]=[]);let n={...e};return this.data[r].push(n),n}async update(t,e,r){let n=this.resolveTableName(t),o=this.data[n]||[],s=o.findIndex(c=>c.id===e);if(s===-1)throw new Error(`Record not found: ${t} with id ${e}`);let a={...o[s],...r};return o[s]=a,a}async delete(t,e){let r=this.resolveTableName(t),n=this.data[r]||[],o=n.findIndex(s=>s.id===e);o>=0&&n.splice(o,1)}async bulkCreate(t,e){let r=this.resolveTableName(t);this.data[r]||(this.data[r]=[]);let n=[...this.data[r]];try{let o=[];for(let s of e){let a={...s};this.data[r].push(a),o.push(a)}return o}catch(o){throw this.data[r]=n,o}}async bulkUpdate(t,e){let r=this.resolveTableName(t),n=[...this.data[r]||[]];try{let o=[];for(let{id:s,updates:a}of e){let c=await this.update(t,s,a);o.push(c)}return o}catch(o){throw this.data[r]=n,o}}takeSnapshot(){let t={};for(let e in this.data)t[e]=[...this.data[e]];return t}async transaction(t){let e=this.transactionDepth===0;e&&this.snapshots.push(this.takeSnapshot()),this.transactionDepth++;try{let r=await t(this);return e&&this.snapshots.pop(),this.transactionDepth--,r}catch(r){if(e){let n=this.snapshots.pop();n&&(this.data=n)}throw this.transactionDepth--,r}}};var _=class{constructor(t){}logInfo(t,e){console.log(t,e)}logWarn(t,e){console.warn(t,e)}logError(t,e){console.error(t,e)}};function Y(i,t){if(!t||Object.keys(t).length===0)return i;let e=new URLSearchParams;for(let[n,o]of Object.entries(t))o!=null&&e.set(n,String(o));let r=e.toString();return r?i.includes("?")?`${i}&${r}`:`${i}?${r}`:i}var N=class{constructor(t){this.fetchImpl=t}async request(t){var s,a,c,l,y,u,d,g,A;let e=(s=this.fetchImpl)!=null?s:globalThis.fetch;if(typeof e!="function")throw new Error("DefaultHttpAdapter requires fetch implementation");let r=Y(t.url,t.query),n=typeof AbortController!="undefined"?new AbortController:null,o=n&&t.timeoutMs?setTimeout(()=>n.abort(),t.timeoutMs):null;try{let m=t.body!==void 0&&t.body!==null,h={...(a=t.headers)!=null?a:{}};m&&!h["content-type"]&&(h["content-type"]="application/json");let p=await e(r,{method:t.method,headers:h,body:m?JSON.stringify(t.body):void 0,signal:n==null?void 0:n.signal}),b={};(l=(c=p.headers)==null?void 0:c.forEach)==null||l.call(c,(k,T)=>{b[T.toLowerCase()]=k});let x=((y=b["content-type"])!=null?y:"").includes("application/json")?await((d=(u=p.json)==null?void 0:u.call(p))!=null?d:Promise.resolve(void 0)):await((A=(g=p.text)==null?void 0:g.call(p))!=null?A:Promise.resolve(""));return{status:p.status,headers:b,data:x}}finally{o&&clearTimeout(o)}}};var R=class{constructor(t){}shouldRetry(t){return!1}nextDelayMs(t){return 0}};var Z=[408,425,429,500,502,503,504],j=class{constructor(t={}){var e,r,n,o;this.maxAttempts=Math.max(1,(e=t.maxAttempts)!=null?e:3),this.baseDelayMs=Math.max(0,(r=t.baseDelayMs)!=null?r:250),this.maxDelayMs=Math.max(this.baseDelayMs,(n=t.maxDelayMs)!=null?n:3e3),this.retryableStatusCodes=new Set((o=t.retryableStatusCodes)!=null?o:Z)}shouldRetry(t){var r,n;if(t.attempt>=this.maxAttempts)return!1;if(t.error)return!0;let e=(n=(r=t.response)==null?void 0:r.status)!=null?n:0;return this.retryableStatusCodes.has(e)}nextDelayMs(t){let e=Math.max(0,t.attempt-1),r=this.baseDelayMs*Math.pow(2,e);return Math.min(this.maxDelayMs,r)}};var U=class{constructor(){this.connected=!1;this.listeners=new Map}async connect(t){this.connectionOptions=t,this.connected=!0}async disconnect(){this.connected=!1}subscribe(t,e){this.listeners.has(t)||this.listeners.set(t,new Set);let r=this.listeners.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&this.listeners.delete(t)}}async publish(t,e){if(!this.connected)throw new Error(`InMemorySocketAdapter is not connected (event=${t})`);let r=this.listeners.get(t);if(!(!r||r.size===0))for(let n of r)n(e)}isConnected(){return this.connected}getConnectionOptions(){return this.connectionOptions}};var z=class{constructor(t){}configure(t){}createChannel(t){}localNotification(t){}};var q=class{constructor(t){}encrypt(t,e){return String(t)}decrypt(t,e){return String(t)}};var E=class{constructor(t){}compute(t){return""}verify(t,e){return String(e||"").trim()===""}};var C=class{constructor(t){}publish(t){}};var B=class{constructor(t){this.records=[]}publish(t){this.records.push(t)}getRecords(){return[...this.records]}clear(){this.records.length=0}};var J=class{constructor(t){}getDocumentPath(t){return t}async writeFile(t,e){throw new Error("exportAdapter.writeFile is not implemented for this platform")}async share(t){throw new Error("exportAdapter.share is not implemented for this platform")}};var W=class{constructor(t){this.map=new Map}getItem(t){var e;return(e=this.map.get(t))!=null?e:null}setItem(t,e){this.map.set(t,e)}removeItem(t){this.map.delete(t)}};var Q=[];async function Rt(i,t){if(typeof i.getSchemaVersion!="function"||typeof i.setSchemaVersion!="function"){let e="Adapter does not support schema versioning (getSchemaVersion/setSchemaVersion required)";throw t.logError(new Error(e),{message:e}),new Error(e)}t.logInfo("Starting database migration process");try{let e=[...Q].sort((o,s)=>o.toVersion-s.toVersion),r=e.length>0?e[e.length-1].toVersion:0,n=await i.getSchemaVersion();if((n==null||n<0)&&(n=0),n>=r){t.logInfo(`Database is already up-to-date at v${n}`);return}t.logInfo(`Migrating database from v${n} to v${r}`);for(let o of e)o.toVersion>n&&(t.logInfo(`Applying migration: v${o.toVersion}`),await o.up(i),await i.setSchemaVersion(o.toVersion),n=o.toVersion);t.logInfo("Database migration completed successfully")}catch(e){throw t.logError(e,{message:"Database migration failed"}),e}}function v(i,t){if(!i)throw new Error(t)}function f(i,t){return`${i}-${t}`}function tt(i){let t=[{name:"id",type:"string"},{name:"name",type:"string"},{name:"age",type:"number"},{name:"tenantId",type:"string"},{name:"isActive",type:"boolean"}];return{name:`${i}_users`,columns:t,skipMetadataColumns:!0}}function et(i){let t=[{name:"id",type:"string"},{name:"userId",type:"string",isIndexed:!0},{name:"nickname",type:"string"}];return{name:`${i}_profiles`,columns:t,skipMetadataColumns:!0}}async function Ct(i,t={}){var w,x,k,T,H,F,M;let e=((w=t.prefix)!=null?w:`dbadapter_${Date.now()}`).replace(/[^a-zA-Z0-9_]/g,"_"),r=`${e}_users`,n=`${e}_profiles`;await i.setSchemaVersion(7);let o=await i.getSchemaVersion();v(o===7,`Expected schema version 7, got ${o}`),await i.addTable(tt(e)),await i.addTable(et(e)),await i.addColumn(r,{name:"email",type:"string",isOptional:!0}),await i.create(r,{id:f(e,"u1"),name:"Alice",age:31,tenantId:"tenant-1",isActive:!0,email:"alice@example.com"}),await i.create(r,{id:f(e,"u2"),name:"Bob",age:24,tenantId:"tenant-1",isActive:!1,email:"bob@example.com"}),await i.bulkCreate(r,[{id:f(e,"u3"),name:"Carla",age:29,tenantId:"tenant-2",isActive:!0,email:"carla@example.com"},{id:f(e,"u4"),name:"Dian",age:22,tenantId:"tenant-2",isActive:!0}]),await i.bulkCreate(n,[{id:f(e,"p1"),userId:f(e,"u1"),nickname:"alice-nick"},{id:f(e,"p2"),userId:f(e,"u3"),nickname:"carla-nick"}]);let s=await i.get(r,f(e,"u1"));v((s==null?void 0:s.name)==="Alice","Expected get(table, id) to return Alice");let a=await i.query(r,{filters:{tenantId:"tenant-1"},sort:[{field:"age",direction:"desc"}]});v(a.length===2,`Expected 2 tenant-1 users, got ${a.length}`),v(a[0].age>=a[1].age,"Expected sorted by age desc");let c={and:[{field:"tenantId",value:"tenant-2"},{field:"isActive",value:!0}]},l=await i.query(r,{filters:c,sort:[{field:"name",direction:"asc"}]});v(l.length===2,`Expected 2 active tenant-2 users, got ${l.length}`);let y={filters:{and:[{field:"id",value:f(e,"u2")},{field:"tenantId",value:"tenant-1"}]}},u=await i.get(r,y);v((u==null?void 0:u.name)==="Bob","Expected get(table, options) to resolve Bob");let d=await i.update(r,f(e,"u1"),{age:32});v(d.age===32,`Expected age updated to 32, got ${d.age}`);let g=await i.bulkUpdate(r,[{id:f(e,"u3"),updates:{age:30}},{id:f(e,"u4"),updates:{age:23}}]);v(g.length===2,`Expected 2 bulk-updated rows, got ${g.length}`);let A=await i.query(r,{sort:[{field:"age",direction:"asc"}],limit:2,offset:1});v(A.length===2,`Expected 2 paged rows, got ${A.length}`);let m=await i.query(r,{fields:{t0:["id","name"],p:["nickname"]},joins:[{table:n,alias:"p",type:"left",conditions:[{left:{type:"column",tableAlias:"t0",field:"id"},operator:"=",right:{type:"column",tableAlias:"p",field:"userId"}}]}],filters:{field:"id",value:f(e,"u1")},resultShape:"flat"});v(m.length===1,`Expected one projected flat row, got ${m.length}`),v(((x=m[0])==null?void 0:x.t0_id)===f(e,"u1"),"Expected flat projected key t0_id"),v(((k=m[0])==null?void 0:k.p_nickname)==="alice-nick","Expected flat projected key p_nickname");let h=await i.query(r,{fields:{t0:["id","name"],p:["nickname"]},joins:[{table:n,alias:"p",type:"left",conditions:[{left:{type:"column",tableAlias:"t0",field:"id"},operator:"=",right:{type:"column",tableAlias:"p",field:"userId"}}]}],filters:{field:"id",value:f(e,"u1")},resultShape:"nested"});v(h.length===1,`Expected one projected nested row, got ${h.length}`),v(((H=(T=h[0])==null?void 0:T.t0)==null?void 0:H.id)===f(e,"u1"),"Expected nested row t0.id"),v(((M=(F=h[0])==null?void 0:F.p)==null?void 0:M.nickname)==="alice-nick","Expected nested row p.nickname");try{throw await i.transaction(async S=>{throw await S.create(r,{id:f(e,"tx_rollback"),name:"TxRollback",age:40,tenantId:"tenant-1",isActive:!0}),new Error("rollback-intent")}),new Error("Expected transaction rollback to throw")}catch(S){let O=S instanceof Error?S.message:String(S);v(O.includes("rollback-intent"),`Expected rollback-intent error, got ${O}`)}let p=await i.get(r,f(e,"tx_rollback"));v(p===null,"Expected rolled back record to not exist"),await i.delete(r,f(e,"u2"));let b=await i.get(r,f(e,"u2"));v(b===null,"Expected deleted record to be null")}var P=class{constructor(t,e){this.extensions=new Map;var r,n,o,s,a,c,l,y,u,d,g,A,m;this.platformAdapter=(r=e.platformAdapter)==null?void 0:r.call(e,t),this.dbAdapter=(n=e.dbAdapter)==null?void 0:n.call(e,t),this.loggerAdapter=(o=e.loggerAdapter)==null?void 0:o.call(e,t),this.httpAdapter=(s=e.httpAdapter)==null?void 0:s.call(e,t),this.httpRetryPolicy=(c=(a=e.httpRetryPolicy)==null?void 0:a.call(e,t))!=null?c:new R(t),this.socketAdapter=(l=e.socketAdapter)==null?void 0:l.call(e,t),this.encryptionAdapter=(y=e.encryptionAdapter)==null?void 0:y.call(e,t),this.checksumAdapter=(d=(u=e.checksumAdapter)==null?void 0:u.call(e,t))!=null?d:new E(t),this.activitySink=(A=(g=e.activitySink)==null?void 0:g.call(e,t))!=null?A:new C(t);for(let[h,p]of Object.entries((m=e.extensions)!=null?m:{}))this.extensions.set(h,p(t))}getExtension(t){return this.extensions.get(t)}clear(){this.extensions.clear()}};function G(i){return!!i&&typeof i.shutdown=="function"}var D=class{constructor(){this.correlationCounter=0;this.started=!1;this.pluginsLoaded=!1;this.pendingPlugins=[];this.hooks={}}static builder(){return new I}setHooks(t){this.hooks={...this.hooks,...t}}use(t,e,r=[]){if(!t.trim())throw new Error("plugin name is required");return this.pendingPlugins.some(n=>n.name===t)?this:(this.pendingPlugins.push({name:t,init:e,deps:r}),this)}async init(t={runMigrations:!0,useSeedData:!1}){if(!this.registry)throw new Error("CoreRuntime registry is not initialized. Call builder().build() first.");if(t.runMigrations!==!1&&this.hooks.runMigrations&&await this.hooks.runMigrations(this),this.hooks.onInit&&await this.hooks.onInit(this),!this.domainServices&&this.hooks.createDomainServices&&(this.domainServices=await this.hooks.createDomainServices(this)),!this.integrationServices&&this.hooks.createIntegrationServices&&(this.integrationServices=await this.hooks.createIntegrationServices(this)),!this.pluginsLoaded){let n=this.resolvePluginLevels();for(let o of n)await Promise.all(o.map(s=>s.init(this)));this.pluginsLoaded=!0}t.useSeedData===!0&&this.hooks.runSeed&&await this.hooks.runSeed(this)}async start(t={}){if(this.started)throw new Error("CoreRuntime already started");try{await this.init(t),this.started=!0}catch(e){throw this.started=!1,e}}async stop(){var t;this.started&&(this.hooks.onStop&&await this.hooks.onStop(this),G(this.integrationServices)&&await this.integrationServices.shutdown(),G(this.domainServices)&&await this.domainServices.shutdown(),(t=this.registry)==null||t.clear(),this.started=!1)}async reset(){await this.stop(),this.domainServices=void 0,this.integrationServices=void 0,this.pendingPlugins=[],this.pluginsLoaded=!1,this.hooks={}}async restart(){let t=[...this.pendingPlugins],e={...this.hooks};await this.reset(),this.pendingPlugins=t,this.hooks=e,await this.start()}isStarted(){return this.started}createCorrelationId(t="cid"){return this.correlationCounter+=1,`${t}-${Date.now()}-${this.correlationCounter}`}logInfo(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logInfo(t,e)}logWarn(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logWarn(t,e)}logError(t,e){var r,n;(n=(r=this.registry)==null?void 0:r.loggerAdapter)==null||n.logError(t,e)}async emitActivity(t){var e;(e=this.registry)!=null&&e.activitySink&&await this.registry.activitySink.publish(t)}resolvePluginLevels(){var s,a,c;if(this.pendingPlugins.length===0)return[];let t=new Map,e=new Map,r=new Map;for(let l of this.pendingPlugins){if(t.has(l.name))throw new Error(`Duplicate plugin name: ${l.name}`);t.set(l.name,[]),e.set(l.name,0),r.set(l.name,l)}for(let l of this.pendingPlugins)for(let y of l.deps){if(!t.has(y))throw new Error(`Plugin "${l.name}" depends on unknown plugin "${y}"`);t.get(y).push(l.name),e.set(l.name,((s=e.get(l.name))!=null?s:0)+1)}let n=[],o=Array.from(e.entries()).filter(([,l])=>l===0).map(([l])=>l);for(;o.length>0;){let l=o.map(u=>r.get(u));n.push(l);let y=[];for(let u of o)for(let d of(a=t.get(u))!=null?a:[]){let g=((c=e.get(d))!=null?c:0)-1;e.set(d,g),g===0&&y.push(d)}o=y}if(n.flat().length!==this.pendingPlugins.length)throw new Error("Circular dependency detected among plugins");return n}},I=class{constructor(){this.runtime=new D;this.adapterOptions={};this.hooks={}}withPlatformAdapter(t){return this.adapterOptions.platformAdapter=t,this}withDbAdapter(t){return this.adapterOptions.dbAdapter=t,this}withHttpAdapter(t){return this.adapterOptions.httpAdapter=t,this}withHttpRetryPolicy(t){return this.adapterOptions.httpRetryPolicy=t,this}withSocketAdapter(t){return this.adapterOptions.socketAdapter=t,this}withEncryptionAdapter(t){return this.adapterOptions.encryptionAdapter=t,this}withChecksumAdapter(t){return this.adapterOptions.checksumAdapter=t,this}withActivitySink(t){return this.adapterOptions.activitySink=t,this}withLoggerAdapter(t){return this.adapterOptions.loggerAdapter=t,this}withExtension(t,e){var r;return this.adapterOptions.extensions=(r=this.adapterOptions.extensions)!=null?r:{},this.adapterOptions.extensions[t]=e,this}withHooks(t){return this.hooks={...this.hooks,...t},this}build(){return this.runtime.setHooks(this.hooks),this.runtime.registry=new P(this.runtime,this.adapterOptions),this.runtime}};function Mt(i){let t=i,e=new Set,r=(n,o)=>{for(let s of e)s(n,o)};return{getState(){return t},setState(n){let o=t;return t=typeof n=="function"?n(t):{...t,...n},r(t,o),t},reset(n){let o=t;return t=n!=null?n:i,r(t,o),t},subscribe(n){return e.add(n),()=>{e.delete(n)}}}}function Ot(i){return{getState:i.getState,subscribe:i.subscribe}}function Lt(){return new Date().toISOString()}function $t(i){let t=0;return()=>(t+=1,`${i}-${Date.now()}-${t}`)}function _t(i){return JSON.parse(JSON.stringify(i))}function Nt(i){if(i.length!==0)return i.length===1?i[0]:{and:i}}export{_ as ConsoleLoggerAdapter,P as CoreAdapterRegistry,D as CoreRuntime,I as CoreRuntimeBuilder,J as DefaultExportAdapter,N as DefaultHttpAdapter,V as DefaultPlatformAdapter,j as ExponentialBackoffHttpPolicy,$ as InMemoryDbAdapter,U as InMemorySocketAdapter,B as MemoryActivitySink,W as MemoryStorageAdapter,R as NoRetryHttpPolicy,C as NoopActivitySink,E as NoopChecksumAdapter,q as NoopEncryptionAdapter,z as NoopNotificationAdapter,Rt as applyPendingMigrations,ot as areChecksumsEqual,Ot as asReadonlyStore,_t as cloneValue,Mt as createStore,nt as executeHttpRequestWithRetry,lt as isContractVersionCompatible,X as isFailureEnvelope,$t as makeIdFactory,Q as migrations,L as normalizeChecksum,Lt as nowIso,Ct as runDbAdapterContractHarness,Nt as toAndFilter,at as unwrap};
|
|
@@ -222,6 +222,14 @@ export interface QueryOptions {
|
|
|
222
222
|
*/
|
|
223
223
|
mainAlias?: string;
|
|
224
224
|
include?: IncludeSpec;
|
|
225
|
+
/**
|
|
226
|
+
* Result shape contract for projected queries (`fields`).
|
|
227
|
+
* - `flat` : `{ "t0_id": "...", "u_name": "..." }`
|
|
228
|
+
* - `nested` : `{ t0: { id: "..." }, u: { name: "..." } }`
|
|
229
|
+
*
|
|
230
|
+
* Default must be `flat` for backward compatibility.
|
|
231
|
+
*/
|
|
232
|
+
resultShape?: 'flat' | 'nested';
|
|
225
233
|
}
|
|
226
234
|
export interface ColumnRelation {
|
|
227
235
|
table: string;
|
|
@@ -264,6 +272,8 @@ export interface DbSchema {
|
|
|
264
272
|
tables: TableSchema[];
|
|
265
273
|
}
|
|
266
274
|
export interface DbAdapter {
|
|
275
|
+
setTableNameResolver(resolver: (logicalTableName: string) => string): void;
|
|
276
|
+
resolveTableName(logicalTableName: string): string;
|
|
267
277
|
getSchemaVersion(): Promise<number>;
|
|
268
278
|
setSchemaVersion(version: number): Promise<void>;
|
|
269
279
|
addTable(table: TableSchema): Promise<void>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FilterExpression } from '../ports/DbAdapter';
|
|
2
|
+
export declare function nowIso(): string;
|
|
3
|
+
export declare function makeIdFactory(prefix: string): () => string;
|
|
4
|
+
export declare function cloneValue<T>(value: T): T;
|
|
5
|
+
export declare function toAndFilter(filters: FilterExpression[]): FilterExpression | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofcore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-alpha.1",
|
|
4
4
|
"description": "Lightweight runtime core for offline-first TypeScript apps.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Agus Made",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"verify:core-runtime": "node ./scripts/verify-core-runtime.js",
|
|
34
34
|
"verify:store": "node ./scripts/verify-store.js",
|
|
35
35
|
"ci:check": "npm run build && npm run verify:contract && npm run verify:logic",
|
|
36
|
-
"prepublishOnly": "npm run ci:check"
|
|
36
|
+
"prepublishOnly": "npm run ci:check",
|
|
37
|
+
"prepack": "npm run build"
|
|
37
38
|
},
|
|
38
39
|
"publishConfig": {
|
|
39
40
|
"access": "public"
|