@stacksjs/orm 0.75.347 → 0.75.349
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/traits/actor.d.ts +2 -0
- package/dist/traits/actor.js +1 -1
- package/dist/traits/audit.js +1 -1
- package/package.json +23 -23
package/dist/traits/actor.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export declare function currentTrailActor(): number | string | null;
|
|
|
19
19
|
* to fail the write being described.
|
|
20
20
|
*/
|
|
21
21
|
export declare function resolveTrailActorId(): Promise<number | string | null>;
|
|
22
|
+
/** Resolve only the request identity, independently of CLI/job overrides. */
|
|
23
|
+
export declare function resolveRequestTrailActorId(): Promise<number | string | null>;
|
|
22
24
|
/**
|
|
23
25
|
* The requesting IP, when there is a request to ask.
|
|
24
26
|
*
|
package/dist/traits/actor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{log}from"@stacksjs/logging";const SENSITIVE_FIELD_PATTERNS=[/^password$/i,/^password_hash$/i,/^api_key$/i,/_token$/i,/_secret$/i,/^remember_token$/i];let explicitActorId=null;export function setTrailActor(id){explicitActorId=id}export function currentTrailActor(){return explicitActorId}export async function resolveTrailActorId(){if(explicitActorId!=null)return explicitActorId;try{const mod=await import("@stacksjs/router").catch(()=>null);if(!mod)return null;const getCurrentRequest=mod.getCurrentRequest;if(typeof getCurrentRequest!=="function")return null;const request=getCurrentRequest();return request?.user?.id??request?._user?.id??null}catch{return null}}export async function resolveTrailIp(){try{const getCurrentRequest=(await import("@stacksjs/router").catch(()=>null))?.getCurrentRequest;if(typeof getCurrentRequest!=="function")return null;const request=getCurrentRequest();return typeof request?.ip==="function"?request.ip()??null:null}catch{return null}}export function redactSensitive(attributes){if(!attributes||typeof attributes!=="object")return null;const safe={};for(const[key,value]of Object.entries(attributes)){if(SENSITIVE_FIELD_PATTERNS.some((pattern)=>pattern.test(key)))continue;safe[key]=value}return safe}export function reportTrailFailure(trail,subject,error){log.warn(`[orm] ${trail} row write failed for ${subject}: ${error?.message??String(error)}`)}
|
|
1
|
+
import{log}from"@stacksjs/logging";const SENSITIVE_FIELD_PATTERNS=[/^password$/i,/^password_hash$/i,/^api_key$/i,/_token$/i,/_secret$/i,/^remember_token$/i];let explicitActorId=null;export function setTrailActor(id){explicitActorId=id}export function currentTrailActor(){return explicitActorId}export async function resolveTrailActorId(){if(explicitActorId!=null)return explicitActorId;return resolveRequestTrailActorId()}export async function resolveRequestTrailActorId(){try{const mod=await import("@stacksjs/router").catch(()=>null);if(!mod)return null;const getCurrentRequest=mod.getCurrentRequest;if(typeof getCurrentRequest!=="function")return null;const request=getCurrentRequest();return request?._authenticatedUser?.id??request?.user?.id??request?._user?.id??null}catch{return null}}export async function resolveTrailIp(){try{const getCurrentRequest=(await import("@stacksjs/router").catch(()=>null))?.getCurrentRequest;if(typeof getCurrentRequest!=="function")return null;const request=getCurrentRequest();return typeof request?.ip==="function"?request.ip()??null:null}catch{return null}}export function redactSensitive(attributes){if(!attributes||typeof attributes!=="object")return null;const safe={};for(const[key,value]of Object.entries(attributes)){if(SENSITIVE_FIELD_PATTERNS.some((pattern)=>pattern.test(key)))continue;safe[key]=value}return safe}export function reportTrailFailure(trail,subject,error){log.warn(`[orm] ${trail} row write failed for ${subject}: ${error?.message??String(error)}`)}
|
package/dist/traits/audit.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sqlDateTime}from"@stacksjs/database/runtime";import{log}from"@stacksjs/logging";const SENSITIVE_FIELD_PATTERNS=[/^password$/i,/^password_hash$/i,/^api_key$/i,/_token$/i,/_secret$/i,/^remember_token$/i],AUDITS_TABLE="model_audits";let _explicitAuditUserId=null;export function setAuditUser(id){_explicitAuditUserId=id}async function resolveAuditUserId(){if(_explicitAuditUserId!=null)return _explicitAuditUserId;
|
|
1
|
+
import{sqlDateTime}from"@stacksjs/database/runtime";import{log}from"@stacksjs/logging";import{resolveRequestTrailActorId}from"./actor";const SENSITIVE_FIELD_PATTERNS=[/^password$/i,/^password_hash$/i,/^api_key$/i,/_token$/i,/_secret$/i,/^remember_token$/i],AUDITS_TABLE="model_audits";let _explicitAuditUserId=null;export function setAuditUser(id){_explicitAuditUserId=id}async function resolveAuditUserId(){if(_explicitAuditUserId!=null)return _explicitAuditUserId;return resolveRequestTrailActorId()}function redactSensitive(row){if(!row||typeof row!=="object")return null;const out={};for(const[k,v]of Object.entries(row)){if(SENSITIVE_FIELD_PATTERNS.some((rx)=>rx.test(k)))continue;out[k]=v}return out}function plainAttrs(value){if(!value||typeof value!=="object")return null;const v=value;if(v._attributes&&typeof v._attributes==="object")return{...v._attributes};return{...value}}function diffAttrs(before,after){if(!before||!after)return{old:before,next:after};const old={},next={},keys=new Set([...Object.keys(before),...Object.keys(after)]);for(const k of keys)if(before[k]!==after[k]){old[k]=before[k];next[k]=after[k]}return{old,next}}async function writeAuditRow(payload,transactional=!1){try{const{db}=await import("@stacksjs/database/runtime");await db.insertInto(AUDITS_TABLE).values({auditable_type:payload.auditable_type,auditable_id:payload.auditable_id,event:payload.event,old_values:payload.old_values?JSON.stringify(payload.old_values):null,new_values:payload.new_values?JSON.stringify(payload.new_values):null,user_id:payload.user_id,created_at:sqlDateTime()}).executeTakeFirst()}catch(err){log.warn(`[orm] audit row write failed for ${payload.auditable_type}#${String(payload.auditable_id)} (${payload.event})`,{error:err});if(transactional)throw err}}export function createAuditMethods(modelName){return{async audits(id){try{const{db}=await import("@stacksjs/database/runtime");return(await db.selectFrom(AUDITS_TABLE).selectAll().where("auditable_type","=",modelName).where("auditable_id","=",id).orderBy("created_at","desc").execute()??[]).map((r)=>({...r,old_values:typeof r.old_values==="string"?safeJsonParse(r.old_values):r.old_values,new_values:typeof r.new_values==="string"?safeJsonParse(r.new_values):r.new_values}))}catch(err){log.warn(`[orm] audits() lookup failed for ${modelName}#${String(id)}`,{error:err});return[]}}}}function safeJsonParse(value){try{return JSON.parse(value)}catch{return value}}export function resolveAuditOptions(useAudit){if(useAudit&&typeof useAudit==="object"&&"transactional"in useAudit)return{transactional:useAudit.transactional===!0};return{transactional:!1}}export function applyAudit(baseModel,modelName,primaryKey="id",opts={}){const transactional=opts.transactional===!0,model=baseModel;if(typeof baseModel.audits!=="function")baseModel.audits=createAuditMethods(modelName).audits;const runWithOptionalTx=async(fn)=>{if(!transactional)return await fn();const{db}=await import("@stacksjs/database/runtime");return await db.transaction(async()=>fn())},origCreate=baseModel.create;if(typeof origCreate==="function")baseModel.create=async function(...args){return await runWithOptionalTx(async()=>{const result=await origCreate.apply(this,args);try{const newAttrs=plainAttrs(result),id=newAttrs?.[primaryKey];if(id!=null){const userId=await resolveAuditUserId();await writeAuditRow({auditable_type:modelName,auditable_id:id,event:"created",old_values:null,new_values:redactSensitive(newAttrs),user_id:userId},transactional)}}catch(err){log.warn(`[orm] audit(create) failed for ${modelName}`,{error:err});if(transactional)throw err}return result})};const origCreateMany=baseModel.createMany;if(typeof origCreateMany==="function")baseModel.createMany=async function(...args){return await runWithOptionalTx(async()=>{const result=await origCreateMany.apply(this,args);try{const userId=Array.isArray(result)&&result.length?await resolveAuditUserId():null;for(const record of Array.isArray(result)?result:[]){const newAttrs=plainAttrs(record),id=newAttrs?.[primaryKey];if(id==null)continue;await writeAuditRow({auditable_type:modelName,auditable_id:id,event:"created",old_values:null,new_values:redactSensitive(newAttrs),user_id:userId},transactional)}}catch(err){log.warn(`[orm] audit(createMany) failed for ${modelName}`,{error:err});if(transactional)throw err}return result})};const origUpdate=baseModel.update;if(typeof origUpdate==="function")baseModel.update=async function(id,data){return await runWithOptionalTx(async()=>{const find=model.find,before=typeof find==="function"?plainAttrs(await find.call(model,id)):null,result=await origUpdate.call(this,id,data);try{const after=plainAttrs(result)??(typeof find==="function"?plainAttrs(await find.call(model,id)):null),{old,next}=diffAttrs(before,after);if(next&&Object.keys(next).length>0){const userId=await resolveAuditUserId();await writeAuditRow({auditable_type:modelName,auditable_id:id,event:"updated",old_values:redactSensitive(old),new_values:redactSensitive(next),user_id:userId},transactional)}}catch(err){log.warn(`[orm] audit(update) failed for ${modelName}#${String(id)}`,{error:err});if(transactional)throw err}return result})};const wrapDelete=(key)=>{const orig=baseModel[key];if(typeof orig!=="function")return;baseModel[key]=async function(id){return await runWithOptionalTx(async()=>{const find=model.find,before=typeof find==="function"?plainAttrs(await find.call(model,id)):null,result=await orig.call(this,id);try{if(result!==!1&&before){const userId=await resolveAuditUserId();await writeAuditRow({auditable_type:modelName,auditable_id:id,event:"deleted",old_values:redactSensitive(before),new_values:null,user_id:userId},transactional)}}catch(err){log.warn(`[orm] audit(${key}) failed for ${modelName}#${String(id)}`,{error:err});if(transactional)throw err}return result})}};wrapDelete("delete");wrapDelete("softDelete")}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/orm",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.349",
|
|
6
6
|
"description": "The Stacks ORM integration",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -63,31 +63,31 @@
|
|
|
63
63
|
"prepublishOnly": "bun run build"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@stacksjs/cache": "0.75.
|
|
67
|
-
"@stacksjs/cli": "0.75.
|
|
68
|
-
"@stacksjs/config": "0.75.
|
|
69
|
-
"@stacksjs/database": "0.75.
|
|
70
|
-
"@stacksjs/env": "0.75.
|
|
71
|
-
"@stacksjs/error-handling": "0.75.
|
|
72
|
-
"@stacksjs/events": "0.75.
|
|
73
|
-
"@stacksjs/logging": "0.75.
|
|
74
|
-
"@stacksjs/model-meta": "0.75.
|
|
75
|
-
"@stacksjs/pagination": "0.75.
|
|
76
|
-
"@stacksjs/path": "0.75.
|
|
77
|
-
"@stacksjs/query-builder": "0.75.
|
|
78
|
-
"@stacksjs/realtime": "0.75.
|
|
79
|
-
"@stacksjs/router": "0.75.
|
|
80
|
-
"@stacksjs/storage": "0.75.
|
|
81
|
-
"@stacksjs/strings": "0.75.
|
|
66
|
+
"@stacksjs/cache": "0.75.349",
|
|
67
|
+
"@stacksjs/cli": "0.75.349",
|
|
68
|
+
"@stacksjs/config": "0.75.349",
|
|
69
|
+
"@stacksjs/database": "0.75.349",
|
|
70
|
+
"@stacksjs/env": "0.75.349",
|
|
71
|
+
"@stacksjs/error-handling": "0.75.349",
|
|
72
|
+
"@stacksjs/events": "0.75.349",
|
|
73
|
+
"@stacksjs/logging": "0.75.349",
|
|
74
|
+
"@stacksjs/model-meta": "0.75.349",
|
|
75
|
+
"@stacksjs/pagination": "0.75.349",
|
|
76
|
+
"@stacksjs/path": "0.75.349",
|
|
77
|
+
"@stacksjs/query-builder": "0.75.349",
|
|
78
|
+
"@stacksjs/realtime": "0.75.349",
|
|
79
|
+
"@stacksjs/router": "0.75.349",
|
|
80
|
+
"@stacksjs/storage": "0.75.349",
|
|
81
|
+
"@stacksjs/strings": "0.75.349",
|
|
82
82
|
"@stacksjs/ts-validation": "^0.5.6",
|
|
83
|
-
"@stacksjs/validation": "0.75.
|
|
83
|
+
"@stacksjs/validation": "0.75.349",
|
|
84
84
|
"bun-query-builder": "^0.3.28"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
|
-
"@stacksjs/auth": "0.75.
|
|
88
|
-
"@stacksjs/payments": "0.75.
|
|
89
|
-
"@stacksjs/queue": "0.75.
|
|
90
|
-
"@stacksjs/search-engine": "0.75.
|
|
87
|
+
"@stacksjs/auth": "0.75.349",
|
|
88
|
+
"@stacksjs/payments": "0.75.349",
|
|
89
|
+
"@stacksjs/queue": "0.75.349",
|
|
90
|
+
"@stacksjs/search-engine": "0.75.349",
|
|
91
91
|
"stripe": "23.0.0"
|
|
92
92
|
},
|
|
93
93
|
"peerDependenciesMeta": {
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
|
-
"@stacksjs/types": "0.75.
|
|
111
|
+
"@stacksjs/types": "0.75.349",
|
|
112
112
|
"better-dx": "^0.2.24",
|
|
113
113
|
"stripe": "23.0.0"
|
|
114
114
|
}
|