@mhmdhammoud/meritt-utils 1.6.1 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ReleaseNotes.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changes
2
2
 
3
+ ## Version 1.6.3
4
+
5
+ ### Elasticsearch Proxy Logging Fix
6
+
7
+ - Disabled Elasticsearch node sniffing by default. Sniffing is unsafe when the
8
+ configured endpoint is an HTTPS proxy because discovered nodes may advertise
9
+ internal addresses or a different protocol.
10
+ - Preserved explicit opt-in through `sniffOnConnectionFault: true` for direct
11
+ multi-node Elasticsearch deployments.
12
+ - Sanitized dots and whitespace from recursive context field names.
13
+ - Replaced empty context field names with `unnamed_field`.
14
+ - Added regression coverage for proxy-safe transport configuration and context
15
+ field sanitization.
16
+
3
17
  ## Version 1.5.3
4
18
 
5
19
  ### Logger Improvements - Critical Bug Fixes & Production Reliability
@@ -34,7 +48,9 @@
34
48
  - Handles `SIGTERM` and `SIGINT` signals
35
49
  - 5-second timeout prevents hanging forever
36
50
  - Proper async/await handling to ensure flush completes
37
- - **Auto-reconnection**: `sniffOnConnectionFault: true` enables automatic reconnection when Elasticsearch nodes fail
51
+ - **Node discovery**: `sniffOnConnectionFault` is available for direct
52
+ multi-node Elasticsearch deployments. It should remain disabled behind a
53
+ proxy because discovered node addresses may not be externally reachable.
38
54
  - **Retry logic**: Configurable retry attempts with timeout for failed requests
39
55
 
40
56
  #### Type Safety
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const elastic_transport_1 = require("../lib/elastic-transport");
4
+ const elasticsearch_1 = require("@elastic/elasticsearch");
5
+ jest.mock('@elastic/elasticsearch', () => ({
6
+ Client: jest.fn(),
7
+ }));
8
+ const MockedClient = elasticsearch_1.Client;
9
+ const writeLog = (transport, doc) => transport.write(`${JSON.stringify(doc)}\n`);
10
+ const waitForEvent = (emitter, eventName) => new Promise((resolve) => {
11
+ emitter.once(eventName, (value) => resolve(value));
12
+ });
13
+ describe('elastic transport resilience', () => {
14
+ beforeEach(() => {
15
+ jest.useRealTimers();
16
+ MockedClient.mockReset();
17
+ });
18
+ test('disables node sniffing by default', () => {
19
+ MockedClient.mockImplementation(() => ({ bulk: jest.fn() }));
20
+ (0, elastic_transport_1.createElasticTransport)({ index: 'logs' });
21
+ expect(MockedClient).toHaveBeenCalledWith(expect.objectContaining({ sniffOnConnectionFault: false }));
22
+ });
23
+ test('allows node sniffing only when explicitly enabled', () => {
24
+ MockedClient.mockImplementation(() => ({ bulk: jest.fn() }));
25
+ (0, elastic_transport_1.createElasticTransport)({
26
+ index: 'logs',
27
+ sniffOnConnectionFault: true,
28
+ });
29
+ expect(MockedClient).toHaveBeenCalledWith(expect.objectContaining({ sniffOnConnectionFault: true }));
30
+ });
31
+ test('reports bulk failures without emitting terminal stream errors', async () => {
32
+ const bulk = jest
33
+ .fn()
34
+ .mockRejectedValueOnce(new Error('ES unavailable'))
35
+ .mockResolvedValueOnce({ errors: false, items: [] });
36
+ MockedClient.mockImplementation(() => ({ bulk }));
37
+ const transport = (0, elastic_transport_1.createElasticTransport)({
38
+ index: 'logs',
39
+ flushBytes: 1,
40
+ flushInterval: 10000,
41
+ requestTimeout: 10,
42
+ });
43
+ const streamError = jest.fn();
44
+ transport.on('error', streamError);
45
+ const failed = waitForEvent(transport, 'bulkError');
46
+ writeLog(transport, { message: 'first' });
47
+ await failed;
48
+ const inserted = waitForEvent(transport, 'insert');
49
+ writeLog(transport, { message: 'second' });
50
+ await expect(inserted).resolves.toEqual({ successful: 1, failed: 0 });
51
+ expect(streamError).not.toHaveBeenCalled();
52
+ expect(bulk).toHaveBeenCalledTimes(2);
53
+ });
54
+ test('watchdog releases a stuck bulk request so later logs can flush', async () => {
55
+ jest.useFakeTimers();
56
+ const bulk = jest
57
+ .fn()
58
+ .mockReturnValueOnce(new Promise(() => undefined))
59
+ .mockResolvedValueOnce({ errors: false, items: [] });
60
+ MockedClient.mockImplementation(() => ({ bulk }));
61
+ const transport = (0, elastic_transport_1.createElasticTransport)({
62
+ index: 'logs',
63
+ flushBytes: 1,
64
+ flushInterval: 10000,
65
+ requestTimeout: 1,
66
+ });
67
+ const timedOut = waitForEvent(transport, 'bulkError');
68
+ writeLog(transport, { message: 'stuck' });
69
+ await jest.advanceTimersByTimeAsync(5001);
70
+ await expect(timedOut).resolves.toMatchObject({
71
+ message: 'Elasticsearch bulk request timed out after 5001ms',
72
+ });
73
+ const inserted = waitForEvent(transport, 'insert');
74
+ writeLog(transport, { message: 'recovered' });
75
+ await expect(inserted).resolves.toEqual({ successful: 1, failed: 0 });
76
+ expect(bulk).toHaveBeenCalledTimes(2);
77
+ });
78
+ });
@@ -132,4 +132,25 @@ describe('route and format logs', () => {
132
132
  _id: expect.anything(),
133
133
  }));
