@tachybase/module-instrumentation 1.0.22

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.
Files changed (52) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1 -0
  3. package/client.d.ts +2 -0
  4. package/client.js +1 -0
  5. package/dist/client/TrackingConfigPane.d.ts +1 -0
  6. package/dist/client/TrackingLogPane.d.ts +1 -0
  7. package/dist/client/TrackingStatisticsPane.d.ts +1 -0
  8. package/dist/client/collections/statisticsConfig.collection.d.ts +10 -0
  9. package/dist/client/collections/trackingConfig.collection.d.ts +10 -0
  10. package/dist/client/collections/trackingLog.collection.d.ts +17 -0
  11. package/dist/client/index.d.ts +1 -0
  12. package/dist/client/index.js +139 -0
  13. package/dist/client/locale.d.ts +7 -0
  14. package/dist/client/plugin.d.ts +5 -0
  15. package/dist/client/schemas/createStatisticsConfig.d.ts +2 -0
  16. package/dist/client/schemas/createTrackingConfig.d.ts +2 -0
  17. package/dist/client/schemas/schemaStatisticsConfigs.d.ts +2 -0
  18. package/dist/client/schemas/schemaTrackingLog.d.ts +2 -0
  19. package/dist/client/schemas/schematrackingConfig.d.ts +2 -0
  20. package/dist/client/schemas/updateStatisticsConfig.d.ts +2 -0
  21. package/dist/client/schemas/updateTrackingConfig.d.ts +2 -0
  22. package/dist/client/schemas/viewTrackingLog.d.ts +2 -0
  23. package/dist/externalVersion.js +12 -0
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.js +39 -0
  26. package/dist/locale/en-US.json +18 -0
  27. package/dist/locale/zh-CN.json +19 -0
  28. package/dist/server/ServerTrackingFilter.d.ts +19 -0
  29. package/dist/server/ServerTrackingFilter.js +68 -0
  30. package/dist/server/actions/tracking-controller.d.ts +5 -0
  31. package/dist/server/actions/tracking-controller.js +135 -0
  32. package/dist/server/collections/statistics_config.d.ts +3 -0
  33. package/dist/server/collections/statistics_config.js +44 -0
  34. package/dist/server/collections/tracking_config.d.ts +3 -0
  35. package/dist/server/collections/tracking_config.js +58 -0
  36. package/dist/server/collections/tracking_log.d.ts +3 -0
  37. package/dist/server/collections/tracking_log.js +50 -0
  38. package/dist/server/hooks/afterAction.d.ts +3 -0
  39. package/dist/server/hooks/afterAction.js +94 -0
  40. package/dist/server/hooks/filterMatch.d.ts +1 -0
  41. package/dist/server/hooks/filterMatch.js +81 -0
  42. package/dist/server/hooks/getActiveUser.d.ts +6 -0
  43. package/dist/server/hooks/getActiveUser.js +84 -0
  44. package/dist/server/hooks/getStatistics.d.ts +17 -0
  45. package/dist/server/hooks/getStatistics.js +208 -0
  46. package/dist/server/index.d.ts +1 -0
  47. package/dist/server/index.js +33 -0
  48. package/dist/server/plugin.d.ts +8 -0
  49. package/dist/server/plugin.js +161 -0
  50. package/package.json +27 -0
  51. package/server.d.ts +2 -0
  52. package/server.js +1 -0
