@cravery/firebase 0.0.38 → 0.0.40

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.
@@ -1,4 +1,5 @@
1
1
  export * from "./bookmark";
2
2
  export * from "./profile";
3
+ export * from "./request";
3
4
  export * from "./user";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/converters/users/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/converters/users/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC"}
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./bookmark"), exports);
18
18
  __exportStar(require("./profile"), exports);
19
+ __exportStar(require("./request"), exports);
19
20
  __exportStar(require("./user"), exports);
20
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/converters/users/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,4CAA0B;AAC1B,yCAAuB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/converters/users/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,4CAA0B;AAC1B,4CAA0B;AAC1B,yCAAuB"}
@@ -0,0 +1,4 @@
1
+ import { FirestoreDataConverter } from "firebase-admin/firestore";
2
+ import type { Request } from "@cravery/core";
3
+ export declare const requestConverter: FirestoreDataConverter<Request>;
4
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/converters/users/request.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EAGvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAS7C,eAAO,MAAM,gBAAgB,EAAE,sBAAsB,CAAC,OAAO,CAqB5D,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.requestConverter = void 0;
15
+ const lib_1 = require("../../lib");
16
+ exports.requestConverter = {
17
+ toFirestore(request) {
18
+ const { id, createdAt, updatedAt, deletedAt } = request, rest = __rest(request, ["id", "createdAt", "updatedAt", "deletedAt"]);
19
+ return (0, lib_1.stripUndefined)(Object.assign(Object.assign({}, rest), { createdAt: (0, lib_1.toFirestoreTimestamp)(createdAt), updatedAt: (0, lib_1.toFirestoreTimestamp)(updatedAt), deletedAt: (0, lib_1.toOptionalFirestoreTimestamp)(deletedAt) }));
20
+ },
21
+ fromFirestore(snapshot) {
22
+ const _a = snapshot.data(), { createdAt, updatedAt, deletedAt } = _a, rest = __rest(_a, ["createdAt", "updatedAt", "deletedAt"]);
23
+ return Object.assign(Object.assign({}, rest), { id: snapshot.id, createdAt: (0, lib_1.toTimestamp)(createdAt), updatedAt: (0, lib_1.toTimestamp)(updatedAt), deletedAt: (0, lib_1.toOptionalTimestamp)(deletedAt) });
24
+ },
25
+ };
26
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/converters/users/request.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAMA,mCAMmB;AAEN,QAAA,gBAAgB,GAAoC;IAC/D,WAAW,CAAC,OAAgB;QAC1B,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,KAAc,OAAO,EAAhB,IAAI,UAAK,OAAO,EAA1D,6CAAgD,CAAU,CAAC;QACjE,OAAO,IAAA,oBAAc,kCAChB,IAAI,KACP,SAAS,EAAE,IAAA,0BAAoB,EAAC,SAAS,CAAC,EAC1C,SAAS,EAAE,IAAA,0BAAoB,EAAC,SAAS,CAAC,EAC1C,SAAS,EAAE,IAAA,kCAA4B,EAAC,SAAS,CAAC,IAClD,CAAC;IACL,CAAC;IAED,aAAa,CAAC,QAA+B;QAC3C,MAAM,KAA+C,QAAQ,CAAC,IAAI,EAAE,EAA9D,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,OAA6B,EAAxB,IAAI,cAA1C,uCAA4C,CAAkB,CAAC;QACrE,OAAO,gCACF,IAAI,KACP,EAAE,EAAE,QAAQ,CAAC,EAAE,EACf,SAAS,EAAE,IAAA,iBAAW,EAAC,SAAS,CAAC,EACjC,SAAS,EAAE,IAAA,iBAAW,EAAC,SAAS,CAAC,EACjC,SAAS,EAAE,IAAA,yBAAmB,EAAC,SAAS,CAAC,GAC/B,CAAC;IACf,CAAC;CACF,CAAC"}
@@ -1,3 +1,4 @@
1
+ export * from "./monitoring";
1
2
  export * from "./strip-undefined";
2
3
  export * from "./timestamp";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
package/dist/lib/index.js CHANGED
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./monitoring"), exports);
17
18
  __exportStar(require("./strip-undefined"), exports);
