@payfit/audit-log 3.5.0-rc.18 → 3.5.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,8 @@ Then, you must instanciate a client :
16
16
  import { AuditLogger } from '@payfit/audit-log'
17
17
 
18
18
  const logger = new AuditLogger({
19
- environment: 'dev', // must be one of: dev, staging, prod
19
+ apiUrl: 'http://localhost:8090',
20
+ environment: 'an-environment-name',
20
21
  service: 'the-name-of-the-service',
21
22
  })
22
23
  ```
package/dist/index.d.ts CHANGED
@@ -1,10 +1,7 @@
1
- import type { Logger } from 'winston';
2
- import { type IMetricsClient } from './metrics';
3
- import { IAuditLogTransport } from './transport/interface';
4
1
  /**
5
2
  * The allowed Namespaces for the AuditLog
6
3
  */
7
- export type AuditNamespaces = 'employee' | 'company' | 'permissions' | 'absence' | 'expense' | 'payments' | 'auth' | 'billing' | 'modules' | 'integrations' | 'partnerApi' | 'donation' | 'notificationSettings' | 'people' | 'subscriptions' | 'organization' | 'declarations' | 'pricing' | 'payroll' | 'jetlang' | 'files' | 'versioner' | 'live-timing';
4
+ export type AuditNamespaces = 'employee' | 'company' | 'permissions' | 'absence' | 'expense' | 'payments' | 'auth' | 'billing' | 'modules' | 'integrations' | 'partnerApi' | 'donation' | 'notificationSettings' | 'people' | 'subscriptions' | 'organization' | 'declarations' | 'pricing' | 'payroll' | 'jetlang' | 'files' | 'versioner';
8
5
  /**
9
6
  * The allowed targets for the AuditLog
10
7
  */
@@ -95,21 +92,13 @@ export interface IAuditLogger {
95
92
  log: (data: IAuditLogData) => Promise<void>;
96
93
  }
97
94
  export interface IAuditLoggerInitialization {
98
- /** @deprecated No longer used. The library routes via SQS based on `environment`. Kept for backward compatibility. */
99
- apiUrl?: string;
95
+ apiUrl: string;
100
96
  environment: string;
101
97
  service: string;
102
98
  }
103
- export interface IAuditLoggerDependencies {
104
- transport?: IAuditLogTransport;
105
- logger?: Logger;
106
- metrics?: IMetricsClient;
107
- }
108
99
  export declare class AuditLogger implements IAuditLogger {
109
100
  protected params: IAuditLoggerInitialization;
110
- private readonly transport;
111
- private readonly logger;
112
- private readonly metrics;
113
- constructor(params: IAuditLoggerInitialization, deps?: IAuditLoggerDependencies);
101
+ private transport;
102
+ constructor(params: IAuditLoggerInitialization);
114
103
  log({ scope, account, ...data }: IAuditLogData): Promise<void>;
115
104
  }
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var v=Object.defineProperty;var p=(s,t,e)=>t in s?v(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var n=(s,t,e)=>(p(s,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("uuid"),o=require("winston"),S=require("hot-shots"),m=require("@aws-sdk/client-sqs"),E="audit-logs",_="@payfit/audit-log",L=()=>{const s=process.env.LOG_LEVEL;return s&&s.trim()!==""?s.trim():"info"},q=(s,t)=>o.createLogger({level:L(),silent:process.env.NODE_ENV==="test",exitOnError:!1,defaultMeta:{namespace:E,sdk:_,service:s,environment:t},format:o.format.combine(o.format.timestamp(),o.format.errors({stack:!0}),o.format.json()),transports:[new o.transports.Console]}),y="payfit.audit-logs.",d=s=>Object.entries(s).filter(([,t])=>t!==void 0&&t!=="").map(([t,e])=>`${t}:${String(e)}`);class A{constructor(){n(this,"client");this.client=new S.StatsD({prefix:y,errorHandler:()=>{},cacheDns:!0})}increment(t,e){this.client.increment(t,1,d(e))}histogram(t,e,i){this.client.histogram(t,e,d(i))}async close(){await new Promise(t=>{this.client.close(()=>t())})}}const M=()=>new A,D="eu-west-3",U={dev:"https://sqs.eu-west-3.amazonaws.com/533547282673/audit-logs-ingest",staging:"https://sqs.eu-west-3.amazonaws.com/589883667243/audit-logs-ingest",prod:"https://sqs.eu-west-3.amazonaws.com/614948436281/audit-logs-ingest"},C={working:"staging",production:"prod"};class O{constructor(t){n(this,"environment");n(this,"client");n(this,"queueUrl");this.environment=t;const e=C[t]??t,i=U[e];if(!i)throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${t}"`);this.queueUrl=i,this.client=new m.SQSClient({region:D})}async create(t){await this.client.send(new m.SendMessageCommand({QueueUrl:this.queueUrl,MessageBody:JSON.stringify(t)}))}}class N{constructor(t,e={}){n(this,"params");n(this,"transport");n(this,"logger");n(this,"metrics");this.params=t,this.transport=e.transport??new O(t.environment),this.logger=e.logger??q(t.service,t.environment),this.metrics=e.metrics??M()}async log({scope:t,account:e,...i}){const h=f.v4(),{environment:c,service:g}=this.params,r={...i,...e,service:g,id:h,environment:c,...t&&{scope:t}},a={service:g,environment:c,namespace:r.namespace,event:r.event,target:r.target},l=Date.now();try{await this.transport.create(r),this.metrics.increment("sent",a),this.metrics.histogram("send_duration_ms",Date.now()-l,a),this.logger.debug("audit-log sent",{id:r.id,event:r.event,target:r.target})}catch(w){this.metrics.increment("send_failed",a),this.metrics.histogram("send_duration_ms",Date.now()-l,a);const u=w.message;try{this.logger.error("audit-log write failed",{audit_log:r,error:u})}catch{this.metrics.increment("serialization_failed",a);try{this.logger.error("audit-log write failed (serialization failed)",{audit_log_meta:{id:r.id,service:r.service,environment:r.environment,namespace:r.namespace,event:r.event,target:r.target},error:u})}catch{}}}}}exports.AuditLogger=N;
1
+ "use strict";var d=Object.defineProperty;var P=(s,e,t)=>e in s?d(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var n=(s,e,t)=>(P(s,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("uuid"),h=require("axios"),p="http://localhost:8090".replace(/\/+$/,"");class f{constructor(e,t=p,r=h){n(this,"basePath");n(this,"axios");n(this,"configuration");this.basePath=t,this.axios=r,e&&(this.configuration=e,this.basePath=e.basePath||this.basePath)}}class g extends Error{constructor(t,r){super(r);n(this,"field");n(this,"name","RequiredError");this.field=t}}const A="https://example.com",w=function(s,e,t){if(t==null)throw new g(e,`Required parameter ${e} was null or undefined when calling ${s}.`)},b=function(s,...e){const t=new URLSearchParams(s.search);for(const r of e)for(const o in r)if(Array.isArray(r[o])){t.delete(o);for(const a of r[o])t.append(o,a)}else t.set(o,r[o]);s.search=t.toString()},x=function(s,e,t){const r=typeof s!="string";return(r&&t&&t.isJsonMime?t.isJsonMime(e.headers["Content-Type"]):r)?JSON.stringify(s!==void 0?s:{}):s||""},y=function(s){return s.pathname+s.search+s.hash},L=function(s,e,t,r){return(o=e,a=t)=>{const i={...s.options,url:((r==null?void 0:r.basePath)||a)+s.url};return o.request(i)}},S=function(s){return{v1LogPost:async(e,t={})=>{w("v1LogPost","inlineObject",e);const r="/v1/log",o=new URL(r,A);let a;s&&(a=s.baseOptions);const i={method:"POST",...a,...t},c={},l={};c["Content-Type"]="application/json",b(o,l);let u=a&&a.headers?a.headers:{};return i.headers={...c,...u,...t.headers},i.data=x(e,i,s),{url:y(o),options:i}}}},E=function(s){const e=S(s);return{async v1LogPost(t,r){const o=await e.v1LogPost(t,r);return L(o,h,p,s)}}};class v extends f{v1LogPost(e,t){return E(this.configuration).v1LogPost(e,t).then(r=>r(this.axios,this.basePath))}}const R=s=>"isAxiosError"in s&&s.isAxiosError&&s instanceof Error;class j{constructor(e){n(this,"apiUrl");n(this,"api");this.apiUrl=e,this.api=new v({basePath:this.apiUrl,isJsonMime(t){const r=new RegExp("^(application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(;.*)?$","i");return t!==null&&(r.test(t)||t.toLowerCase()==="application/json-patch+json")}})}async create(e){var t;try{await this.api.v1LogPost(e,{timeout:5e3})}catch(r){if(!R(r))throw r;const o=((t=r.response)==null?void 0:t.data)||r.message;throw new Error(o)}}}class q{constructor(e){n(this,"params");n(this,"transport");this.params=e,this.transport=new j(e.apiUrl)}async log({scope:e,account:t,...r}){const o=m.v4(),{environment:a,service:i}=this.params,c=Math.floor(Date.now()/1e3),l={...r,...t,service:i,id:o,environment:a,timestamp:c,...e&&{scope:e}};await this.transport.create(l)}}exports.AuditLogger=q;
package/dist/index.mjs CHANGED
@@ -1,132 +1,149 @@
1
- var p = Object.defineProperty;
2
- var w = (s, t, e) => t in s ? p(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
3
- var i = (s, t, e) => (w(s, typeof t != "symbol" ? t + "" : t, e), e);
4
- import { v4 as v } from "uuid";
5
- import { createLogger as f, format as a, transports as E } from "winston";
6
- import { StatsD as _ } from "hot-shots";
7
- import { SQSClient as S, SendMessageCommand as L } from "@aws-sdk/client-sqs";
8
- const y = "audit-logs", A = "@payfit/audit-log", D = () => {
9
- const s = process.env.LOG_LEVEL;
10
- return s && s.trim() !== "" ? s.trim() : "info";
11
- }, M = (s, t) => f({
12
- level: D(),
13
- silent: process.env.NODE_ENV === "test",
14
- exitOnError: !1,
15
- defaultMeta: {
16
- namespace: y,
17
- sdk: A,
18
- service: s,
19
- environment: t
20
- },
21
- format: a.combine(a.timestamp(), a.errors({ stack: !0 }), a.json()),
22
- transports: [new E.Console()]
23
- }), U = "payfit.audit-logs.", d = (s) => Object.entries(s).filter(([, t]) => t !== void 0 && t !== "").map(([t, e]) => `${t}:${String(e)}`);
24
- class q {
25
- constructor() {
26
- i(this, "client");
27
- this.client = new _({
28
- prefix: U,
29
- // Loss of metrics never breaks the caller — DogStatsD UDP is best-effort by design.
30
- errorHandler: () => {
31
- },
32
- cacheDns: !0
33
- });
34
- }
35
- increment(t, e) {
36
- this.client.increment(t, 1, d(e));
1
+ var u = Object.defineProperty;
2
+ var P = (s, e, t) => e in s ? u(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var n = (s, e, t) => (P(s, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import { v4 as m } from "uuid";
5
+ import l from "axios";
6
+ const p = "http://localhost:8090".replace(/\/+$/, "");
7
+ class f {
8
+ constructor(e, t = p, o = l) {
9
+ n(this, "basePath");
10
+ n(this, "axios");
11
+ n(this, "configuration");
12
+ this.basePath = t, this.axios = o, e && (this.configuration = e, this.basePath = e.basePath || this.basePath);
37
13
  }
38
- histogram(t, e, n) {
39
- this.client.histogram(t, e, d(n));
40
- }
41
- async close() {
42
- await new Promise((t) => {
43
- this.client.close(() => t());
44
- });
14
+ }
15
+ class A extends Error {
16
+ constructor(t, o) {
17
+ super(o);
18
+ n(this, "field");
19
+ n(this, "name", "RequiredError");
20
+ this.field = t;
45
21
  }
46
22
  }
47
- const C = () => new q(), N = "eu-west-3", O = {
48
- dev: "https://sqs.eu-west-3.amazonaws.com/533547282673/audit-logs-ingest",
49
- staging: "https://sqs.eu-west-3.amazonaws.com/589883667243/audit-logs-ingest",
50
- prod: "https://sqs.eu-west-3.amazonaws.com/614948436281/audit-logs-ingest"
51
- }, z = {
52
- working: "staging",
53
- production: "prod"
23
+ const w = "https://example.com", x = function(s, e, t) {
24
+ if (t == null)
25
+ throw new A(e, `Required parameter ${e} was null or undefined when calling ${s}.`);
26
+ }, g = function(s, ...e) {
27
+ const t = new URLSearchParams(s.search);
28
+ for (const o of e)
29
+ for (const r in o)
30
+ if (Array.isArray(o[r])) {
31
+ t.delete(r);
32
+ for (const a of o[r])
33
+ t.append(r, a);
34
+ } else
35
+ t.set(r, o[r]);
36
+ s.search = t.toString();
37
+ }, b = function(s, e, t) {
38
+ const o = typeof s != "string";
39
+ return (o && t && t.isJsonMime ? t.isJsonMime(e.headers["Content-Type"]) : o) ? JSON.stringify(s !== void 0 ? s : {}) : s || "";
40
+ }, y = function(s) {
41
+ return s.pathname + s.search + s.hash;
42
+ }, E = function(s, e, t, o) {
43
+ return (r = e, a = t) => {
44
+ const i = { ...s.options, url: ((o == null ? void 0 : o.basePath) || a) + s.url };
45
+ return r.request(i);
46
+ };
47
+ }, L = function(s) {
48
+ return {
49
+ /**
50
+ *
51
+ * @summary Creates Audit Log event
52
+ * @param {InlineObject} inlineObject
53
+ * @param {*} [options] Override http request option.
54
+ * @throws {RequiredError}
55
+ */
56
+ v1LogPost: async (e, t = {}) => {
57
+ x("v1LogPost", "inlineObject", e);
58
+ const o = "/v1/log", r = new URL(o, w);
59
+ let a;
60
+ s && (a = s.baseOptions);
61
+ const i = { method: "POST", ...a, ...t }, c = {}, h = {};
62
+ c["Content-Type"] = "application/json", g(r, h);
63
+ let d = a && a.headers ? a.headers : {};
64
+ return i.headers = { ...c, ...d, ...t.headers }, i.data = b(e, i, s), {
65
+ url: y(r),
66
+ options: i
67
+ };
68
+ }
69
+ };
70
+ }, S = function(s) {
71
+ const e = L(s);
72
+ return {
73
+ /**
74
+ *
75
+ * @summary Creates Audit Log event
76
+ * @param {InlineObject} inlineObject
77
+ * @param {*} [options] Override http request option.
78
+ * @throws {RequiredError}
79
+ */
80
+ async v1LogPost(t, o) {
81
+ const r = await e.v1LogPost(t, o);
82
+ return E(r, l, p, s);
83
+ }
84
+ };
54
85
  };
55
- class R {
56
- constructor(t) {
57
- i(this, "environment");
58
- i(this, "client");
59
- i(this, "queueUrl");
60
- this.environment = t;
61
- const e = z[t] ?? t, n = O[e];
62
- if (!n)
63
- throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${t}"`);
64
- this.queueUrl = n, this.client = new S({ region: N });
65
- }
66
- async create(t) {
67
- await this.client.send(new L({
68
- QueueUrl: this.queueUrl,
69
- MessageBody: JSON.stringify(t)
70
- }));
86
+ class v extends f {
87
+ /**
88
+ *
89
+ * @summary Creates Audit Log event
90
+ * @param {InlineObject} inlineObject
91
+ * @param {*} [options] Override http request option.
92
+ * @throws {RequiredError}
93
+ * @memberof DefaultApi
94
+ */
95
+ v1LogPost(e, t) {
96
+ return S(this.configuration).v1LogPost(e, t).then((o) => o(this.axios, this.basePath));
71
97
  }
72
98
  }
73
- class x {
74
- constructor(t, e = {}) {
75
- i(this, "params");
76
- i(this, "transport");
77
- i(this, "logger");
78
- i(this, "metrics");
79
- this.params = t, this.transport = e.transport ?? new R(t.environment), this.logger = e.logger ?? M(t.service, t.environment), this.metrics = e.metrics ?? C();
99
+ const R = (s) => "isAxiosError" in s && s.isAxiosError && s instanceof Error;
100
+ class U {
101
+ constructor(e) {
102
+ n(this, "apiUrl");
103
+ n(this, "api");
104
+ this.apiUrl = e, this.api = new v({
105
+ basePath: this.apiUrl,
106
+ isJsonMime(t) {
107
+ const o = new RegExp(
108
+ // eslint-disable-next-line no-control-regex
109
+ "^(application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(;.*)?$",
110
+ "i"
111
+ );
112
+ return t !== null && (o.test(t) || t.toLowerCase() === "application/json-patch+json");
113
+ }
114
+ });
80
115
  }
81
- async log({ scope: t, account: e, ...n }) {
82
- const u = v(), { environment: c, service: g } = this.params, r = {
83
- ...n,
84
- ...e,
85
- service: g,
86
- id: u,
87
- environment: c,
88
- ...t && { scope: t }
89
- }, o = {
90
- service: g,
91
- environment: c,
92
- namespace: r.namespace,
93
- event: r.event,
94
- target: r.target
95
- }, l = Date.now();
116
+ async create(e) {
117
+ var t;
96
118
  try {
97
- await this.transport.create(r), this.metrics.increment("sent", o), this.metrics.histogram("send_duration_ms", Date.now() - l, o), this.logger.debug("audit-log sent", {
98
- id: r.id,
99
- event: r.event,
100
- target: r.target
101
- });
102
- } catch (h) {
103
- this.metrics.increment("send_failed", o), this.metrics.histogram("send_duration_ms", Date.now() - l, o);
104
- const m = h.message;
105
- try {
106
- this.logger.error("audit-log write failed", {
107
- audit_log: r,
108
- error: m
109
- });
110
- } catch {
111
- this.metrics.increment("serialization_failed", o);
112
- try {
113
- this.logger.error("audit-log write failed (serialization failed)", {
114
- audit_log_meta: {
115
- id: r.id,
116
- service: r.service,
117
- environment: r.environment,
118
- namespace: r.namespace,
119
- event: r.event,
120
- target: r.target
121
- },
122
- error: m
123
- });
124
- } catch {
125
- }
126
- }
119
+ await this.api.v1LogPost(e, { timeout: 5e3 });
120
+ } catch (o) {
121
+ if (!R(o))
122
+ throw o;
123
+ const r = ((t = o.response) == null ? void 0 : t.data) || o.message;
124
+ throw new Error(r);
127
125
  }
128
126
  }
129
127
  }
128
+ class O {
129
+ constructor(e) {
130
+ n(this, "params");
131
+ n(this, "transport");
132
+ this.params = e, this.transport = new U(e.apiUrl);
133
+ }
134
+ async log({ scope: e, account: t, ...o }) {
135
+ const r = m(), { environment: a, service: i } = this.params, c = Math.floor(Date.now() / 1e3), h = {
136
+ ...o,
137
+ ...t,
138
+ service: i,
139
+ id: r,
140
+ environment: a,
141
+ timestamp: c,
142
+ ...e && { scope: e }
143
+ };
144
+ await this.transport.create(h);
145
+ }
146
+ }
130
147
  export {
131
- x as AuditLogger
148
+ O as AuditLogger
132
149
  };
@@ -1,8 +1,8 @@
1
- import { IAuditLogCreationData, IAuditLogTransport } from './interface';
1
+ import { InlineObject } from './generated/model';
2
+ import { IAuditLogTransport } from './interface';
2
3
  export declare class Transport implements IAuditLogTransport {
3
- protected environment: string;
4
- private client;
5
- private queueUrl;
6
- constructor(environment: string);
7
- create(auditLogData: IAuditLogCreationData): Promise<void>;
4
+ protected apiUrl: string;
5
+ private api;
6
+ constructor(apiUrl: string);
7
+ create(auditLogData: InlineObject): Promise<void>;
8
8
  }
@@ -1,5 +1,6 @@
1
1
  export interface IAuditLogCreationData {
2
2
  id: string;
3
+ timestamp: number;
3
4
  environment: string;
4
5
  service: string;
5
6
  scope?: Record<string, unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payfit/audit-log",
3
- "version": "3.5.0-rc.18",
3
+ "version": "3.5.0-rc.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/PayFit/audit-logs.git",
@@ -15,8 +15,6 @@
15
15
  "build": "rimraf dist && vite build",
16
16
  "prepack": "npm run build",
17
17
  "lint": "eslint .",
18
- "test": "vitest run",
19
- "test:watch": "vitest",
20
18
  "start:playground": "ts-node src/playground.ts",
21
19
  "format:check": "prettier --check .",
22
20
  "format:fix": "prettier --write .",
@@ -25,12 +23,9 @@
25
23
  "author": "",
26
24
  "license": "ISC",
27
25
  "dependencies": {
28
- "@aws-sdk/client-sqs": "^3.600.0",
29
26
  "axios": "^1.0.0",
30
- "hot-shots": "^11.0.0",
31
27
  "lodash": "^4.17.20",
32
- "uuid": "^9.0.0",
33
- "winston": "^3.13.0"
28
+ "uuid": "^9.0.0"
34
29
  },
35
30
  "devDependencies": {
36
31
  "@openapitools/openapi-generator-cli": "2.7.0",
@@ -51,14 +46,13 @@
51
46
  "semantic-release": "22.0.12",
52
47
  "ts-node": "10.9.2",
53
48
  "typescript": "5.3.3",
54
- "vite": "4.5.1",
55
- "vitest": "4.1.4"
49
+ "vite": "4.5.1"
56
50
  },
51
+ "peerDependencies": {},
57
52
  "publishConfig": {
58
53
  "registry": "https://registry.npmjs.org/"
59
54
  },
60
55
  "files": [
61
56
  "dist"
62
- ],
63
- "packageManager": "yarn@4.14.1+sha512.64df448055b2d37ba269d7db535a469b8da93f8ef1140c25fd7a83c00a8fbaacb214ca0e02553b92a2c54cef78bb67d0b4817fab02001df0e24fac0faccc3b42"
57
+ ]
64
58
  }
@@ -1 +0,0 @@
1
- export {};
package/dist/logger.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { type Logger } from 'winston';
2
- export declare const createSdkLogger: (service: string, environment: string) => Logger;
@@ -1 +0,0 @@
1
- export {};
package/dist/metrics.d.ts DELETED
@@ -1,15 +0,0 @@
1
- export declare const METRIC_PREFIX = "payfit.audit-logs.";
2
- export type MetricName = 'sent' | 'send_failed' | 'serialization_failed' | 'send_duration_ms';
3
- export interface MetricTags {
4
- service: string;
5
- environment: string;
6
- namespace?: string;
7
- event?: string;
8
- target?: string;
9
- }
10
- export interface IMetricsClient {
11
- increment(name: MetricName, tags: MetricTags): void;
12
- histogram(name: MetricName, value: number, tags: MetricTags): void;
13
- close(): Promise<void>;
14
- }
15
- export declare const createMetricsClient: () => IMetricsClient;
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};