@@ -0,0 +1,81 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var filterMatch_exports = {};
19
+ __export(filterMatch_exports, {
20
+ filterMatch: () => filterMatch
21
+ });
22
+ module.exports = __toCommonJS(filterMatch_exports);
23
+ const operators = {
24
+ $eq: (a, b) => a === b,
25
+ $ne: (a, b) => a !== b,
26
+ $gt: (a, b) => a > b,
27
+ $gte: (a, b) => a >= b,
28
+ $lt: (a, b) => a < b,
29
+ $lte: (a, b) => a <= b,
30
+ $in: (a, b) => a.includes(b),
31
+ $exists: (a, b) => b ? a !== void 0 : a === void 0,
32
+ $null: (a, b) => b ? a === null : a !== null
33
+ };
34
+ function getValueByPath(obj, path) {
35
+ if (!obj || !path) return void 0;
36
+ return path.split(".").reduce((acc, key) => {
37
+ if (acc === void 0 || acc === null) return void 0;
38
+ return acc[key];
39
+ }, obj);
40
+ }
41
+ function matchCondition(value, condition) {
42
+ for (const op in condition) {
43
+ const operator = op;
44
+ if (operators[operator]) {
45
+ if (!operators[operator](value, condition[op])) return false;
46
+ } else {
47
+ return false;
48
+ }
49
+ }
50
+ return true;
51
+ }
52
+ function filterMatch(model, filter) {
53
+ if ("$and" in filter) {
54
+ return filter["$and"].every((subFilter) => filterMatch(model, subFilter));
55
+ }
56
+ if ("$or" in filter) {
57
+ return filter["$or"].some((subFilter) => filterMatch(model, subFilter));
58
+ }
59
+ for (const key in filter) {
60
+ const value = filter[key];
61
+ if (typeof value === "object" && !Array.isArray(value)) {
62
+ for (const subKey in value) {
63
+ const nested = value[subKey];
64
+ const fullPath = `${key}.${subKey}`;
65
+ const actualValue = getValueByPath(model, fullPath);
66
+ if (!matchCondition(actualValue, nested)) {
67
+ return false;
68
+ }
69
+ }
70
+ } else {
71
+ if (getValueByPath(model, key) !== value) {
72
+ return false;
73
+ }
74
+ }
75
+ }
76
+ return true;
77
+ }
78
+ // Annotate the CommonJS export names for ESM import in node:
79
+ 0 && (module.exports = {
80
+ filterMatch
81
+ });
@@ -0,0 +1,6 @@
1
+ import { Context } from '@tachybase/actions';
2
+ export declare const getDailyActiveUser: (ctx: Context) => Promise<{
3
+ todayActiveUserCount: number;
4
+ average7: number;
5
+ average30: number;
6
+ }>;
@@ -0,0 +1,84 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var getActiveUser_exports = {};
29
+ __export(getActiveUser_exports, {
30
+ getDailyActiveUser: () => getDailyActiveUser
31
+ });
32
+ module.exports = __toCommonJS(getActiveUser_exports);
33
+ var import_dayjs = __toESM(require("dayjs"));
34
+ const getDailyActiveUser = async (ctx) => {
35
+ var _a, _b, _c, _d;
36
+ const repo = await ctx.db.getRepository("trackingEvents");
37
+ const todayStart = (0, import_dayjs.default)().startOf("day").toDate();
38
+ const todayEnd = (0, import_dayjs.default)().endOf("day").toDate();
39
+ const weekStart = (0, import_dayjs.default)().subtract(6, "day").startOf("day").toDate();
40
+ const monthStart = (0, import_dayjs.default)().subtract(29, "day").startOf("day").toDate();
41
+ try {
42
+ const last30DaysData = await repo.find({
43
+ filter: {
44
+ key: "sign-in",
45
+ createdAt: {
46
+ $gte: monthStart.toISOString(),
47
+ $lte: todayEnd.toISOString()
48
+ }
49
+ }
50
+ });
51
+ const dayUserMap = /* @__PURE__ */ new Map();
52
+ for (const item of last30DaysData) {
53
+ const createdAt = item.createdAt || ((_a = item.values) == null ? void 0 : _a.createdAt);
54
+ const account = (_c = (_b = item.values) == null ? void 0 : _b.payload) == null ? void 0 : _c.account;
55
+ if (!createdAt || !account) continue;
56
+ const dateStr = (0, import_dayjs.default)(createdAt).format("YYYY-MM-DD");
57
+ if (!dayUserMap.has(dateStr)) {
58
+ dayUserMap.set(dateStr, /* @__PURE__ */ new Set());
59
+ }
60
+ dayUserMap.get(dateStr).add(account);
61
+ }
62
+ const todayKey = (0, import_dayjs.default)().format("YYYY-MM-DD");
63
+ const todayActiveUserCount = ((_d = dayUserMap.get(todayKey)) == null ? void 0 : _d.size) || 0;
64
+ const past7Days = Array.from({ length: 7 }, (_, i) => (0, import_dayjs.default)().subtract(i, "day").format("YYYY-MM-DD"));
65
+ const past30Days = Array.from({ length: 30 }, (_, i) => (0, import_dayjs.default)().subtract(i, "day").format("YYYY-MM-DD"));
66
+ const average = (dates) => {
67
+ const total = dates.reduce((sum, dateStr) => {
68
+ var _a2;
69
+ return sum + (((_a2 = dayUserMap.get(dateStr)) == null ? void 0 : _a2.size) || 0);
70
+ }, 0);
71
+ return Math.round(total / dates.length);
72
+ };
73
+ const average7 = average(past7Days);
74
+ const average30 = average(past30Days);
75
+ return { todayActiveUserCount, average7, average30 };
76
+ } catch (error) {
77
+ console.error("Failed to fetch tracking events:", error);
78
+ return { todayActiveUserCount: 0, average7: 0, average30: 0 };
79
+ }
80
+ };
81
+ // Annotate the CommonJS export names for ESM import in node:
82
+ 0 && (module.exports = {
83
+ getDailyActiveUser
84
+ });
@@ -0,0 +1,17 @@
1
+ type FilterConfig = {
2
+ filterKey: string | string[];
3
+ filterValues?: Record<string, any>;
4
+ dedupBy?: string;
5
+ minCount: number;
6
+ timeFilter?: {
7
+ after?: string;
8
+ before?: string;
9
+ on?: string;
10
+ today?: true;
11
+ rangeDays?: number;
12
+ };
13
+ timeGroup?: string;
14
+ };
15
+ export declare function countDataByEventFrequency(data: any[], config: FilterConfig): number;
16
+ export declare function groupDataByTime(data: any[], config: FilterConfig): Record<string, number>;
17
+ export {};
@@ -0,0 +1,208 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var getStatistics_exports = {};
29
+ __export(getStatistics_exports, {
30
+ countDataByEventFrequency: () => countDataByEventFrequency,
31
+ groupDataByTime: () => groupDataByTime
32
+ });
33
+ module.exports = __toCommonJS(getStatistics_exports);
34
+ var import_dayjs = __toESM(require("dayjs"));
35
+ function getValueByPath(obj, path) {
36
+ return path.split(".").reduce((acc, key) => acc == null ? void 0 : acc[key], obj);
37
+ }
38
+ function isSameDay(date1, date2) {
39
+ return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate();
40
+ }
41
+ function countDataByEventFrequency(data, config) {
42
+ var _a;
43
+ const { filterKey, filterValues = {}, dedupBy, minCount = 1, timeFilter } = config;
44
+ const matchKey = (itemKey) => {
45
+ if (Array.isArray(filterKey)) return filterKey.includes(itemKey);
46
+ return itemKey === filterKey;
47
+ };
48
+ const matchesValues = (values) => {
49
+ return Object.entries(filterValues).every(([k, v]) => values[k] === v);
50
+ };
51
+ const matchesTime = (item) => {
52
+ if (!timeFilter) return true;
53
+ const raw = item.createdAt;
54
+ if (!raw) return false;
55
+ const time = new Date(raw);
56
+ if (isNaN(time.getTime())) return false;
57
+ const now = /* @__PURE__ */ new Date();
58
+ if (timeFilter.rangeDays !== void 0) {
59
+ const start = (0, import_dayjs.default)().subtract(timeFilter.rangeDays - 1, "day").startOf("day").toDate();
60
+ const end = (0, import_dayjs.default)().endOf("day").toDate();
61
+ return time >= start && time <= end;
62
+ }
63
+ if (timeFilter.today) {
64
+ return isSameDay(time, /* @__PURE__ */ new Date());
65
+ }
66
+ if (timeFilter.on) {
67
+ const target = new Date(timeFilter.on);
68
+ if (isNaN(target.getTime())) return false;
69
+ return isSameDay(time, target);
70
+ }
71
+ if (timeFilter.after) {
72
+ const after = new Date(timeFilter.after);
73
+ if (isNaN(after.getTime())) return false;
74
+ if (time < after) return false;
75
+ }
76
+ if (timeFilter.before) {
77
+ const before = new Date(timeFilter.before);
78
+ if (isNaN(before.getTime())) return false;
79
+ if (time > before) return false;
80
+ }
81
+ return true;
82
+ };
83
+ const groupMap = {};
84
+ for (const item of data) {
85
+ if (!matchKey(item.key)) continue;
86
+ if (!matchesValues(item.values)) continue;
87
+ if (!matchesTime(item)) continue;
88
+ const key = dedupBy ? getValueByPath(item.values, dedupBy) : "__no_dedup__";
89
+ if (!key) continue;
90
+ if (!groupMap[key]) groupMap[key] = [];
91
+ groupMap[key].push(item);
92
+ }
93
+ let count = 0;
94
+ if (dedupBy) {
95
+ for (const key in groupMap) {
96
+ if (groupMap[key].length >= minCount) {
97
+ count++;
98
+ }
99
+ }
100
+ } else {
101
+ count = ((_a = groupMap["__no_dedup__"]) == null ? void 0 : _a.length) ?? 0;
102
+ if (count < minCount) {
103
+ count = 0;
104
+ }
105
+ }
106
+ return count;
107
+ }
108
+ function groupDataByTime(data, config) {
109
+ const { filterKey, filterValues = {}, dedupBy, minCount = 1, timeFilter, timeGroup = "day" } = config;
110
+ const matchKey = (itemKey) => {
111
+ if (Array.isArray(filterKey)) return filterKey.includes(itemKey);
112
+ return itemKey === filterKey;
113
+ };
114
+ const matchesValues = (values) => {
115
+ return Object.entries(filterValues).every(([k, v]) => values[k] === v);
116
+ };
117
+ const matchesTime = (item) => {
118
+ if (!timeFilter) return true;
119
+ const raw = item.createdAt;
120
+ if (!raw) return false;
121
+ const time = new Date(raw);
122
+ if (isNaN(time.getTime())) return false;
123
+ if (timeFilter.rangeDays !== void 0) {
124
+ const start2 = (0, import_dayjs.default)().subtract(timeFilter.rangeDays - 1, "day").startOf("day").toDate();
125
+ const end = (0, import_dayjs.default)().endOf("day").toDate();
126
+ return time >= start2 && time <= end;
127
+ }
128
+ if (timeFilter.today) {
129
+ return isSameDay(time, /* @__PURE__ */ new Date());
130
+ }
131
+ if (timeFilter.on) {
132
+ const target = new Date(timeFilter.on);
133
+ if (isNaN(target.getTime())) return false;
134
+ return isSameDay(time, target);
135
+ }
136
+ if (timeFilter.after) {
137
+ const after = new Date(timeFilter.after);
138
+ if (isNaN(after.getTime())) return false;
139
+ if (time < after) return false;
140
+ }
141
+ if (timeFilter.before) {
142
+ const before = new Date(timeFilter.before);
143
+ if (isNaN(before.getTime())) return false;
144
+ if (time > before) return false;
145
+ }
146
+ return true;
147
+ };
148
+ const range = (timeFilter == null ? void 0 : timeFilter.rangeDays) ?? 30;
149
+ const now = (0, import_dayjs.default)().endOf("day");
150
+ const start = (0, import_dayjs.default)().subtract(range - 1, "day").startOf("day");
151
+ const dateMap = {};
152
+ for (let i = 0; i < range; i++) {
153
+ const date = start.add(i, "day");
154
+ let key;
155
+ if (timeGroup === "week") {
156
+ const start2 = date.startOf("week");
157
+ const end = date.endOf("week");
158
+ key = `${start2.format("MM-DD")}~${end.format("MM-DD")}`;
159
+ } else if (timeGroup === "month") {
160
+ key = date.startOf("month").format("YYYY-MM");
161
+ } else {
162
+ key = date.format("MM-DD");
163
+ }
164
+ dateMap[key] = [];
165
+ }
166
+ for (const item of data) {
167
+ if (!matchKey(item.key)) continue;
168
+ if (!matchesValues(item.values)) continue;
169
+ if (!matchesTime(item)) continue;
170
+ const time = (0, import_dayjs.default)(item.createdAt);
171
+ let groupKey;
172
+ if (timeGroup === "week") {
173
+ const start2 = time.startOf("week");
174
+ const end = time.endOf("week");
175
+ groupKey = `${start2.format("MM-DD")}~${end.format("MM-DD")}`;
176
+ } else if (timeGroup === "month") {
177
+ groupKey = time.startOf("month").format("YYYY-MM");
178
+ } else {
179
+ groupKey = time.format("MM-DD");
180
+ }
181
+ if (!dateMap[groupKey]) {
182
+ dateMap[groupKey] = [];
183
+ }
184
+ dateMap[groupKey].push(item);
185
+ }
186
+ const result = {};
187
+ for (const key in dateMap) {
188
+ const group = dateMap[key];
189
+ if (dedupBy) {
190
+ const dedupSet = /* @__PURE__ */ new Map();
191
+ for (const item of group) {
192
+ const id = getValueByPath(item.values, dedupBy);
193
+ if (!id) continue;
194
+ dedupSet.set(id, (dedupSet.get(id) ?? 0) + 1);
195
+ }
196
+ result[key] = Array.from(dedupSet.values()).filter((v) => v >= minCount).length;
197
+ } else {
198
+ const count = group.length;
199
+ result[key] = count >= minCount ? count : 0;
200
+ }
201
+ }
202
+ return result;
203
+ }
204
+ // Annotate the CommonJS export names for ESM import in node:
205
+ 0 && (module.exports = {
206
+ countDataByEventFrequency,
207
+ groupDataByTime
208
+ });
@@ -0,0 +1 @@
1
+ export { default } from './plugin';
@@ -0,0 +1,33 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var server_exports = {};
29
+ __export(server_exports, {
30
+ default: () => import_plugin.default
31
+ });
32
+ module.exports = __toCommonJS(server_exports);
33
+ var import_plugin = __toESM(require("./plugin"));
@@ -0,0 +1,8 @@
1
+ import { Plugin } from '@tachybase/server';
2
+ import { ServerTrackingFilter } from './ServerTrackingFilter';
3
+ export declare class ModuleInstrumentationServer extends Plugin {
4
+ serverTrackingFilter: ServerTrackingFilter;
5
+ addServerTrackingListener(): Promise<void>;
6
+ load(): Promise<void>;
7
+ }
8
+ export default ModuleInstrumentationServer;
@@ -0,0 +1,161 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
7
+ var __typeError = (msg) => {
8
+ throw TypeError(msg);
9
+ };
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
+ var __decoratorStart = (base) => [, , , __create((base == null ? void 0 : base[__knownSymbol("metadata")]) ?? null)];
26
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
27
+ var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
28
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
29
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
30
+ var __runInitializers = (array, flags, self, value) => {
31
+ for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
32
+ return value;
33
+ };
34
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
35
+ var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
36
+ var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
37
+ var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
38
+ var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
39
+ return __privateGet(this, extra);
40
+ }, set [name](x) {
41
+ return __privateSet(this, extra, x);
42
+ } }, name));
43
+ k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
44
+ for (var i = decorators.length - 1; i >= 0; i--) {
45
+ ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
46
+ if (k) {
47
+ ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
48
+ if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
49
+ if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
50
+ }
51
+ it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
52
+ if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
53
+ else if (typeof it !== "object" || it === null) __typeError("Object expected");
54
+ else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
55
+ }
56
+ return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
57
+ };
58
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
59
+ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
60
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
61
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
62
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
63
+ var plugin_exports = {};
64
+ __export(plugin_exports, {
65
+ ModuleInstrumentationServer: () => ModuleInstrumentationServer,
66
+ default: () => plugin_default
67
+ });
68
+ module.exports = __toCommonJS(plugin_exports);
69
+ var import_node_worker_threads = require("node:worker_threads");
70
+ var import_server = require("@tachybase/server");
71
+ var import_tracking_controller = require("./actions/tracking-controller");
72
+ var import_afterAction = require("./hooks/afterAction");
73
+ var import_ServerTrackingFilter = require("./ServerTrackingFilter");
74
+ var _ModuleInstrumentationServer_decorators, _init, _a;
75
+ _ModuleInstrumentationServer_decorators = [(0, import_server.InjectedPlugin)({
76
+ Controllers: [import_tracking_controller.TrackingController]
77
+ })];
78
+ class ModuleInstrumentationServer extends (_a = import_server.Plugin) {
79
+ constructor() {
80
+ super(...arguments);
81
+ this.serverTrackingFilter = null;
82
+ }
83
+ async addServerTrackingListener() {
84
+ this.app.on("afterStart", async () => {
85
+ const SignInTracking = await this.app.db.getRepository("trackingConfig").findOne({
86
+ filter: {
87
+ title: "sign-in",
88
+ resourceName: "auth",
89
+ action: "signIn"
90
+ }
91
+ });
92
+ if (!SignInTracking) {
93
+ await this.app.db.getRepository("trackingConfig").create({
94
+ values: {
95
+ title: "sign-in",
96
+ resourceName: "auth",
97
+ action: "signIn",
98
+ trackingOptions: {
99
+ meta: ["userId", "recordId", "createdAt"],
100
+ filter: {
101
+ $and: [
102
+ {
103
+ payload: {
104
+ errors: {
105
+ $exists: false
106
+ }
107
+ }
108
+ }
109
+ ]
110
+ },
111
+ payload: ["errors", "account"]
112
+ }
113
+ }
114
+ });
115
+ }
116
+ this.serverTrackingFilter = new import_ServerTrackingFilter.ServerTrackingFilter(this.db);
117
+ await this.serverTrackingFilter.load();
118
+ });
119
+ this.app.use(
120
+ async (ctx, next) => {
121
+ var _a2;
122
+ await next();
123
+ if (ctx.action) {
124
+ const { actionName, resourceName } = ctx.action;
125
+ if ((_a2 = this.serverTrackingFilter) == null ? void 0 : _a2.check(resourceName, actionName)) {
126
+ const whiteList = this.serverTrackingFilter.whiteList;
127
+ return await (0, import_afterAction.handleOtherAction)(ctx, next, whiteList);
128
+ }
129
+ }
130
+ },
131
+ { tag: "trackingConfig", before: "errorHandler" }
132
+ );
133
+ }
134
+ async load() {
135
+ if (import_node_worker_threads.isMainThread) {
136
+ this.addServerTrackingListener();
137
+ }
138
+ this.app.acl.allow("instrumentation", "create", "public");
139
+ this.app.acl.allow("instrumentation", "list", "loggedIn");
140
+ this.app.acl.registerSnippet({
141
+ name: `pm.system-services.custom-instrumentation.clientTracking`,
142
+ actions: ["trackingEvents:*"]
143
+ });
144
+ this.app.acl.registerSnippet({
145
+ name: `pm.system-services.custom-instrumentation.trackingConfig`,
146
+ actions: ["trackingConfig:*"]
147
+ });
148
+ this.app.acl.registerSnippet({
149
+ name: `pm.system-services.custom-instrumentation.trackingStatistics`,
150
+ actions: ["statisticsConfig:*"]
151
+ });
152
+ }
153
+ }
154
+ _init = __decoratorStart(_a);
155
+ ModuleInstrumentationServer = __decorateElement(_init, 0, "ModuleInstrumentationServer", _ModuleInstrumentationServer_decorators, ModuleInstrumentationServer);
156
+ __runInitializers(_init, 1, ModuleInstrumentationServer);
157
+ var plugin_default = ModuleInstrumentationServer;
158
+ // Annotate the CommonJS export names for ESM import in node:
159
+ 0 && (module.exports = {
160
+ ModuleInstrumentationServer
161
+ });
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@tachybase/module-instrumentation",
3
+ "displayName": "Custom instrumentation",
4
+ "version": "1.0.22",
5
+ "description": "A module for tracking and instrumentation in Tachybase.",
6
+ "keywords": [
7
+ "Logging and monitoring"
8
+ ],
9
+ "main": "dist/server/index.js",
10
+ "devDependencies": {
11
+ "@antv/g2": "^5.3.0",
12
+ "antd": "5.22.5",
13
+ "dayjs": "1.11.13",
14
+ "lodash": "^4.17.21"
15
+ },
16
+ "peerDependencies": {
17
+ "@tachybase/actions": "1.0.25",
18
+ "@tachybase/client": "1.0.25",
19
+ "@tachybase/database": "1.0.25",
20
+ "@tachybase/schema": "1.0.25",
21
+ "@tachybase/server": "1.0.25",
22
+ "@tachybase/test": "1.0.25",
23
+ "@tachybase/utils": "1.0.25"
24
+ },
25
+ "description.zh-CN": "Tachybase 应用的追踪和埋点模块",
26
+ "displayName.zh-CN": "埋点追踪"
27
+ }
package/server.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './dist/server';
2
+ export { default } from './dist/server';
package/server.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/server/index.js');