@codeleap/logger 6.8.0 → 7.0.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/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './lib';
2
+ export * from './types';
3
+ export * from './utils';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,82 @@
1
+ import { SlackService } from './Slack';
2
+ import { PerformanceService } from './performance';
3
+ /**
4
+ * Base logger class. Logging methods (`info`, `error`, `warn`, `log`, `debug`, `test`) are stubs
5
+ * that must be overridden by the consuming app — calling them before providing an implementation
6
+ * throws. Use {@link createLogger} to produce a concrete instance, then assign it to `logger`.
7
+ *
8
+ * `initialize` must be called once before `patchConsole` or any Slack/perf functionality works.
9
+ */
10
+ export class Logger {
11
+ isIgnored(args) {
12
+ if (!Logger.initialized)
13
+ return false;
14
+ const ignoreLogs = this.config.Logger.ignoreLogs;
15
+ return typeof args[0] === 'string' && ignoreLogs.some(w => args.join(' ').includes(w));
16
+ }
17
+ /**
18
+ * Monkey-patches `console.log`, `console.warn`, and `console.error` so that any message
19
+ * matching an entry in `config.Logger.ignoreLogs` is silently dropped.
20
+ *
21
+ * Call this after `initialize`. Patching before initialization has no effect because
22
+ * `isIgnored` returns `false` until the config is loaded.
23
+ */
24
+ patchConsole() {
25
+ const consoles = ['log', 'warn', 'error'];
26
+ consoles.forEach(level => {
27
+ const consoleAny = console;
28
+ const consoleRef = consoleAny[level].bind(console);
29
+ consoleAny[level] = (...args) => {
30
+ if (!this.isIgnored(args))
31
+ consoleRef(...args);
32
+ };
33
+ });
34
+ }
35
+ /**
36
+ * Bootstraps the logger with app-wide config. Safe to call multiple times — subsequent calls
37
+ * are no-ops. Also instantiates `slack` and `perf` sub-services, so they are only available
38
+ * after this method returns.
39
+ */
40
+ initialize(config) {
41
+ if (Logger.initialized)
42
+ return;
43
+ this.config = config;
44
+ this.slack = new SlackService(config);
45
+ this.perf = new PerformanceService(config);
46
+ Logger.initialized = true;
47
+ }
48
+ /**
49
+ * Stub — must be overridden. Intended for temporary test logs that should never reach
50
+ * production; implementations typically no-op in non-dev environments.
51
+ */
52
+ test(...args) {
53
+ throw new Error('Logger: implement the method "test"');
54
+ }
55
+ /** Stub — must be overridden. */
56
+ info(...args) {
57
+ throw new Error('Logger: implement the method "info"');
58
+ }
59
+ /** Stub — must be overridden. */
60
+ error(...args) {
61
+ throw new Error('Logger: implement the method "error"');
62
+ }
63
+ /** Stub — must be overridden. */
64
+ warn(...args) {
65
+ throw new Error('Logger: implement the method "warn"');
66
+ }
67
+ /** Stub — must be overridden. */
68
+ log(...args) {
69
+ throw new Error('Logger: implement the method "log"');
70
+ }
71
+ /** Stub — must be overridden. */
72
+ debug(...args) {
73
+ throw new Error('Logger: implement the method "debug"');
74
+ }
75
+ }
76
+ Logger.initialized = false;
77
+ /**
78
+ * Shared `Logger` instance. Logging methods throw until the consuming app replaces them via
79
+ * {@link createLogger} and calls {@link Logger.initialize}.
80
+ */
81
+ export const logger = new Logger();
82
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/lib/Logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD;;;;;;GAMG;AACH,MAAM,OAAO,MAAM;IAST,SAAS,CAAC,IAAe;QAC/B,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO,KAAK,CAAA;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAA;QAChD,OAAO,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACxF,CAAC;IAED;;;;;;OAMG;IACH,YAAY;QACV,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAU,CAAA;QAClD,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACvB,MAAM,UAAU,GAAG,OAAkE,CAAA;YACrF,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAClD,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;gBACzC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAAE,UAAU,CAAC,GAAG,IAAI,CAAC,CAAA;YAChD,CAAC,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAyB,MAAS;QAC1C,IAAI,MAAM,CAAC,WAAW;YAAE,OAAM;QAE9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QAGpB,IAAI,CAAC,KAAK,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAA;QAErC,IAAI,CAAC,IAAI,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAA;QAE1C,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;IAC3B,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,GAAG,IAAe;QACrB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IAED,iCAAiC;IACjC,IAAI,CAAC,GAAG,IAAe;QACrB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IAED,iCAAiC;IACjC,KAAK,CAAC,GAAG,IAAe;QACtB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACzD,CAAC;IAED,iCAAiC;IACjC,IAAI,CAAC,GAAG,IAAe;QACrB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IAED,iCAAiC;IACjC,GAAG,CAAC,GAAG,IAAe;QACpB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IAED,iCAAiC;IACjC,KAAK,CAAC,GAAG,IAAe;QACtB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACzD,CAAC;;AAjFM,kBAAW,GAAG,KAAK,CAAA;AAoF5B;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA"}
@@ -0,0 +1,120 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ /// <reference types="node" />
11
+ import { inspect } from 'util';
12
+ import { TypeGuards } from '@codeleap/types';
13
+ const DEFAULT_CHANNEL = '#_dev_logs';
14
+ const DEFAULT_BASE_URL = 'https://slack.com/api/chat.postMessage';
15
+ /**
16
+ * Sends structured log messages to a Slack channel via the Slack Web API.
17
+ *
18
+ * The service is inert until {@link setApi} is called with an HTTP client. Messages are
19
+ * silently suppressed when the API client is absent, `echoConfig.enabled` is `false`, or
20
+ * the current environment does not match the caller-supplied `sendIn` filter.
21
+ */
22
+ export class SlackService {
23
+ constructor(config) {
24
+ this.config = config;
25
+ this.serializers = {
26
+ version: (IsDev) => {
27
+ return IsDev ? 'debug' : 'release';
28
+ },
29
+ };
30
+ this.echoConfig = config.Slack.echo;
31
+ this.isDev = config.Environment.IsDev;
32
+ this.appName = config.AppName;
33
+ }
34
+ /**
35
+ * Registers the HTTP client used to POST messages to Slack. Must be called before `echo`
36
+ * can send anything; calling `echo` without a registered API is a no-op.
37
+ */
38
+ setApi(fetcher) {
39
+ this.api = fetcher;
40
+ }
41
+ /**
42
+ * Posts a labelled object to Slack. The message is formatted with `util.inspect` so nested
43
+ * structures are human-readable in the channel.
44
+ *
45
+ * Delivery is conditional on three independent guards:
46
+ * - `options.sendIn` — restricts to `'debug'` (IsDev) or `'release'` (production) builds;
47
+ * omitting `sendIn` sends in both environments.
48
+ * - `echoConfig.enabled` — master switch in the config; defaults to `true` when omitted.
49
+ * - A registered API client (see {@link setApi}).
50
+ *
51
+ * Failures are caught and logged to `console.error` rather than propagated.
52
+ */
53
+ echo(label_1, slackData_1) {
54
+ return __awaiter(this, arguments, void 0, function* (label, slackData, moduleName = undefined, messageOptions = {}) {
55
+ var _a, _b, _c, _d, _e, _f, _g, _h;
56
+ const options = this.parseOptions(messageOptions);
57
+ const slack = this.parseData(label, slackData, options.info, moduleName);
58
+ const enabled = TypeGuards.isBoolean(this.echoConfig.enabled) ? this.echoConfig.enabled : true;
59
+ if (!options.send || !this.api || !this.echoConfig || !enabled)
60
+ return;
61
+ const settingsData = (_b = (_a = this === null || this === void 0 ? void 0 : this.echoConfig) === null || _a === void 0 ? void 0 : _a.options) !== null && _b !== void 0 ? _b : {};
62
+ try {
63
+ const data = Object.assign({ 'channel': (_d = (_c = this === null || this === void 0 ? void 0 : this.echoConfig) === null || _c === void 0 ? void 0 : _c.channel) !== null && _d !== void 0 ? _d : DEFAULT_CHANNEL, 'text': slack, 'username': `${this.appName} Log`, 'icon_url': (_e = this === null || this === void 0 ? void 0 : this.echoConfig) === null || _e === void 0 ? void 0 : _e.icon }, settingsData);
64
+ yield this.api.post('', data, {
65
+ baseURL: (_g = (_f = this === null || this === void 0 ? void 0 : this.echoConfig) === null || _f === void 0 ? void 0 : _f.baseURL) !== null && _g !== void 0 ? _g : DEFAULT_BASE_URL,
66
+ headers: {
67
+ Authorization: `Bearer ${(_h = this === null || this === void 0 ? void 0 : this.echoConfig) === null || _h === void 0 ? void 0 : _h.token}`,
68
+ },
69
+ });
70
+ }
71
+ catch (err) {
72
+ console.error('Failed to echo', err, 'logger echoSlack');
73
+ }
74
+ });
75
+ }
76
+ parseOptions(options) {
77
+ const { sendIn = [], include = [], } = options;
78
+ const hasSendIn = sendIn.length >= 1;
79
+ const isDebug = hasSendIn ? sendIn.includes('debug') : true;
80
+ const isRelease = hasSendIn ? sendIn.includes('release') : true;
81
+ if (!isDebug && this.isDev || !isRelease && !this.isDev) {
82
+ return {
83
+ info: '',
84
+ send: false,
85
+ };
86
+ }
87
+ let str = '';
88
+ const separator = ' - ';
89
+ include.forEach(k => {
90
+ var _a, _b;
91
+ const data = (_b = (_a = this.serializers)[k]) === null || _b === void 0 ? void 0 : _b.call(_a, this.isDev);
92
+ str = `${str}${str.length > 0 ? separator : ''}[${data}]`;
93
+ });
94
+ return {
95
+ info: str,
96
+ send: true,
97
+ };
98
+ }
99
+ parseData(label, data, info, module) {
100
+ const obj = !info ? data : Object.assign(Object.assign({}, data), { info });
101
+ const args = [`${!module ? '' : `(${module}) `}${label}: `, obj];
102
+ const slack = args.map(i => {
103
+ if (typeof i === 'object') {
104
+ try {
105
+ return inspect(i, {
106
+ depth: 5,
107
+ compact: false,
108
+ showHidden: true,
109
+ });
110
+ }
111
+ catch (e) {
112
+ return `${i} (Unserializable value)`;
113
+ }
114
+ }
115
+ return String(i);
116
+ }).join(' ');
117
+ return slack;
118
+ }
119
+ }
120
+ //# sourceMappingURL=Slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slack.js","sourceRoot":"","sources":["../../src/lib/Slack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './Logger';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
@@ -0,0 +1,21 @@
1
+ const defineError = (errorName, args) => {
2
+ var _a;
3
+ switch (errorName) {
4
+ case 'maxRenders':
5
+ return `${args.name} is rendering more than ${args.maxRenders}time per ${((_a = args.throttleInterval) !== null && _a !== void 0 ? _a : 0) / 1000}second!
6
+ If you aware of this, you can disable it in the Settings.ts > Performancer.
7
+ `;
8
+ }
9
+ };
10
+ /**
11
+ * Thrown by {@link PerformanceService.inspectRender} when a component exceeds its allowed
12
+ * render budget. The error name is always `'Codeleap:Perf'`, making it easy to distinguish
13
+ * from application errors in React error boundaries or crash-reporting tools.
14
+ */
15
+ export class PerformanceError extends Error {
16
+ constructor(errorName, args) {
17
+ super(defineError(errorName, args));
18
+ this.name = 'Codeleap:Perf';
19
+ }
20
+ }
21
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/lib/performance/errors.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,GAAG,CAAC,SAAqB,EAAE,IAAwB,EAAE,EAAE;;IACtE,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,GAAG,IAAI,CAAC,IAAI,2BAA2B,IAAI,CAAC,UAAU,YAC3D,CAAC,MAAA,IAAI,CAAC,gBAAgB,mCAAI,CAAC,CAAC,GAAG,IACjC;;OAEC,CAAA;IACL,CAAC;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,SAAqB,EAAE,IAAwB;QACzD,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAA;QACnC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC7B,CAAC;CACF"}
@@ -0,0 +1,76 @@
1
+ import { throttle } from '@codeleap/utils';
2
+ import { useEffect } from 'react';
3
+ import { PerformanceError } from './errors';
4
+ export * from './types';
5
+ /**
6
+ * Dev-only performance utilities. All methods are no-ops in production
7
+ * (`config.Environment.IsDev === false`) or when
8
+ * `config.Logger.performanceInspector.enabled` is `false`.
9
+ */
10
+ export class PerformanceService {
11
+ constructor(config) {
12
+ this.config = config;
13
+ this.renderCounter = {};
14
+ /**
15
+ * Tracks render frequency for a component and warns when it exceeds the configured threshold.
16
+ *
17
+ * Call this at the top of a function component body (not inside a hook). By default it also
18
+ * registers mount/unmount effects via `useEffect` — pass `noHooks: true` to skip those when
19
+ * the component cannot accept additional hooks.
20
+ *
21
+ * When the accumulated render count within a `throttleInterval` window exceeds `maxRenders`,
22
+ * the counter resets and a {@link PerformanceError} is thrown (surfacing as a React error
23
+ * boundary hit rather than a silent warning).
24
+ *
25
+ * Components whose names start with any entry in
26
+ * `config.Logger.performanceInspector.blacklist` are silently skipped.
27
+ *
28
+ * Has no effect outside a dev environment or when the inspector is disabled in config.
29
+ */
30
+ this.inspectRender = (name, options = {
31
+ noHooks: false,
32
+ logMode: 'summarized',
33
+ throttleInterval: 1000,
34
+ }) => {
35
+ const config = this.config.Logger.performanceInspector;
36
+ const blacklist = config.blacklist || [];
37
+ if (blacklist.some((item) => name.startsWith(item)))
38
+ return;
39
+ const { noHooks, logMode, throttleInterval, maxRenders = config.maxRenders } = options;
40
+ if (!config.enabled || !this.config.Environment.IsDev) {
41
+ return;
42
+ }
43
+ if (!noHooks) {
44
+ useEffect(() => {
45
+ console.log(`[PerformanceInspector] Mounted -> ${name}`);
46
+ return () => {
47
+ console.log(`[PerformanceInspector] Unmounted -> ${name}`);
48
+ };
49
+ });
50
+ }
51
+ this.renderCounter[name] = this.renderCounter[name] ? this.renderCounter[name] + 1 : 1;
52
+ const renders = this.renderCounter[name];
53
+ if (renders > maxRenders) {
54
+ this.renderCounter[name] = 0;
55
+ throw new PerformanceError('maxRenders', {
56
+ name,
57
+ throttleInterval,
58
+ maxRenders,
59
+ });
60
+ }
61
+ if (logMode === 'raw') {
62
+ console.log(`[PerformanceInspector] Rendered -> ${name}: ${renders}`);
63
+ return;
64
+ }
65
+ function logSummary() {
66
+ if (renders <= 0)
67
+ return;
68
+ console.log(`[PerformanceInspector] Render summary -> ${name}: ${renders}`);
69
+ this.renderCounter[name] = 0;
70
+ }
71
+ // @ts-ignore
72
+ throttle(logSummary, name, throttleInterval);
73
+ };
74
+ }
75
+ }
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/performance/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAI3C,cAAc,SAAS,CAAA;AAEvB;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IAG7B,YAAoB,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;QAFxC,kBAAa,GAA2B,EAAE,CAAA;QAI1C;;;;;;;;;;;;;;;WAeG;QACH,kBAAa,GAAG,CACd,IAAY,EACZ,UAAgC;YAC9B,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,YAAY;YACrB,gBAAgB,EAAE,IAAI;SACvB,EACD,EAAE;YACF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAA;YAEtD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAA;YAExC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBAAE,OAAM;YAE3D,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,GAAG,OAAO,CAAA;YAEtF,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;gBACtD,OAAM;YACR,CAAC;YAED,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,SAAS,CAAC,GAAG,EAAE;oBACb,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAA;oBAExD,OAAO,GAAG,EAAE;wBACV,OAAO,CAAC,GAAG,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAA;oBAC5D,CAAC,CAAA;gBACH,CAAC,CAAC,CAAA;YACJ,CAAC;YAED,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAEtF,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;YAExC,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;gBACzB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAE5B,MAAM,IAAI,gBAAgB,CAAC,YAAY,EAAE;oBACvC,IAAI;oBACJ,gBAAgB;oBAChB,UAAU;iBACX,CAAC,CAAA;YACJ,CAAC;YAED,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,sCAAsC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAA;gBACrE,OAAM;YACR,CAAC;YAED,SAAS,UAAU;gBACjB,IAAI,OAAO,IAAI,CAAC;oBAAE,OAAM;gBAExB,OAAO,CAAC,GAAG,CAAC,4CAA4C,IAAI,KAAK,OAAO,EAAE,CAAC,CAAA;gBAC3E,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;YACD,aAAa;YACb,QAAQ,CAAC,UAAU,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAA;QAC9C,CAAC,CAAA;IA3E2C,CAAC;CA4E9C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/performance/types.ts"],"names":[],"mappings":""}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Concrete logger implementation produced by {@link createLogger}. Each log method writes to
3
+ * the native `console` counterpart **and** fans out to every registered transport, so
4
+ * third-party sinks (e.g. Sentry, Datadog) receive the same payload without extra wiring.
5
+ *
6
+ * `test` is intentionally a no-op — it exists as a scratch channel that leaves no output in
7
+ * any environment.
8
+ *
9
+ * Transport functions are shared as a static property, meaning all `CustomLogger` instances
10
+ * created in the same process share the same transport list. Only one call to
11
+ * {@link createLogger} is expected per app.
12
+ */
13
+ class CustomLogger {
14
+ static applyTransport(level, ...args) {
15
+ CustomLogger.transport.map(fn => {
16
+ fn(level, ...args);
17
+ });
18
+ }
19
+ info(...args) {
20
+ console.info(...args);
21
+ CustomLogger.applyTransport('info', ...args);
22
+ }
23
+ error(...args) {
24
+ console.error(...args);
25
+ CustomLogger.applyTransport('error', ...args);
26
+ }
27
+ warn(...args) {
28
+ console.warn(...args);
29
+ CustomLogger.applyTransport('warn', ...args);
30
+ }
31
+ /** Intentional no-op. Use as a scratch channel for temporary logs that must not ship. */
32
+ test(...args) {
33
+ }
34
+ log(...args) {
35
+ console.log(...args);
36
+ CustomLogger.applyTransport('log', ...args);
37
+ }
38
+ debug(...args) {
39
+ console.debug(...args);
40
+ CustomLogger.applyTransport('debug', ...args);
41
+ }
42
+ }
43
+ /**
44
+ * Wires up the transport list and returns a ready-to-use {@link CustomLogger} instance.
45
+ *
46
+ * The returned instance satisfies the logging method contract expected by {@link Logger},
47
+ * so it should be used to replace the stub methods on the shared `logger` singleton after
48
+ * calling `logger.initialize(config)`.
49
+ *
50
+ * Calling this more than once replaces the shared transport list for all existing instances.
51
+ */
52
+ export const createLogger = (options) => {
53
+ CustomLogger.transport = options.transport;
54
+ return new CustomLogger();
55
+ };
56
+ //# sourceMappingURL=createLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createLogger.js","sourceRoot":"","sources":["../../src/utils/createLogger.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;GAWG;AACH,MAAM,YAAY;IAGhB,MAAM,CAAC,cAAc,CAAC,KAAY,EAAE,GAAG,IAAe;QACpD,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAA;QACpB,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;QACrB,YAAY,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;IAC9C,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;QACtB,YAAY,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAA;IAC/C,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;QACrB,YAAY,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;IAC9C,CAAC;IAED,yFAAyF;IACzF,IAAI,CAAC,GAAG,IAAe;IAEvB,CAAC;IAED,GAAG,CAAC,GAAG,IAAe;QACpB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;QACpB,YAAY,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAA;IAC7C,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;QACtB,YAAY,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAA;IAC/C,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAsB,EAAE,EAAE;IACrD,YAAY,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAE1C,OAAO,IAAI,YAAY,EAAE,CAAA;AAC3B,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './createLogger';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codeleap/logger",
3
- "version": "6.8.0",
4
- "main": "src/index.ts",
3
+ "version": "7.0.1",
4
+ "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
7
7
  ".": {
@@ -22,9 +22,9 @@
22
22
  "directory": "packages/logger"
23
23
  },
24
24
  "devDependencies": {
25
- "@codeleap/types": "6.8.0",
26
- "@codeleap/utils": "6.8.0",
27
- "@codeleap/config": "6.8.0",
25
+ "@codeleap/types": "7.0.1",
26
+ "@codeleap/utils": "7.0.1",
27
+ "@codeleap/config": "7.0.1",
28
28
  "ts-node-dev": "1.1.8",
29
29
  "@sentry/types": "8.40.0"
30
30
  },
@@ -33,8 +33,8 @@
33
33
  "typecheck": "bun tsc --noEmit -p ./tsconfig.json"
34
34
  },
35
35
  "peerDependencies": {
36
- "@codeleap/types": "6.8.0",
37
- "@codeleap/utils": "6.8.0",
36
+ "@codeleap/types": "7.0.1",
37
+ "@codeleap/utils": "7.0.1",
38
38
  "typescript": "6.0.3",
39
39
  "react": "19.1.0"
40
40
  },