134
134
  });
135
+ test('sanitize empty, dotted, and whitespace context field names', () => {
136
+ //@ts-ignore
137
+ jest.spyOn(pino_1.pino, 'destination').mockReturnValue(PINO_DESTINATION);
138
+ //@ts-ignore
139
+ pino_1.pino.mockReturnValue(PINO);
140
+ const logger = new logger_1.default(LOGGER_NAME);
141
+ logger.info(LOG_EVENT, {
142
+ '': 'empty',
143
+ 'field.with.dots': 'dotted',
144
+ ' field name ': 'spaced',
145
+ nested: { ' ': 'nested-empty' },
146
+ });
147
+ expect(PINO.info).toHaveBeenCalledWith(expect.objectContaining({
148
+ context: {
149
+ unnamed_field: 'empty',
150
+ fieldwithdots: 'dotted',
151
+ fieldname: 'spaced',
152
+ nested: { unnamed_field: 'nested-empty' },
153
+ },
154
+ }));
155
+ });
135
156
  });
@@ -24,4 +24,8 @@ export interface ElasticTransportOptions extends Pick<ClientOptions, 'node' | 'a
24
24
  rejectUnauthorized?: boolean;
25
25
  tls?: ClientOptions['tls'];
26
26
  }
27
- export declare const createElasticTransport: (opts?: ElasticTransportOptions) => NodeJS.ReadWriteStream;
27
+ export interface ElasticTransportStream extends NodeJS.ReadWriteStream {
28
+ flush: () => Promise<void>;
29
+ close: () => Promise<void>;
30
+ }
31
+ export declare const createElasticTransport: (opts?: ElasticTransportOptions) => ElasticTransportStream;
@@ -17,6 +17,7 @@ exports.createElasticTransport = void 0;
17
17
  // eslint-disable-next-line @typescript-eslint/no-require-imports
18
18
  const split = require('split2');
19
19
  const elasticsearch_1 = require("@elastic/elasticsearch");