18
19
  __exportStar(require("./timestamp"), exports);
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,8CAA4B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,oDAAkC;AAClC,8CAA4B"}
@@ -0,0 +1,15 @@
1
+ import { ObservableGauge } from "@opentelemetry/api";
2
+ type Attributes = Record<string, string>;
3
+ export declare const incrementCounter: (name: string, attributes?: Attributes, value?: number) => void;
4
+ export declare const recordTiming: (name: string, durationMs: number, attributes?: Attributes) => void;
5
+ export declare const withTiming: <T>(name: string, fn: () => Promise<T>, attributes?: Attributes) => Promise<T>;
6
+ export declare const registerGauge: (name: string, callback: () => number | Promise<number>, attributes?: Attributes) => ObservableGauge;
7
+ export declare const createMetricsScope: (defaultAttributes: Attributes) => {
8
+ incrementCounter: (name: string, attributes?: Attributes, value?: number) => void;
9
+ recordTiming: (name: string, durationMs: number, attributes?: Attributes) => void;
10
+ withTiming: <T>(name: string, fn: () => Promise<T>, attributes?: Attributes) => Promise<T>;
11
+ registerGauge: (name: string, callback: () => number | Promise<number>, attributes?: Attributes) => ObservableGauge;
12
+ };
13
+ export declare const shutdown: () => Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=monitoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../../src/lib/monitoring.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,eAAe,EAAS,MAAM,oBAAoB,CAAC;AA2ChF,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzC,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,aAAa,UAAU,EACvB,cAAS,KACR,IAEF,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,aAAa,UAAU,KACtB,IAEF,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,CAAC,EAChC,MAAM,MAAM,EACZ,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,aAAa,UAAU,KACtB,OAAO,CAAC,CAAC,CAKX,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,UAAU,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,EACxC,aAAa,UAAU,KACtB,eAOF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,mBAAmB,UAAU;6BACrC,MAAM,eAAe,UAAU;yBAGnC,MAAM,cAAc,MAAM,eAAe,UAAU;iBAG3D,CAAC,QACN,MAAM,MACR,MAAM,OAAO,CAAC,CAAC,CAAC,eACP,UAAU;0BAIjB,MAAM,YACF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,eAC3B,UAAU;CAEzB,CAAC;AAEH,eAAO,MAAM,QAAQ,QAAO,OAAO,CAAC,IAAI,CAA6B,CAAC"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shutdown = exports.createMetricsScope = exports.registerGauge = exports.withTiming = exports.recordTiming = exports.incrementCounter = void 0;
4
+ const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
5
+ const resources_1 = require("@opentelemetry/resources");
6
+ const opentelemetry_cloud_monitoring_exporter_1 = require("@google-cloud/opentelemetry-cloud-monitoring-exporter");
7
+ const resource = (0, resources_1.resourceFromAttributes)({
8
+ "service.name": "cravery-backend",
9
+ });
10
+ const exporter = new opentelemetry_cloud_monitoring_exporter_1.MetricExporter();
11
+ const meterProvider = new sdk_metrics_1.MeterProvider({
12
+ resource,
13
+ readers: [
14
+ new sdk_metrics_1.PeriodicExportingMetricReader({
15
+ exporter,
16
+ exportIntervalMillis: 60000,
17
+ }),
18
+ ],
19
+ });
20
+ const meter = meterProvider.getMeter("cravery");
21
+ const counters = new Map();
22
+ const histograms = new Map();
23
+ const getCounter = (name, description) => {
24
+ if (!counters.has(name)) {
25
+ counters.set(name, meter.createCounter(`cravery.${name}`, { description }));
26
+ }
27
+ return counters.get(name);
28
+ };
29
+ const getHistogram = (name, description) => {
30
+ if (!histograms.has(name)) {
31
+ histograms.set(name, meter.createHistogram(`cravery.${name}`, {
32
+ description,
33
+ unit: "ms",
34
+ }));
35
+ }
36
+ return histograms.get(name);
37
+ };
38
+ const incrementCounter = (name, attributes, value = 1) => {
39
+ getCounter(name).add(value, attributes);
40
+ };
41
+ exports.incrementCounter = incrementCounter;
42
+ const recordTiming = (name, durationMs, attributes) => {
43
+ getHistogram(name).record(durationMs, attributes);
44
+ };
45
+ exports.recordTiming = recordTiming;
46
+ const withTiming = async (name, fn, attributes) => {
47
+ const start = Date.now();
48
+ const result = await fn();
49
+ (0, exports.recordTiming)(name, Date.now() - start, attributes);
50
+ return result;
51
+ };
52
+ exports.withTiming = withTiming;
53
+ const registerGauge = (name, callback, attributes) => {
54
+ const gauge = meter.createObservableGauge(`cravery.${name}`);
55
+ gauge.addCallback(async (observableResult) => {
56
+ const value = await callback();
57
+ observableResult.observe(value, attributes);
58
+ });
59
+ return gauge;
60
+ };
61
+ exports.registerGauge = registerGauge;
62
+ const createMetricsScope = (defaultAttributes) => ({
63
+ incrementCounter: (name, attributes, value = 1) => (0, exports.incrementCounter)(name, Object.assign(Object.assign({}, defaultAttributes), attributes), value),
64
+ recordTiming: (name, durationMs, attributes) => (0, exports.recordTiming)(name, durationMs, Object.assign(Object.assign({}, defaultAttributes), attributes)),
65
+ withTiming: (name, fn, attributes) => (0, exports.withTiming)(name, fn, Object.assign(Object.assign({}, defaultAttributes), attributes)),
66
+ registerGauge: (name, callback, attributes) => (0, exports.registerGauge)(name, callback, Object.assign(Object.assign({}, defaultAttributes), attributes)),
67
+ });
68
+ exports.createMetricsScope = createMetricsScope;
69
+ const shutdown = () => meterProvider.shutdown();
70
+ exports.shutdown = shutdown;
71
+ //# sourceMappingURL=monitoring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitoring.js","sourceRoot":"","sources":["../../src/lib/monitoring.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cravery/firebase",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
4
4
  "description": "Shared Firebase Admin SDK utilities for Cravery",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,6 +28,10 @@
