@ga-components/logger 1.0.0
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 +73 -0
- package/dist/index.d.mts +36 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +110 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +83 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# React + TypeScript + Vite
|
|
2
|
+
|
|
3
|
+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
4
|
+
|
|
5
|
+
Currently, two official plugins are available:
|
|
6
|
+
|
|
7
|
+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
|
8
|
+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
|
9
|
+
|
|
10
|
+
## React Compiler
|
|
11
|
+
|
|
12
|
+
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
|
13
|
+
|
|
14
|
+
## Expanding the ESLint configuration
|
|
15
|
+
|
|
16
|
+
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
export default defineConfig([
|
|
20
|
+
globalIgnores(['dist']),
|
|
21
|
+
{
|
|
22
|
+
files: ['**/*.{ts,tsx}'],
|
|
23
|
+
extends: [
|
|
24
|
+
// Other configs...
|
|
25
|
+
|
|
26
|
+
// Remove tseslint.configs.recommended and replace with this
|
|
27
|
+
tseslint.configs.recommendedTypeChecked,
|
|
28
|
+
// Alternatively, use this for stricter rules
|
|
29
|
+
tseslint.configs.strictTypeChecked,
|
|
30
|
+
// Optionally, add this for stylistic rules
|
|
31
|
+
tseslint.configs.stylisticTypeChecked,
|
|
32
|
+
|
|
33
|
+
// Other configs...
|
|
34
|
+
],
|
|
35
|
+
languageOptions: {
|
|
36
|
+
parserOptions: {
|
|
37
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
38
|
+
tsconfigRootDir: import.meta.dirname,
|
|
39
|
+
},
|
|
40
|
+
// other options...
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
])
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// eslint.config.js
|
|
50
|
+
import reactX from 'eslint-plugin-react-x'
|
|
51
|
+
import reactDom from 'eslint-plugin-react-dom'
|
|
52
|
+
|
|
53
|
+
export default defineConfig([
|
|
54
|
+
globalIgnores(['dist']),
|
|
55
|
+
{
|
|
56
|
+
files: ['**/*.{ts,tsx}'],
|
|
57
|
+
extends: [
|
|
58
|
+
// Other configs...
|
|
59
|
+
// Enable lint rules for React
|
|
60
|
+
reactX.configs['recommended-typescript'],
|
|
61
|
+
// Enable lint rules for React DOM
|
|
62
|
+
reactDom.configs.recommended,
|
|
63
|
+
],
|
|
64
|
+
languageOptions: {
|
|
65
|
+
parserOptions: {
|
|
66
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
67
|
+
tsconfigRootDir: import.meta.dirname,
|
|
68
|
+
},
|
|
69
|
+
// other options...
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
])
|
|
73
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
type LogLevel = "info" | "warn" | "error";
|
|
2
|
+
type LogEnv = "PROD" | "DEV";
|
|
3
|
+
interface LogEntry {
|
|
4
|
+
timestamp: Date;
|
|
5
|
+
level: LogLevel;
|
|
6
|
+
message: string;
|
|
7
|
+
env: LogEnv;
|
|
8
|
+
userId: string | null;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
page: string;
|
|
11
|
+
stackTrace: string | null;
|
|
12
|
+
payload: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
interface LoggerConfig {
|
|
15
|
+
env: LogEnv;
|
|
16
|
+
userId?: string | null;
|
|
17
|
+
apiKey: string;
|
|
18
|
+
authDomain: string;
|
|
19
|
+
projectId: string;
|
|
20
|
+
storageBucket: string;
|
|
21
|
+
messagingSenderId: string;
|
|
22
|
+
appId: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare class Logger {
|
|
26
|
+
private config;
|
|
27
|
+
private initialized;
|
|
28
|
+
init(config: LoggerConfig): void;
|
|
29
|
+
private send;
|
|
30
|
+
info(message: string, payload?: Record<string, unknown>): Promise<void>;
|
|
31
|
+
warn(message: string, payload?: Record<string, unknown>): Promise<void>;
|
|
32
|
+
error(message: string, error?: Error, payload?: Record<string, unknown>): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
declare const logger: Logger;
|
|
35
|
+
|
|
36
|
+
export { type LogEntry, type LogEnv, type LogLevel, type LoggerConfig, logger };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
type LogLevel = "info" | "warn" | "error";
|
|
2
|
+
type LogEnv = "PROD" | "DEV";
|
|
3
|
+
interface LogEntry {
|
|
4
|
+
timestamp: Date;
|
|
5
|
+
level: LogLevel;
|
|
6
|
+
message: string;
|
|
7
|
+
env: LogEnv;
|
|
8
|
+
userId: string | null;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
page: string;
|
|
11
|
+
stackTrace: string | null;
|
|
12
|
+
payload: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
interface LoggerConfig {
|
|
15
|
+
env: LogEnv;
|
|
16
|
+
userId?: string | null;
|
|
17
|
+
apiKey: string;
|
|
18
|
+
authDomain: string;
|
|
19
|
+
projectId: string;
|
|
20
|
+
storageBucket: string;
|
|
21
|
+
messagingSenderId: string;
|
|
22
|
+
appId: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare class Logger {
|
|
26
|
+
private config;
|
|
27
|
+
private initialized;
|
|
28
|
+
init(config: LoggerConfig): void;
|
|
29
|
+
private send;
|
|
30
|
+
info(message: string, payload?: Record<string, unknown>): Promise<void>;
|
|
31
|
+
warn(message: string, payload?: Record<string, unknown>): Promise<void>;
|
|
32
|
+
error(message: string, error?: Error, payload?: Record<string, unknown>): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
declare const logger: Logger;
|
|
35
|
+
|
|
36
|
+
export { type LogEntry, type LogEnv, type LogLevel, type LoggerConfig, logger };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
logger: () => logger
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/core/logger.ts
|
|
28
|
+
var import_firestore2 = require("firebase/firestore");
|
|
29
|
+
|
|
30
|
+
// src/config/firebase.ts
|
|
31
|
+
var import_app = require("firebase/app");
|
|
32
|
+
var import_firestore = require("firebase/firestore");
|
|
33
|
+
var app;
|
|
34
|
+
var db;
|
|
35
|
+
var initFirebase = (config) => {
|
|
36
|
+
if (!(0, import_app.getApps)().length) {
|
|
37
|
+
app = (0, import_app.initializeApp)(
|
|
38
|
+
{
|
|
39
|
+
apiKey: config.apiKey,
|
|
40
|
+
authDomain: config.authDomain,
|
|
41
|
+
projectId: config.projectId,
|
|
42
|
+
storageBucket: config.storageBucket,
|
|
43
|
+
messagingSenderId: config.messagingSenderId,
|
|
44
|
+
appId: config.appId
|
|
45
|
+
},
|
|
46
|
+
"ga-logger"
|
|
47
|
+
);
|
|
48
|
+
} else {
|
|
49
|
+
app = (0, import_app.getApps)()[0];
|
|
50
|
+
}
|
|
51
|
+
db = (0, import_firestore.getFirestore)(app);
|
|
52
|
+
return db;
|
|
53
|
+
};
|
|
54
|
+
var getDb = () => db;
|
|
55
|
+
|
|
56
|
+
// src/core/logger.ts
|
|
57
|
+
var sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
58
|
+
var Logger = class {
|
|
59
|
+
constructor() {
|
|
60
|
+
this.config = null;
|
|
61
|
+
this.initialized = false;
|
|
62
|
+
}
|
|
63
|
+
init(config) {
|
|
64
|
+
this.config = config;
|
|
65
|
+
initFirebase(config);
|
|
66
|
+
this.initialized = true;
|
|
67
|
+
console.info("[ga-logger] initialized \u2014", config.env);
|
|
68
|
+
}
|
|
69
|
+
async send(level, message, payload = {}, error) {
|
|
70
|
+
if (!this.initialized || !this.config) {
|
|
71
|
+
console.warn("[ga-logger] not initialized. Call logger.init() first.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const entry = {
|
|
75
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
76
|
+
level,
|
|
77
|
+
message,
|
|
78
|
+
env: this.config.env,
|
|
79
|
+
userId: this.config.userId ?? null,
|
|
80
|
+
sessionId,
|
|
81
|
+
page: typeof window !== "undefined" ? window.location.pathname : "",
|
|
82
|
+
stackTrace: error?.stack ?? null,
|
|
83
|
+
payload
|
|
84
|
+
};
|
|
85
|
+
try {
|
|
86
|
+
const db2 = getDb();
|
|
87
|
+
await (0, import_firestore2.addDoc)((0, import_firestore2.collection)(db2, "logs"), {
|
|
88
|
+
...entry,
|
|
89
|
+
timestamp: import_firestore2.Timestamp.fromDate(entry.timestamp)
|
|
90
|
+
});
|
|
91
|
+
} catch (e) {
|
|
92
|
+
console.error("[ga-logger] failed to send log:", e);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
info(message, payload) {
|
|
96
|
+
return this.send("info", message, payload);
|
|
97
|
+
}
|
|
98
|
+
warn(message, payload) {
|
|
99
|
+
return this.send("warn", message, payload);
|
|
100
|
+
}
|
|
101
|
+
error(message, error, payload) {
|
|
102
|
+
return this.send("error", message, payload, error);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var logger = new Logger();
|
|
106
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
107
|
+
0 && (module.exports = {
|
|
108
|
+
logger
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/logger.ts","../src/config/firebase.ts"],"sourcesContent":["export { logger } from \"./core/logger\";\nexport type { LogEntry, LoggerConfig, LogLevel, LogEnv } from \"./types\";\n","import { collection, addDoc, Timestamp } from \"firebase/firestore\";\nimport { initFirebase, getDb } from \"../config/firebase\";\nimport { LogEntry, LogLevel, LoggerConfig } from \"../types\";\n\n// Generate simple sessionId sekali per session browser\nconst sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;\n\nclass Logger {\n private config: LoggerConfig | null = null;\n private initialized = false;\n\n init(config: LoggerConfig) {\n this.config = config;\n initFirebase(config);\n this.initialized = true;\n console.info(\"[ga-logger] initialized —\", config.env);\n }\n\n private async send(level: LogLevel, message: string, payload: Record<string, unknown> = {}, error?: Error) {\n if (!this.initialized || !this.config) {\n console.warn(\"[ga-logger] not initialized. Call logger.init() first.\");\n return;\n }\n\n const entry: LogEntry = {\n timestamp: new Date(),\n level,\n message,\n env: this.config.env,\n userId: this.config.userId ?? null,\n sessionId,\n page: typeof window !== \"undefined\" ? window.location.pathname : \"\",\n stackTrace: error?.stack ?? null,\n payload,\n };\n\n try {\n const db = getDb();\n await addDoc(collection(db, \"logs\"), {\n ...entry,\n timestamp: Timestamp.fromDate(entry.timestamp),\n });\n } catch (e) {\n // Jangan throw — logger tidak boleh crash app utama\n console.error(\"[ga-logger] failed to send log:\", e);\n }\n }\n\n info(message: string, payload?: Record<string, unknown>) {\n return this.send(\"info\", message, payload);\n }\n\n warn(message: string, payload?: Record<string, unknown>) {\n return this.send(\"warn\", message, payload);\n }\n\n error(message: string, error?: Error, payload?: Record<string, unknown>) {\n return this.send(\"error\", message, payload, error);\n }\n}\n\n// Singleton export\nexport const logger = new Logger();\n","import { initializeApp, getApps, FirebaseApp } from \"firebase/app\";\nimport { getFirestore, Firestore } from \"firebase/firestore\";\nimport { LoggerConfig } from \"../types\";\n\nlet app: FirebaseApp;\nlet db: Firestore;\n\nexport const initFirebase = (config: LoggerConfig) => {\n if (!getApps().length) {\n app = initializeApp(\n {\n apiKey: config.apiKey,\n authDomain: config.authDomain,\n projectId: config.projectId,\n storageBucket: config.storageBucket,\n messagingSenderId: config.messagingSenderId,\n appId: config.appId,\n },\n \"ga-logger\",\n );\n } else {\n app = getApps()[0];\n }\n\n db = getFirestore(app);\n return db;\n};\n\nexport const getDb = () => db;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,oBAA8C;;;ACA9C,iBAAoD;AACpD,uBAAwC;AAGxC,IAAI;AACJ,IAAI;AAEG,IAAM,eAAe,CAAC,WAAyB;AAClD,MAAI,KAAC,oBAAQ,EAAE,QAAQ;AACnB,cAAM;AAAA,MACF;AAAA,QACI,QAAQ,OAAO;AAAA,QACf,YAAY,OAAO;AAAA,QACnB,WAAW,OAAO;AAAA,QAClB,eAAe,OAAO;AAAA,QACtB,mBAAmB,OAAO;AAAA,QAC1B,OAAO,OAAO;AAAA,MAClB;AAAA,MACA;AAAA,IACJ;AAAA,EACJ,OAAO;AACH,cAAM,oBAAQ,EAAE,CAAC;AAAA,EACrB;AAEA,WAAK,+BAAa,GAAG;AACrB,SAAO;AACX;AAEO,IAAM,QAAQ,MAAM;;;ADvB3B,IAAM,YAAY,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAE9E,IAAM,SAAN,MAAa;AAAA,EAAb;AACI,SAAQ,SAA8B;AACtC,SAAQ,cAAc;AAAA;AAAA,EAEtB,KAAK,QAAsB;AACvB,SAAK,SAAS;AACd,iBAAa,MAAM;AACnB,SAAK,cAAc;AACnB,YAAQ,KAAK,kCAA6B,OAAO,GAAG;AAAA,EACxD;AAAA,EAEA,MAAc,KAAK,OAAiB,SAAiB,UAAmC,CAAC,GAAG,OAAe;AACvG,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,QAAQ;AACnC,cAAQ,KAAK,wDAAwD;AACrE;AAAA,IACJ;AAEA,UAAM,QAAkB;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA,KAAK,KAAK,OAAO;AAAA,MACjB,QAAQ,KAAK,OAAO,UAAU;AAAA,MAC9B;AAAA,MACA,MAAM,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,MACjE,YAAY,OAAO,SAAS;AAAA,MAC5B;AAAA,IACJ;AAEA,QAAI;AACA,YAAMC,MAAK,MAAM;AACjB,gBAAM,8BAAO,8BAAWA,KAAI,MAAM,GAAG;AAAA,QACjC,GAAG;AAAA,QACH,WAAW,4BAAU,SAAS,MAAM,SAAS;AAAA,MACjD,CAAC;AAAA,IACL,SAAS,GAAG;AAER,cAAQ,MAAM,mCAAmC,CAAC;AAAA,IACtD;AAAA,EACJ;AAAA,EAEA,KAAK,SAAiB,SAAmC;AACrD,WAAO,KAAK,KAAK,QAAQ,SAAS,OAAO;AAAA,EAC7C;AAAA,EAEA,KAAK,SAAiB,SAAmC;AACrD,WAAO,KAAK,KAAK,QAAQ,SAAS,OAAO;AAAA,EAC7C;AAAA,EAEA,MAAM,SAAiB,OAAe,SAAmC;AACrE,WAAO,KAAK,KAAK,SAAS,SAAS,SAAS,KAAK;AAAA,EACrD;AACJ;AAGO,IAAM,SAAS,IAAI,OAAO;","names":["import_firestore","db"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// src/core/logger.ts
|
|
2
|
+
import { collection, addDoc, Timestamp } from "firebase/firestore";
|
|
3
|
+
|
|
4
|
+
// src/config/firebase.ts
|
|
5
|
+
import { initializeApp, getApps } from "firebase/app";
|
|
6
|
+
import { getFirestore } from "firebase/firestore";
|
|
7
|
+
var app;
|
|
8
|
+
var db;
|
|
9
|
+
var initFirebase = (config) => {
|
|
10
|
+
if (!getApps().length) {
|
|
11
|
+
app = initializeApp(
|
|
12
|
+
{
|
|
13
|
+
apiKey: config.apiKey,
|
|
14
|
+
authDomain: config.authDomain,
|
|
15
|
+
projectId: config.projectId,
|
|
16
|
+
storageBucket: config.storageBucket,
|
|
17
|
+
messagingSenderId: config.messagingSenderId,
|
|
18
|
+
appId: config.appId
|
|
19
|
+
},
|
|
20
|
+
"ga-logger"
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
app = getApps()[0];
|
|
24
|
+
}
|
|
25
|
+
db = getFirestore(app);
|
|
26
|
+
return db;
|
|
27
|
+
};
|
|
28
|
+
var getDb = () => db;
|
|
29
|
+
|
|
30
|
+
// src/core/logger.ts
|
|
31
|
+
var sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
32
|
+
var Logger = class {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.config = null;
|
|
35
|
+
this.initialized = false;
|
|
36
|
+
}
|
|
37
|
+
init(config) {
|
|
38
|
+
this.config = config;
|
|
39
|
+
initFirebase(config);
|
|
40
|
+
this.initialized = true;
|
|
41
|
+
console.info("[ga-logger] initialized \u2014", config.env);
|
|
42
|
+
}
|
|
43
|
+
async send(level, message, payload = {}, error) {
|
|
44
|
+
if (!this.initialized || !this.config) {
|
|
45
|
+
console.warn("[ga-logger] not initialized. Call logger.init() first.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const entry = {
|
|
49
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
50
|
+
level,
|
|
51
|
+
message,
|
|
52
|
+
env: this.config.env,
|
|
53
|
+
userId: this.config.userId ?? null,
|
|
54
|
+
sessionId,
|
|
55
|
+
page: typeof window !== "undefined" ? window.location.pathname : "",
|
|
56
|
+
stackTrace: error?.stack ?? null,
|
|
57
|
+
payload
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
const db2 = getDb();
|
|
61
|
+
await addDoc(collection(db2, "logs"), {
|
|
62
|
+
...entry,
|
|
63
|
+
timestamp: Timestamp.fromDate(entry.timestamp)
|
|
64
|
+
});
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.error("[ga-logger] failed to send log:", e);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
info(message, payload) {
|
|
70
|
+
return this.send("info", message, payload);
|
|
71
|
+
}
|
|
72
|
+
warn(message, payload) {
|
|
73
|
+
return this.send("warn", message, payload);
|
|
74
|
+
}
|
|
75
|
+
error(message, error, payload) {
|
|
76
|
+
return this.send("error", message, payload, error);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
var logger = new Logger();
|
|
80
|
+
export {
|
|
81
|
+
logger
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/logger.ts","../src/config/firebase.ts"],"sourcesContent":["import { collection, addDoc, Timestamp } from \"firebase/firestore\";\nimport { initFirebase, getDb } from \"../config/firebase\";\nimport { LogEntry, LogLevel, LoggerConfig } from \"../types\";\n\n// Generate simple sessionId sekali per session browser\nconst sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;\n\nclass Logger {\n private config: LoggerConfig | null = null;\n private initialized = false;\n\n init(config: LoggerConfig) {\n this.config = config;\n initFirebase(config);\n this.initialized = true;\n console.info(\"[ga-logger] initialized —\", config.env);\n }\n\n private async send(level: LogLevel, message: string, payload: Record<string, unknown> = {}, error?: Error) {\n if (!this.initialized || !this.config) {\n console.warn(\"[ga-logger] not initialized. Call logger.init() first.\");\n return;\n }\n\n const entry: LogEntry = {\n timestamp: new Date(),\n level,\n message,\n env: this.config.env,\n userId: this.config.userId ?? null,\n sessionId,\n page: typeof window !== \"undefined\" ? window.location.pathname : \"\",\n stackTrace: error?.stack ?? null,\n payload,\n };\n\n try {\n const db = getDb();\n await addDoc(collection(db, \"logs\"), {\n ...entry,\n timestamp: Timestamp.fromDate(entry.timestamp),\n });\n } catch (e) {\n // Jangan throw — logger tidak boleh crash app utama\n console.error(\"[ga-logger] failed to send log:\", e);\n }\n }\n\n info(message: string, payload?: Record<string, unknown>) {\n return this.send(\"info\", message, payload);\n }\n\n warn(message: string, payload?: Record<string, unknown>) {\n return this.send(\"warn\", message, payload);\n }\n\n error(message: string, error?: Error, payload?: Record<string, unknown>) {\n return this.send(\"error\", message, payload, error);\n }\n}\n\n// Singleton export\nexport const logger = new Logger();\n","import { initializeApp, getApps, FirebaseApp } from \"firebase/app\";\nimport { getFirestore, Firestore } from \"firebase/firestore\";\nimport { LoggerConfig } from \"../types\";\n\nlet app: FirebaseApp;\nlet db: Firestore;\n\nexport const initFirebase = (config: LoggerConfig) => {\n if (!getApps().length) {\n app = initializeApp(\n {\n apiKey: config.apiKey,\n authDomain: config.authDomain,\n projectId: config.projectId,\n storageBucket: config.storageBucket,\n messagingSenderId: config.messagingSenderId,\n appId: config.appId,\n },\n \"ga-logger\",\n );\n } else {\n app = getApps()[0];\n }\n\n db = getFirestore(app);\n return db;\n};\n\nexport const getDb = () => db;\n"],"mappings":";AAAA,SAAS,YAAY,QAAQ,iBAAiB;;;ACA9C,SAAS,eAAe,eAA4B;AACpD,SAAS,oBAA+B;AAGxC,IAAI;AACJ,IAAI;AAEG,IAAM,eAAe,CAAC,WAAyB;AAClD,MAAI,CAAC,QAAQ,EAAE,QAAQ;AACnB,UAAM;AAAA,MACF;AAAA,QACI,QAAQ,OAAO;AAAA,QACf,YAAY,OAAO;AAAA,QACnB,WAAW,OAAO;AAAA,QAClB,eAAe,OAAO;AAAA,QACtB,mBAAmB,OAAO;AAAA,QAC1B,OAAO,OAAO;AAAA,MAClB;AAAA,MACA;AAAA,IACJ;AAAA,EACJ,OAAO;AACH,UAAM,QAAQ,EAAE,CAAC;AAAA,EACrB;AAEA,OAAK,aAAa,GAAG;AACrB,SAAO;AACX;AAEO,IAAM,QAAQ,MAAM;;;ADvB3B,IAAM,YAAY,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAE9E,IAAM,SAAN,MAAa;AAAA,EAAb;AACI,SAAQ,SAA8B;AACtC,SAAQ,cAAc;AAAA;AAAA,EAEtB,KAAK,QAAsB;AACvB,SAAK,SAAS;AACd,iBAAa,MAAM;AACnB,SAAK,cAAc;AACnB,YAAQ,KAAK,kCAA6B,OAAO,GAAG;AAAA,EACxD;AAAA,EAEA,MAAc,KAAK,OAAiB,SAAiB,UAAmC,CAAC,GAAG,OAAe;AACvG,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,QAAQ;AACnC,cAAQ,KAAK,wDAAwD;AACrE;AAAA,IACJ;AAEA,UAAM,QAAkB;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA,KAAK,KAAK,OAAO;AAAA,MACjB,QAAQ,KAAK,OAAO,UAAU;AAAA,MAC9B;AAAA,MACA,MAAM,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,MACjE,YAAY,OAAO,SAAS;AAAA,MAC5B;AAAA,IACJ;AAEA,QAAI;AACA,YAAMA,MAAK,MAAM;AACjB,YAAM,OAAO,WAAWA,KAAI,MAAM,GAAG;AAAA,QACjC,GAAG;AAAA,QACH,WAAW,UAAU,SAAS,MAAM,SAAS;AAAA,MACjD,CAAC;AAAA,IACL,SAAS,GAAG;AAER,cAAQ,MAAM,mCAAmC,CAAC;AAAA,IACtD;AAAA,EACJ;AAAA,EAEA,KAAK,SAAiB,SAAmC;AACrD,WAAO,KAAK,KAAK,QAAQ,SAAS,OAAO;AAAA,EAC7C;AAAA,EAEA,KAAK,SAAiB,SAAmC;AACrD,WAAO,KAAK,KAAK,QAAQ,SAAS,OAAO;AAAA,EAC7C;AAAA,EAEA,MAAM,SAAiB,OAAe,SAAmC;AACrE,WAAO,KAAK,KAAK,SAAS,SAAS,SAAS,KAAK;AAAA,EACrD;AACJ;AAGO,IAAM,SAAS,IAAI,OAAO;","names":["db"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ga-components/logger",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"dev": "tsup --watch",
|
|
14
|
+
"clean": "rm -rf dist"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"firebase": "^11.0.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": "^18.2.0",
|
|
21
|
+
"react-dom": "^18.2.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/react": "^18.2.0",
|
|
25
|
+
"@types/react-dom": "^18.2.0",
|
|
26
|
+
"react": "^18.2.0",
|
|
27
|
+
"react-dom": "^18.2.0",
|
|
28
|
+
"tsup": "^8.0.2",
|
|
29
|
+
"typescript": "^5.0.0",
|
|
30
|
+
"vite-plugin-dts": "^5.0.2"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"require": "./dist/index.cjs"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|