20
+ const createTimeoutError = (timeoutMs) => new Error(`Elasticsearch bulk request timed out after ${timeoutMs}ms`);
20
21
  function setDateTimeString(value) {
21
22
  if (value !== null && typeof value === 'object' && 'time' in value) {
22
23
  const t = value.time;
@@ -34,13 +35,15 @@ function getIndexName(index, time) {
34
35
  return index.replace('%{DATE}', time.substring(0, 10));
35
36
  }
36
37
  function createBulkSender(opts, client, splitter) {
37
- var _a, _b, _c, _d, _e, _f, _g;
38
+ var _a, _b, _c, _d, _e, _f, _g, _h;
38
39
  const esVersion = Number((_b = (_a = opts.esVersion) !== null && _a !== void 0 ? _a : opts['es-version']) !== null && _b !== void 0 ? _b : 7);
39
40
  const index = (_c = opts.index) !== null && _c !== void 0 ? _c : 'pino';
40
41
  const buildIndexName = typeof index === 'function' ? index : null;
41
42
  const opType = esVersion >= 7 ? undefined : undefined;
42
43
  const flushBytes = (_e = (_d = opts.flushBytes) !== null && _d !== void 0 ? _d : opts['flush-bytes']) !== null && _e !== void 0 ? _e : 1000;
43
44
  const flushInterval = (_g = (_f = opts.flushInterval) !== null && _f !== void 0 ? _f : opts['flush-interval']) !== null && _g !== void 0 ? _g : 3000;
45
+ const requestTimeout = (_h = opts.requestTimeout) !== null && _h !== void 0 ? _h : 30000;
46
+ const bulkWatchdogTimeout = requestTimeout + 5000;
44
47
  let buffer = [];
45
48
  let bufferedBytes = 0;
46
49
  let timer;
@@ -100,6 +103,40 @@ function createBulkSender(opts, client, splitter) {
100
103
  error.cause = cause;
101
104
  splitter.emit('insertError', error);
102
105
  };
106
+ const emitBulkError = (err) => {
107
+ // Do not emit the standard stream "error" event for retryable bulk
108
+ // failures. Some stream consumers treat it as terminal, which can leave
109
+ // Pino writing into a poisoned stream while the process continues running.
110
+ splitter.emit('bulkError', err);
111
+ };
112
+ const bulkWithWatchdog = async (operations) => {
113
+ let timeout;
114
+ const bulkPromise = client.bulk({
115
+ operations,
116
+ refresh: false,
117
+ timeout: `${requestTimeout}ms`,
118
+ });
119
+ try {
120
+ return await Promise.race([
121
+ bulkPromise,
122
+ new Promise((_, reject) => {
123
+ var _a;
124
+ timeout = setTimeout(() => {
125
+ reject(createTimeoutError(bulkWatchdogTimeout));
126
+ }, bulkWatchdogTimeout);
127
+ (_a = timeout.unref) === null || _a === void 0 ? void 0 : _a.call(timeout);
128
+ }),
129
+ ]);
130
+ }
131
+ finally {
132
+ if (timeout) {
133
+ clearTimeout(timeout);
134
+ }
135
+ // If the watchdog wins, the original request may reject later. Consume
136
+ // that rejection so a stale request cannot crash the app.
137
+ bulkPromise.catch(() => undefined);
138
+ }
139
+ };
103
140
  const flush = async () => {
104
141
  var _a, _b;
105
142
  if (isFlushing) {
@@ -116,12 +153,7 @@ function createBulkSender(opts, client, splitter) {
116
153
  bufferedBytes = 0;
117
154
  try {
118
155
  const operations = batch.flatMap(buildOperation);
119
- const response = await client.bulk({
120
- operations,
121
- refresh: false,
122
- timeout: opts.requestTimeout ? `${opts.requestTimeout}ms` : undefined,
123
- });
124
- const body = response;
156
+ const body = await bulkWithWatchdog(operations);
125
157
  if (body.errors && Array.isArray(body.items)) {
126
158
  body.items.forEach((item, index) => {
127
159
  const result = Object.values(item)[0];
@@ -132,11 +164,13 @@ function createBulkSender(opts, client, splitter) {
132
164
  }
133
165
  splitter.emit('insert', {
134
166
  successful: batch.length,
135
- failed: body.errors ? ((_b = (_a = body.items) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) : 0,
167
+ failed: body.errors
168
+ ? ((_b = (_a = body.items) === null || _a === void 0 ? void 0 : _a.filter((item) => { var _a; return (_a = Object.values(item)[0]) === null || _a === void 0 ? void 0 : _a.error; }).length) !== null && _b !== void 0 ? _b : 0)
169
+ : 0,
136
170
  });
137
171
  }
138
172
  catch (err) {
139
- splitter.emit('error', err);
173
+ emitBulkError(err);
140
174
  // Drop the failed batch instead of wedging the stream. The next log line
141
175
  // creates a fresh bulk request and can recover without a process restart.
142
176
  batch.forEach((doc) => emitDroppedDocument(doc, err));
@@ -170,6 +204,7 @@ function createBulkSender(opts, client, splitter) {
170
204
  };
171
205
  }
172
206
  const createElasticTransport = (opts = {}) => {
207
+ var _a;
173
208
  const splitter = split(function (line) {
174
209
  let value;
175
210
  try {
@@ -206,7 +241,8 @@ const createElasticTransport = (opts = {}) => {
206
241
  tls: { rejectUnauthorized: opts.rejectUnauthorized, ...opts.tls },
207
242
  maxRetries: opts.maxRetries,
208
243
  requestTimeout: opts.requestTimeout,
209
- sniffOnConnectionFault: opts.sniffOnConnectionFault,
244
+ // Keep the configured proxy endpoint unless callers explicitly opt in.
245
+ sniffOnConnectionFault: (_a = opts.sniffOnConnectionFault) !== null && _a !== void 0 ? _a : false,
210
246
  };
211
247
  if (opts.caFingerprint) {
212
248
  clientOpts.caFingerprint = opts.caFingerprint;
@@ -226,11 +262,13 @@ const createElasticTransport = (opts = {}) => {
226
262
  void bulkSender.close();
227
263
  });
228
264
  const splitterWithDestroy = splitter;
265
+ splitterWithDestroy.flush = bulkSender.flush;
266
+ splitterWithDestroy.close = bulkSender.close;
229
267
  const originalDestroy = splitterWithDestroy.destroy.bind(splitterWithDestroy);
230
268
  splitterWithDestroy.destroy = function (err) {
231
269
  void bulkSender.close();
232
270
  originalDestroy(err);
233
271
  };
234
- return splitter;
272
+ return splitterWithDestroy;
235
273
  };
236
274
  exports.createElasticTransport = createElasticTransport;
@@ -59,7 +59,8 @@ const RESERVED_ES_FIELD_ALIASES = {
59
59
  };
60
60
  /** Convert arbitrary field names into ES-safe flattened keys */
61
61
  const toSafeElasticFieldName = (key) => {
62
- const normalized = toSnakeCase(key);
62
+ const cleaned = key.replace(/[.\s]+/g, '');
63
+ const normalized = toSnakeCase(cleaned) || 'unnamed_field';
63
64
  const mapped = RESERVED_ES_FIELD_ALIASES[normalized];
64
65
  if (mapped) {
65
66
  return mapped;
@@ -219,8 +220,12 @@ function registerShutdownHandlers() {
219
220
  clearTimeout(timeout);
220
221
  resolve();
221
222
  });
222
- // Now trigger the flush
223
- esTransport === null || esTransport === void 0 ? void 0 : esTransport.end();
223
+ esTransport === null || esTransport === void 0 ? void 0 : esTransport.flush().catch((error) => {
224
+ console.error(`[Logger] Error flushing logs on ${signal}:`, error);
225
+ }).finally(() => {
226
+ // Now trigger stream shutdown
227
+ esTransport === null || esTransport === void 0 ? void 0 : esTransport.end();
228
+ });
224
229
  });
225
230
  }
226
231
  catch (error) {
@@ -286,8 +291,8 @@ function getLogger(elasticConfig) {
286
291
  // Retry configuration for connection resilience
287
292
  maxRetries: maxRetries,
288
293
  requestTimeout: requestTimeout,
289
- // Automatically reconnect on connection faults
290
- sniffOnConnectionFault: true,
294
+ // Sniffing can bypass proxies and discover unreachable internal nodes.
295
+ sniffOnConnectionFault: false,
291
296
  };
292
297
  if (elasticConfig) {
293
298
  Object.assign(esConfig, elasticConfig);
@@ -295,7 +300,7 @@ function getLogger(elasticConfig) {
295
300
  // Create transport with connection lifecycle fix (pino-elasticsearch #140)
296
301
  esTransport = (0, elastic_transport_1.createElasticTransport)(esConfig);
297
302
  // Handle Elasticsearch connection errors
298
- esTransport.on('error', (err) => {
303
+ esTransport.on('bulkError', (err) => {
299
304
  console.error('[Logger] Elasticsearch transport error:', err.message);
300
305
  console.error('[Logger] Logs may not be reaching Kibana. Check Elasticsearch connection.');
301
306
  });
@@ -58,7 +58,8 @@ export interface ElasticConfig {
58
58
  requestTimeout?: number;
59
59
  /**
60
60
  * Whether to sniff for additional Elasticsearch nodes on connection fault.
61
- * Enables automatic reconnection when a node fails.
61
+ * Defaults to false because sniffing can bypass a proxy and discover
62
+ * internal node addresses that are unreachable or use a different protocol.
62
63
  */
63
64
  sniffOnConnectionFault?: boolean;
64
65
  }
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "@mhmdhammoud/meritt-utils",
3
- "version": "1.6.1",
3
+ "version": "1.6.3",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "private": false,
7
7
  "typings": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "imagesloaded.d.ts",
11
+ "README.md",
12
+ "ReleaseNotes.md"
13
+ ],
8
14
  "repository": {
9
15
  "type": "git",
10
- "url": "git@github.com:Mhmdhammoud/meritt-utils.git"
16
+ "url": "git+ssh://git@github.com/Mhmdhammoud/meritt-utils.git"
11
17
  },
12
18
  "publishConfig": {
13
19
  "access": "public"
@@ -18,7 +24,7 @@
18
24
  "watch": "tsc --watch",
19
25
  "build": "tsc",
20
26
  "test:types": "tsc --noemit",
21
- "prepare": "husky install",
27
+ "prepare": "husky",
22
28
  "lint": "eslint src --fix",
23
29
  "prepublish": "npm run build",
24
30
  "test": "jest",
@@ -1,84 +0,0 @@
1
- name: NPM Publish on Release
2
-
3
- on:
4
- push:
5
- branches: [master]
6
-
7
- jobs:
8
- test:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - name: Checkout code
12
- uses: actions/checkout@v4
13
-
14
- - name: Setup Node.js
15
- uses: actions/setup-node@v4
16
- with:
17
- node-version: '20'
18
- cache: 'npm'
19
-
20
- - name: Install dependencies
21
- run: npm ci
22
-
23
- - name: Run type check
24
- run: npm run test:types
25
-
26
- - name: Run linting
27
- run: npm run lint
28
-
29
- - name: Run tests
30
- run: npm test
31
-
32
- build:
33
- needs: test
34
- runs-on: ubuntu-latest
35
- steps:
36
- - name: Checkout code
37
- uses: actions/checkout@v4
38
-
39
- - name: Setup Node.js
40
- uses: actions/setup-node@v4
41
- with:
42
- node-version: '20'
43
- cache: 'npm'
44
-
45
- - name: Install dependencies
46
- run: npm ci
47
-
48
- - name: Build project
49
- run: npm run build
50
-
51
- - name: Upload build artifacts
52
- uses: actions/upload-artifact@v4
53
- with:
54
- name: dist
55
- path: dist/
56
-
57
- publish-npm:
58
- needs: [test, build]
59
- runs-on: ubuntu-latest
60
- if: success()
61
- steps:
62
- - name: Checkout code
63
- uses: actions/checkout@v4
64
-
65
- - name: Setup Node.js
66
- uses: actions/setup-node@v4
67
- with:
68
- node-version: '20'
69
- registry-url: https://registry.npmjs.org/
70
- cache: 'npm'
71
-
72
- - name: Install dependencies
73
- run: npm ci
74
-
75
- - name: Download build artifacts
76
- uses: actions/download-artifact@v4
77
- with:
78
- name: dist
79
- path: dist/
80
-
81
- - name: Publish to NPM
82
- run: npm publish
83
- env:
84
- NODE_AUTH_TOKEN: ${{ secrets.npm_token }}
@@ -1,83 +0,0 @@
1
- name: CI Pipeline
2
-
3
- on:
4
- push:
5
- branches: [dev]
6
- pull_request:
7
- branches: [dev, master]
8
-
9
- jobs:
10
- lint-and-test:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - name: Checkout code
14
- uses: actions/checkout@v4
15
-
16
- - name: Setup Node.js
17
- uses: actions/setup-node@v4
18
- with:
19
- node-version: '20'
20
- cache: 'npm'
21
-
22
- - name: Install dependencies
23
- run: npm ci
24
-
25
- - name: Run type check
26
- run: npm run test:types
27
-
28
- - name: Run linting
29
- run: npm run lint
30
-
31
- - name: Run tests with coverage
32
- run: npm run test:coverage
33
-
34
- - name: Upload coverage reports
35
- uses: actions/upload-artifact@v4
36
- if: always()
37
- with:
38
- name: coverage-report
39
- path: coverage/
40
-
41
- build:
42
- needs: lint-and-test
43
- runs-on: ubuntu-latest
44
- steps:
45
- - name: Checkout code
46
- uses: actions/checkout@v4
47
-
48
- - name: Setup Node.js
49
- uses: actions/setup-node@v4
50
- with:
51
- node-version: '20'
52
- cache: 'npm'
53
-
54
- - name: Install dependencies
55
- run: npm ci
56
-
57
- - name: Build project
58
- run: npm run build
59
-
60
- - name: Upload build artifacts
61
- uses: actions/upload-artifact@v4
62
- with:
63
- name: dist
64
- path: dist/
65
-
66
- security-audit:
67
- runs-on: ubuntu-latest
68
- steps:
69
- - name: Checkout code
70
- uses: actions/checkout@v4
71
-
72
- - name: Setup Node.js
73
- uses: actions/setup-node@v4
74
- with:
75
- node-version: '20'
76
- cache: 'npm'
77
-
78
- - name: Install dependencies
79
- run: npm ci
80
-
81
- - name: Run security audit
82
- run: npm audit --audit-level=moderate
83
-
package/.husky/pre-commit DELETED
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env sh
2
- . "$(dirname -- "$0")/_/husky.sh"
3
-
4
- red='\033[0;31m'
5
- green='\033[0;32m'
6
- yellow='\033[0;33m'
7
- blue='\033[0;34m'
8
- magenta='\033[0;35m'
9
- cyan='\033[0;36m'
10
- clear='\033[0m'
11
- echo "
12
-
13
- __ __ ______ _____ _____ _______ _______ _____ ________ __
14
- | \/ | ____| __ \|_ _|__ __|__ __| | __ \| ____\ \ / /
15
- | \ / | |__ | |__) | | | | | | | | | | | |__ \ \ / /
16
- | |\/| | __| | _ / | | | | | | | | | | __| \ \/ /
17
- | | | | |____| | \ \ _| |_ | | | | | |__| | |____ \ /
18
- |_| |_|______|_| \_\_____| |_| |_| |_____/|______| \/
19
-
20
-
21
- "
22
- echo -e "Let's hope you are not ${red}DUMB${clear}!"
23
-
24
- echo -ne '\n'
25
-
26
- echo -e "${yellow}Or Are You ??${clear}!"
27
- echo -ne '\n'
28
- echo -e "${yellow}Running pre-commit hook...${clear}"
29
- echo -ne '\n'
30
- echo -ne '\n'
31
-
32
- echo -ne '##################### (25%)\r'
33
- sleep 0.3
34
- echo -ne '############################## (35%)\r'
35
- sleep 0.3
36
- echo -ne '###################################### (45%)\r'
37
- sleep 0.3
38
- echo -ne '############################################################ (77%)\r'
39
- sleep 0.3
40
- echo -ne '################################################################## (100%)\r'
41
-
42
- echo -ne '\n'
43
- echo -ne '\n'
44
- echo -ne '\n'
45
-
46
- echo -e "${yellow}Running types...${clear}"
47
- echo -ne '\n'
48
- npm run test:types
49
- echo -ne '\n'
50
-
51
- echo -e "${green}types passed...${clear} ✅"
52
- echo -ne '\n'
53
- echo -e "${yellow}Running linting...${clear}"
54
-
55
- npm run lint
56
- echo -e "${green}linting passed...${clear} ✅"
57
-
58
- echo -ne '\n'
59
-
60
- echo -e "${yellow}Seems like you are a${clear} ${green}CLEVER DEVELOPER${clear} 👌"
61
- echo -ne '\n'
62
- echo -e "${green}GOOD TO GO${clear} 🚀🚀🚀"
package/.prettierrc DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "semi": false,
3
- "singleQuote": true,
4
- "trailingComma": "es5",
5
- "tabWidth": 2,
6
- "useTabs": true,
7
- "printWidth": 80
8
- }
package/.prettierrc.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "trailingComma": "es5",
3
- "tabWidth": 2,
4
- "semi": false,
5
- "singleQuote": true,
6
- "useTabs": true,
7
- "bracketSpacing": false
8
- }
package/ISSUES.md DELETED
File without changes
package/eslint.config.mjs DELETED
@@ -1,64 +0,0 @@
1
- // @ts-check
2
- import eslint from '@eslint/js'
3
- import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
4
- import globals from 'globals'
5
- import tseslint from 'typescript-eslint'
6
-
7
- export default tseslint.config(
8
- {
9
- ignores: [
10
- 'eslint.config.mjs',
11
- 'dist/**',
12
- 'node_modules/**',
13
- 'coverage/**',
14
- '*.d.ts',
15
- ],
16
- },
17
- eslint.configs.recommended,
18
- ...tseslint.configs.recommendedTypeChecked,
19
- eslintPluginPrettierRecommended,
20
- {
21
- languageOptions: {
22
- globals: {
23
- ...globals.node,
24
- },
25
- sourceType: 'module',
26
- parserOptions: {
27
- projectService: true,
28
- tsconfigRootDir: import.meta.dirname,
29
- },
30
- },
31
- },
32
- {
33
- rules: {
34
- '@typescript-eslint/no-explicit-any': 'off',
35
- '@typescript-eslint/no-floating-promises': 'warn',
36
- '@typescript-eslint/no-unsafe-argument': 'off',
37
- '@typescript-eslint/no-unsafe-assignment': 'off',
38
- '@typescript-eslint/no-unsafe-return': 'off',
39
- '@typescript-eslint/no-unsafe-member-access': 'off',
40
- '@typescript-eslint/no-unsafe-call': 'off',
41
- '@typescript-eslint/ban-ts-comment': 'off',
42
- '@typescript-eslint/require-await': 'off',
43
- '@typescript-eslint/await-thenable': 'off',
44
- '@typescript-eslint/no-unsafe-enum-comparison': 'off',
45
- '@typescript-eslint/no-base-to-string': 'off',
46
- '@typescript-eslint/no-redundant-type-constituents': 'off',
47
- '@typescript-eslint/no-unused-vars': [
48
- 'error',
49
- {
50
- argsIgnorePattern: '^_',
51
- varsIgnorePattern: '^_',
52
- },
53
- ],
54
- 'no-console': 'error',
55
- 'prettier/prettier': ['error', { semi: false }],
56
- },
57
- },
58
- {
59
- files: ['src/lib/logger.ts'],
60
- rules: {
61
- 'no-console': 'off',
62
- },
63
- }
64
- )