28
28
  "typescript": "^5.9.3"
29
29
  },
30
30
  "dependencies": {
31
- "@cravery/core": "^0.0.61"
31
+ "@cravery/core": "^0.0.62",
32
+ "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.21.0",
33
+ "@opentelemetry/api": "^1.9.0",
34
+ "@opentelemetry/resources": "^2.4.0",
35
+ "@opentelemetry/sdk-metrics": "^2.4.0"
32
36
  }
33
37
  }
@@ -1,3 +1,4 @@
1
1
  export * from "./bookmark";
2
2
  export * from "./profile";
3
+ export * from "./request";
3
4
  export * from "./user";
@@ -0,0 +1,36 @@
1
+ import {
2
+ FirestoreDataConverter,
3
+ QueryDocumentSnapshot,
4
+ DocumentData,
5
+ } from "firebase-admin/firestore";
6
+ import type { Request } from "@cravery/core";
7
+ import {
8
+ toTimestamp,
9
+ toOptionalTimestamp,
10
+ toFirestoreTimestamp,
11
+ toOptionalFirestoreTimestamp,
12
+ stripUndefined,
13
+ } from "../../lib";
14
+
15
+ export const requestConverter: FirestoreDataConverter<Request> = {
16
+ toFirestore(request: Request): DocumentData {
17
+ const { id, createdAt, updatedAt, deletedAt, ...rest } = request;
18
+ return stripUndefined({
19
+ ...rest,
20
+ createdAt: toFirestoreTimestamp(createdAt),
21
+ updatedAt: toFirestoreTimestamp(updatedAt),
22
+ deletedAt: toOptionalFirestoreTimestamp(deletedAt),
23
+ });
24
+ },
25
+
26
+ fromFirestore(snapshot: QueryDocumentSnapshot): Request {
27
+ const { createdAt, updatedAt, deletedAt, ...rest } = snapshot.data();
28
+ return {
29
+ ...rest,
30
+ id: snapshot.id,
31
+ createdAt: toTimestamp(createdAt),
32
+ updatedAt: toTimestamp(updatedAt),
33
+ deletedAt: toOptionalTimestamp(deletedAt),
34
+ } as Request;
35
+ },
36
+ };
package/src/lib/index.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./monitoring";
1
2
  export * from "./strip-undefined";
2
3
  export * from "./timestamp";
@@ -0,0 +1,112 @@
1
+ import {
2
+ MeterProvider,
3
+ PeriodicExportingMetricReader,
4
+ } from "@opentelemetry/sdk-metrics";
5
+ import { resourceFromAttributes } from "@opentelemetry/resources";
6
+ import { MetricExporter } from "@google-cloud/opentelemetry-cloud-monitoring-exporter";
7
+ import { Counter, Histogram, ObservableGauge, Meter } from "@opentelemetry/api";
8
+
9
+ const resource = resourceFromAttributes({
10
+ "service.name": "cravery-backend",
11
+ });
12
+
13
+ const exporter = new MetricExporter();
14
+
15
+ const meterProvider = new MeterProvider({
16
+ resource,
17
+ readers: [
18
+ new PeriodicExportingMetricReader({
19
+ exporter,
20
+ exportIntervalMillis: 60000,
21
+ }),
22
+ ],
23
+ });
24
+
25
+ const meter: Meter = meterProvider.getMeter("cravery");
26
+
27
+ const counters = new Map<string, Counter>();
28
+ const histograms = new Map<string, Histogram>();
29
+
30
+ const getCounter = (name: string, description?: string): Counter => {
31
+ if (!counters.has(name)) {
32
+ counters.set(name, meter.createCounter(`cravery.${name}`, { description }));
33
+ }
34
+ return counters.get(name)!;
35
+ };
36
+
37
+ const getHistogram = (name: string, description?: string): Histogram => {
38
+ if (!histograms.has(name)) {
39
+ histograms.set(
40
+ name,
41
+ meter.createHistogram(`cravery.${name}`, {
42
+ description,
43
+ unit: "ms",
44
+ }),
45
+ );
46
+ }
47
+ return histograms.get(name)!;
48
+ };
49
+
50
+ type Attributes = Record<string, string>;
51
+
52
+ export const incrementCounter = (
53
+ name: string,
54
+ attributes?: Attributes,
55
+ value = 1,
56
+ ): void => {
57
+ getCounter(name).add(value, attributes);
58
+ };
59
+
60
+ export const recordTiming = (
61
+ name: string,
62
+ durationMs: number,
63
+ attributes?: Attributes,
64
+ ): void => {
65
+ getHistogram(name).record(durationMs, attributes);
66
+ };
67
+
68
+ export const withTiming = async <T>(
69
+ name: string,
70
+ fn: () => Promise<T>,
71
+ attributes?: Attributes,
72
+ ): Promise<T> => {
73
+ const start = Date.now();
74
+ const result = await fn();
75
+ recordTiming(name, Date.now() - start, attributes);
76
+ return result;
77
+ };
78
+
79
+ export const registerGauge = (
80
+ name: string,
81
+ callback: () => number | Promise<number>,
82
+ attributes?: Attributes,
83
+ ): ObservableGauge => {
84
+ const gauge = meter.createObservableGauge(`cravery.${name}`);
85
+ gauge.addCallback(async (observableResult) => {
86
+ const value = await callback();
87
+ observableResult.observe(value, attributes);
88
+ });
89
+ return gauge;
90
+ };
91
+
92
+ export const createMetricsScope = (defaultAttributes: Attributes) => ({
93
+ incrementCounter: (name: string, attributes?: Attributes, value = 1) =>
94
+ incrementCounter(name, { ...defaultAttributes, ...attributes }, value),
95
+
96
+ recordTiming: (name: string, durationMs: number, attributes?: Attributes) =>
97
+ recordTiming(name, durationMs, { ...defaultAttributes, ...attributes }),
98
+
99
+ withTiming: <T>(
100
+ name: string,
101
+ fn: () => Promise<T>,
102
+ attributes?: Attributes,
103
+ ) => withTiming(name, fn, { ...defaultAttributes, ...attributes }),
104
+
105
+ registerGauge: (
106
+ name: string,
107
+ callback: () => number | Promise<number>,
108
+ attributes?: Attributes,
109
+ ) => registerGauge(name, callback, { ...defaultAttributes, ...attributes }),
110
+ });
111
+
112
+ export const shutdown = (): Promise<void> => meterProvider.shutdown();