@lssm/lib.metering 0.0.0-canary-20251217080011 → 1.41.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/dist/aggregation/index.js +1 -271
- package/dist/contracts/index.js +1 -1034
- package/dist/docs/index.js +1 -1
- package/dist/docs/metering.docblock.js +2 -22
- package/dist/entities/index.js +1 -418
- package/dist/events.js +1 -379
- package/dist/index.js +1 -8
- package/dist/metering.feature.js +1 -125
- package/package.json +13 -14
- package/dist/aggregation/index.d.ts +0 -155
- package/dist/contracts/dist/capabilities/openbanking.js +0 -88
- package/dist/contracts/dist/client/index.js +0 -5
- package/dist/contracts/dist/client/react/feature-render.js +0 -2
- package/dist/contracts/dist/client/react/form-render.js +0 -4
- package/dist/contracts/dist/client/react/index.js +0 -4
- package/dist/contracts/dist/contract-registry/index.js +0 -1
- package/dist/contracts/dist/contract-registry/schemas.js +0 -60
- package/dist/contracts/dist/docs/PUBLISHING.docblock.js +0 -16
- package/dist/contracts/dist/docs/accessibility_wcag_compliance_specs.docblock.js +0 -16
- package/dist/contracts/dist/docs/index.js +0 -29
- package/dist/contracts/dist/docs/presentations.js +0 -71
- package/dist/contracts/dist/docs/registry.js +0 -44
- package/dist/contracts/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/auth/better-auth-nextjs.docblock.js +0 -80
- package/dist/contracts/dist/docs/tech/contracts/openapi-export.docblock.js +0 -57
- package/dist/contracts/dist/docs/tech/lifecycle-stage-system.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/llm/llm-integration.docblock.js +0 -357
- package/dist/contracts/dist/docs/tech/mcp-endpoints.docblock.js +0 -37
- package/dist/contracts/dist/docs/tech/presentation-runtime.docblock.js +0 -16
- package/dist/contracts/dist/docs/tech/schema/README.docblock.js +0 -20
- package/dist/contracts/dist/docs/tech/studio/learning-events.docblock.js +0 -48
- package/dist/contracts/dist/docs/tech/studio/learning-journeys.docblock.js +0 -79
- package/dist/contracts/dist/docs/tech/studio/platform-admin-panel.docblock.js +0 -84
- package/dist/contracts/dist/docs/tech/studio/project-access-teams.docblock.js +0 -45
- package/dist/contracts/dist/docs/tech/studio/project-routing.docblock.js +0 -67
- package/dist/contracts/dist/docs/tech/studio/sandbox-unlogged.docblock.js +0 -40
- package/dist/contracts/dist/docs/tech/studio/team-invitations.docblock.js +0 -69
- package/dist/contracts/dist/docs/tech/studio/workspace-ops.docblock.js +0 -47
- package/dist/contracts/dist/docs/tech/studio/workspaces.docblock.js +0 -62
- package/dist/contracts/dist/docs/tech/telemetry-ingest.docblock.js +0 -155
- package/dist/contracts/dist/docs/tech/templates/runtime.docblock.js +0 -20
- package/dist/contracts/dist/docs/tech/vscode-extension.docblock.js +0 -101
- package/dist/contracts/dist/docs/tech/workflows/overview.docblock.js +0 -20
- package/dist/contracts/dist/events.js +0 -10
- package/dist/contracts/dist/experiments/evaluator.js +0 -1
- package/dist/contracts/dist/index.js +0 -71
- package/dist/contracts/dist/install.js +0 -2
- package/dist/contracts/dist/integrations/contracts.js +0 -377
- package/dist/contracts/dist/integrations/index.js +0 -18
- package/dist/contracts/dist/integrations/openbanking/contracts/accounts.js +0 -228
- package/dist/contracts/dist/integrations/openbanking/contracts/balances.js +0 -159
- package/dist/contracts/dist/integrations/openbanking/contracts/index.js +0 -3
- package/dist/contracts/dist/integrations/openbanking/contracts/transactions.js +0 -210
- package/dist/contracts/dist/integrations/openbanking/models.js +0 -242
- package/dist/contracts/dist/integrations/openbanking/telemetry.js +0 -13
- package/dist/contracts/dist/integrations/providers/elevenlabs.js +0 -52
- package/dist/contracts/dist/integrations/providers/gcs-storage.js +0 -75
- package/dist/contracts/dist/integrations/providers/gmail.js +0 -87
- package/dist/contracts/dist/integrations/providers/google-calendar.js +0 -66
- package/dist/contracts/dist/integrations/providers/index.js +0 -11
- package/dist/contracts/dist/integrations/providers/mistral.js +0 -68
- package/dist/contracts/dist/integrations/providers/postmark.js +0 -68
- package/dist/contracts/dist/integrations/providers/powens.js +0 -116
- package/dist/contracts/dist/integrations/providers/qdrant.js +0 -73
- package/dist/contracts/dist/integrations/providers/registry.js +0 -10
- package/dist/contracts/dist/integrations/providers/stripe.js +0 -83
- package/dist/contracts/dist/integrations/providers/twilio-sms.js +0 -61
- package/dist/contracts/dist/jsonschema.js +0 -1
- package/dist/contracts/dist/knowledge/contracts.js +0 -306
- package/dist/contracts/dist/knowledge/index.js +0 -7
- package/dist/contracts/dist/knowledge/spaces/email-threads.js +0 -34
- package/dist/contracts/dist/knowledge/spaces/financial-docs.js +0 -34
- package/dist/contracts/dist/knowledge/spaces/financial-overview.js +0 -38
- package/dist/contracts/dist/knowledge/spaces/index.js +0 -6
- package/dist/contracts/dist/knowledge/spaces/product-canon.js +0 -34
- package/dist/contracts/dist/knowledge/spaces/support-faq.js +0 -37
- package/dist/contracts/dist/knowledge/spaces/uploaded-docs.js +0 -34
- package/dist/contracts/dist/llm/exporters.js +0 -19
- package/dist/contracts/dist/llm/index.js +0 -2
- package/dist/contracts/dist/llm/prompts.js +0 -1
- package/dist/contracts/dist/onboarding-base.js +0 -196
- package/dist/contracts/dist/openapi.js +0 -1
- package/dist/contracts/dist/ownership.js +0 -21
- package/dist/contracts/dist/presentations.js +0 -1
- package/dist/contracts/dist/presentations.v2.js +0 -11
- package/dist/contracts/dist/prompt.js +0 -1
- package/dist/contracts/dist/promptRegistry.js +0 -1
- package/dist/contracts/dist/regenerator/index.js +0 -1
- package/dist/contracts/dist/regenerator/service.js +0 -6
- package/dist/contracts/dist/registry.js +0 -2
- package/dist/contracts/dist/resources.js +0 -1
- package/dist/contracts/dist/schema/dist/EnumType.js +0 -2
- package/dist/contracts/dist/schema/dist/FieldType.js +0 -49
- package/dist/contracts/dist/schema/dist/ScalarTypeEnum.js +0 -236
- package/dist/contracts/dist/schema/dist/SchemaModel.js +0 -34
- package/dist/contracts/dist/schema/dist/entity/defineEntity.js +0 -1
- package/dist/contracts/dist/schema/dist/entity/index.js +0 -2
- package/dist/contracts/dist/schema/dist/entity/types.js +0 -1
- package/dist/contracts/dist/schema/dist/index.js +0 -6
- package/dist/contracts/dist/server/graphql-pothos.js +0 -6
- package/dist/contracts/dist/server/index.js +0 -8
- package/dist/contracts/dist/server/mcp/createMcpServer.js +0 -4
- package/dist/contracts/dist/server/mcp/registerPresentations.js +0 -2
- package/dist/contracts/dist/server/mcp/registerPrompts.js +0 -1
- package/dist/contracts/dist/server/mcp/registerResources.js +0 -2
- package/dist/contracts/dist/server/mcp/registerTools.js +0 -1
- package/dist/contracts/dist/server/provider-mcp.js +0 -1
- package/dist/contracts/dist/server/rest-elysia.js +0 -1
- package/dist/contracts/dist/server/rest-express.js +0 -1
- package/dist/contracts/dist/server/rest-generic.js +0 -1
- package/dist/contracts/dist/server/rest-next-app.js +0 -1
- package/dist/contracts/dist/server/rest-next-pages.js +0 -1
- package/dist/contracts/dist/spec.js +0 -34
- package/dist/contracts/dist/telemetry/index.js +0 -1
- package/dist/contracts/dist/telemetry/tracker.js +0 -1
- package/dist/contracts/dist/tests/index.js +0 -1
- package/dist/contracts/dist/tests/runner.js +0 -2
- package/dist/contracts/dist/workflow/index.js +0 -1
- package/dist/contracts/dist/workflow/runner.js +0 -1
- package/dist/contracts/index.d.ts +0 -1138
- package/dist/docs/index.d.ts +0 -1
- package/dist/docs/metering.docblock.d.ts +0 -1
- package/dist/entities/index.d.ts +0 -230
- package/dist/events.d.ts +0 -539
- package/dist/index.d.ts +0 -6
- package/dist/metering.feature.d.ts +0 -11
- package/dist/schema/dist/EnumType.js +0 -2
- package/dist/schema/dist/FieldType.js +0 -49
- package/dist/schema/dist/ScalarTypeEnum.js +0 -236
- package/dist/schema/dist/SchemaModel.js +0 -39
- package/dist/schema/dist/entity/defineEntity.js +0 -236
- package/dist/schema/dist/entity/index.js +0 -2
- package/dist/schema/dist/entity/types.js +0 -1
- package/dist/schema/dist/index.js +0 -6
|
@@ -1,271 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Get the start of a period for a given date.
|
|
4
|
-
*/
|
|
5
|
-
function getPeriodStart(date, periodType) {
|
|
6
|
-
const d = new Date(date);
|
|
7
|
-
switch (periodType) {
|
|
8
|
-
case "HOURLY":
|
|
9
|
-
d.setMinutes(0, 0, 0);
|
|
10
|
-
return d;
|
|
11
|
-
case "DAILY":
|
|
12
|
-
d.setHours(0, 0, 0, 0);
|
|
13
|
-
return d;
|
|
14
|
-
case "WEEKLY":
|
|
15
|
-
d.setHours(0, 0, 0, 0);
|
|
16
|
-
const day = d.getDay();
|
|
17
|
-
d.setDate(d.getDate() - day);
|
|
18
|
-
return d;
|
|
19
|
-
case "MONTHLY":
|
|
20
|
-
d.setHours(0, 0, 0, 0);
|
|
21
|
-
d.setDate(1);
|
|
22
|
-
return d;
|
|
23
|
-
case "YEARLY":
|
|
24
|
-
d.setHours(0, 0, 0, 0);
|
|
25
|
-
d.setMonth(0, 1);
|
|
26
|
-
return d;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Get the end of a period for a given date.
|
|
31
|
-
*/
|
|
32
|
-
function getPeriodEnd(date, periodType) {
|
|
33
|
-
const start = getPeriodStart(date, periodType);
|
|
34
|
-
switch (periodType) {
|
|
35
|
-
case "HOURLY": return new Date(start.getTime() + 3600 * 1e3);
|
|
36
|
-
case "DAILY": return new Date(start.getTime() + 1440 * 60 * 1e3);
|
|
37
|
-
case "WEEKLY": return new Date(start.getTime() + 10080 * 60 * 1e3);
|
|
38
|
-
case "MONTHLY": {
|
|
39
|
-
const end = new Date(start);
|
|
40
|
-
end.setMonth(end.getMonth() + 1);
|
|
41
|
-
return end;
|
|
42
|
-
}
|
|
43
|
-
case "YEARLY": {
|
|
44
|
-
const end = new Date(start);
|
|
45
|
-
end.setFullYear(end.getFullYear() + 1);
|
|
46
|
-
return end;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Format a period key for grouping.
|
|
52
|
-
*/
|
|
53
|
-
function formatPeriodKey(date, periodType) {
|
|
54
|
-
const start = getPeriodStart(date, periodType);
|
|
55
|
-
const year = start.getFullYear();
|
|
56
|
-
const month = String(start.getMonth() + 1).padStart(2, "0");
|
|
57
|
-
const day = String(start.getDate()).padStart(2, "0");
|
|
58
|
-
const hour = String(start.getHours()).padStart(2, "0");
|
|
59
|
-
switch (periodType) {
|
|
60
|
-
case "HOURLY": return `${year}-${month}-${day}T${hour}`;
|
|
61
|
-
case "DAILY": return `${year}-${month}-${day}`;
|
|
62
|
-
case "WEEKLY": return `${year}-W${getWeekNumber(start)}`;
|
|
63
|
-
case "MONTHLY": return `${year}-${month}`;
|
|
64
|
-
case "YEARLY": return `${year}`;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function getWeekNumber(date) {
|
|
68
|
-
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
69
|
-
const dayNum = d.getUTCDay() || 7;
|
|
70
|
-
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
|
71
|
-
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
72
|
-
const weekNum = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
|
73
|
-
return String(weekNum).padStart(2, "0");
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Usage aggregator.
|
|
77
|
-
*
|
|
78
|
-
* Aggregates usage records into summaries based on period type.
|
|
79
|
-
*/
|
|
80
|
-
var UsageAggregator = class {
|
|
81
|
-
storage;
|
|
82
|
-
batchSize;
|
|
83
|
-
constructor(options) {
|
|
84
|
-
this.storage = options.storage;
|
|
85
|
-
this.batchSize = options.batchSize || 1e3;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Aggregate usage records for a period.
|
|
89
|
-
*/
|
|
90
|
-
async aggregate(params) {
|
|
91
|
-
const { periodType, periodStart, metricKey } = params;
|
|
92
|
-
const periodEnd = params.periodEnd || getPeriodEnd(periodStart, periodType);
|
|
93
|
-
const result = {
|
|
94
|
-
periodType,
|
|
95
|
-
periodStart,
|
|
96
|
-
periodEnd,
|
|
97
|
-
recordsProcessed: 0,
|
|
98
|
-
summariesCreated: 0,
|
|
99
|
-
summariesUpdated: 0,
|
|
100
|
-
errors: []
|
|
101
|
-
};
|
|
102
|
-
const records = await this.storage.getUnaggregatedRecords({
|
|
103
|
-
metricKey,
|
|
104
|
-
periodStart,
|
|
105
|
-
periodEnd,
|
|
106
|
-
limit: this.batchSize
|
|
107
|
-
});
|
|
108
|
-
if (records.length === 0) return result;
|
|
109
|
-
const groups = this.groupRecords(records, periodType);
|
|
110
|
-
for (const [groupKey, groupRecords] of groups.entries()) try {
|
|
111
|
-
await this.aggregateGroup(groupKey, groupRecords, periodType, result);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
const [metricKey$1, subjectType, subjectId] = groupKey.split("::");
|
|
114
|
-
result.errors.push({
|
|
115
|
-
metricKey: metricKey$1,
|
|
116
|
-
subjectType,
|
|
117
|
-
subjectId,
|
|
118
|
-
error: error instanceof Error ? error.message : String(error)
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
const recordIds = records.map((r) => r.id);
|
|
122
|
-
await this.storage.markRecordsAggregated(recordIds, /* @__PURE__ */ new Date());
|
|
123
|
-
result.recordsProcessed = records.length;
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Group records by metric, subject, and period.
|
|
128
|
-
*/
|
|
129
|
-
groupRecords(records, periodType) {
|
|
130
|
-
const groups = /* @__PURE__ */ new Map();
|
|
131
|
-
for (const record of records) {
|
|
132
|
-
const periodKey = formatPeriodKey(record.timestamp, periodType);
|
|
133
|
-
const groupKey = `${record.metricKey}::${record.subjectType}::${record.subjectId}::${periodKey}`;
|
|
134
|
-
const existing = groups.get(groupKey) || [];
|
|
135
|
-
existing.push(record);
|
|
136
|
-
groups.set(groupKey, existing);
|
|
137
|
-
}
|
|
138
|
-
return groups;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Aggregate a group of records into a summary.
|
|
142
|
-
*/
|
|
143
|
-
async aggregateGroup(groupKey, records, periodType, result) {
|
|
144
|
-
const [metricKey, subjectType, subjectId] = groupKey.split("::");
|
|
145
|
-
if (!metricKey || !subjectType || !subjectId || records.length === 0) return;
|
|
146
|
-
const firstRecord = records[0];
|
|
147
|
-
const periodStart = getPeriodStart(firstRecord.timestamp, periodType);
|
|
148
|
-
const periodEnd = getPeriodEnd(firstRecord.timestamp, periodType);
|
|
149
|
-
const aggregationType = (await this.storage.getMetric(metricKey))?.aggregationType || "SUM";
|
|
150
|
-
const quantities = records.map((r) => r.quantity);
|
|
151
|
-
const aggregated = this.calculateAggregation(quantities, aggregationType);
|
|
152
|
-
await this.storage.upsertSummary({
|
|
153
|
-
metricKey,
|
|
154
|
-
subjectType,
|
|
155
|
-
subjectId,
|
|
156
|
-
periodType,
|
|
157
|
-
periodStart,
|
|
158
|
-
periodEnd,
|
|
159
|
-
totalQuantity: aggregated.total,
|
|
160
|
-
recordCount: records.length,
|
|
161
|
-
minQuantity: aggregated.min,
|
|
162
|
-
maxQuantity: aggregated.max,
|
|
163
|
-
avgQuantity: aggregated.avg
|
|
164
|
-
});
|
|
165
|
-
result.summariesCreated++;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Calculate aggregation values.
|
|
169
|
-
*/
|
|
170
|
-
calculateAggregation(quantities, aggregationType) {
|
|
171
|
-
if (quantities.length === 0) return {
|
|
172
|
-
total: 0,
|
|
173
|
-
min: 0,
|
|
174
|
-
max: 0,
|
|
175
|
-
avg: 0
|
|
176
|
-
};
|
|
177
|
-
const min = Math.min(...quantities);
|
|
178
|
-
const max = Math.max(...quantities);
|
|
179
|
-
const sum = quantities.reduce((a, b) => a + b, 0);
|
|
180
|
-
const avg = sum / quantities.length;
|
|
181
|
-
const count = quantities.length;
|
|
182
|
-
let total;
|
|
183
|
-
switch (aggregationType) {
|
|
184
|
-
case "COUNT":
|
|
185
|
-
total = count;
|
|
186
|
-
break;
|
|
187
|
-
case "SUM":
|
|
188
|
-
total = sum;
|
|
189
|
-
break;
|
|
190
|
-
case "AVG":
|
|
191
|
-
total = avg;
|
|
192
|
-
break;
|
|
193
|
-
case "MAX":
|
|
194
|
-
total = max;
|
|
195
|
-
break;
|
|
196
|
-
case "MIN":
|
|
197
|
-
total = min;
|
|
198
|
-
break;
|
|
199
|
-
case "LAST":
|
|
200
|
-
total = quantities[quantities.length - 1] ?? 0;
|
|
201
|
-
break;
|
|
202
|
-
default: total = sum;
|
|
203
|
-
}
|
|
204
|
-
return {
|
|
205
|
-
total,
|
|
206
|
-
min,
|
|
207
|
-
max,
|
|
208
|
-
avg
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
/**
|
|
213
|
-
* In-memory usage storage for testing.
|
|
214
|
-
*/
|
|
215
|
-
var InMemoryUsageStorage = class {
|
|
216
|
-
records = [];
|
|
217
|
-
summaries = /* @__PURE__ */ new Map();
|
|
218
|
-
metrics = /* @__PURE__ */ new Map();
|
|
219
|
-
addRecord(record) {
|
|
220
|
-
this.records.push(record);
|
|
221
|
-
}
|
|
222
|
-
addMetric(metric) {
|
|
223
|
-
this.metrics.set(metric.key, metric);
|
|
224
|
-
}
|
|
225
|
-
async getUnaggregatedRecords(options) {
|
|
226
|
-
let records = this.records.filter((r) => {
|
|
227
|
-
const inPeriod = r.timestamp >= options.periodStart && r.timestamp < options.periodEnd;
|
|
228
|
-
const matchesMetric = !options.metricKey || r.metricKey === options.metricKey;
|
|
229
|
-
return inPeriod && matchesMetric;
|
|
230
|
-
});
|
|
231
|
-
if (options.limit) records = records.slice(0, options.limit);
|
|
232
|
-
return records;
|
|
233
|
-
}
|
|
234
|
-
async markRecordsAggregated(recordIds) {
|
|
235
|
-
this.records = this.records.filter((r) => !recordIds.includes(r.id));
|
|
236
|
-
}
|
|
237
|
-
async upsertSummary(summary) {
|
|
238
|
-
const key = `${summary.metricKey}::${summary.subjectType}::${summary.subjectId}::${summary.periodType}::${summary.periodStart.toISOString()}`;
|
|
239
|
-
const existing = this.summaries.get(key);
|
|
240
|
-
if (existing) {
|
|
241
|
-
existing.totalQuantity += summary.totalQuantity;
|
|
242
|
-
existing.recordCount += summary.recordCount;
|
|
243
|
-
if (summary.minQuantity !== void 0) existing.minQuantity = Math.min(existing.minQuantity ?? Infinity, summary.minQuantity);
|
|
244
|
-
if (summary.maxQuantity !== void 0) existing.maxQuantity = Math.max(existing.maxQuantity ?? -Infinity, summary.maxQuantity);
|
|
245
|
-
return existing;
|
|
246
|
-
}
|
|
247
|
-
const newSummary = {
|
|
248
|
-
id: `summary-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
249
|
-
...summary
|
|
250
|
-
};
|
|
251
|
-
this.summaries.set(key, newSummary);
|
|
252
|
-
return newSummary;
|
|
253
|
-
}
|
|
254
|
-
async getMetric(key) {
|
|
255
|
-
return this.metrics.get(key) || null;
|
|
256
|
-
}
|
|
257
|
-
async listMetrics() {
|
|
258
|
-
return Array.from(this.metrics.values());
|
|
259
|
-
}
|
|
260
|
-
getSummaries() {
|
|
261
|
-
return Array.from(this.summaries.values());
|
|
262
|
-
}
|
|
263
|
-
clear() {
|
|
264
|
-
this.records = [];
|
|
265
|
-
this.summaries.clear();
|
|
266
|
-
this.metrics.clear();
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
//#endregion
|
|
271
|
-
export { InMemoryUsageStorage, UsageAggregator, formatPeriodKey, getPeriodEnd, getPeriodStart };
|
|
1
|
+
function e(e,t){let n=new Date(e);switch(t){case`HOURLY`:return n.setMinutes(0,0,0),n;case`DAILY`:return n.setHours(0,0,0,0),n;case`WEEKLY`:n.setHours(0,0,0,0);let e=n.getDay();return n.setDate(n.getDate()-e),n;case`MONTHLY`:return n.setHours(0,0,0,0),n.setDate(1),n;case`YEARLY`:return n.setHours(0,0,0,0),n.setMonth(0,1),n}}function t(t,n){let r=e(t,n);switch(n){case`HOURLY`:return new Date(r.getTime()+3600*1e3);case`DAILY`:return new Date(r.getTime()+1440*60*1e3);case`WEEKLY`:return new Date(r.getTime()+10080*60*1e3);case`MONTHLY`:{let e=new Date(r);return e.setMonth(e.getMonth()+1),e}case`YEARLY`:{let e=new Date(r);return e.setFullYear(e.getFullYear()+1),e}}}function n(t,n){let i=e(t,n),a=i.getFullYear(),o=String(i.getMonth()+1).padStart(2,`0`),s=String(i.getDate()).padStart(2,`0`),c=String(i.getHours()).padStart(2,`0`);switch(n){case`HOURLY`:return`${a}-${o}-${s}T${c}`;case`DAILY`:return`${a}-${o}-${s}`;case`WEEKLY`:return`${a}-W${r(i)}`;case`MONTHLY`:return`${a}-${o}`;case`YEARLY`:return`${a}`}}function r(e){let t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate())),n=t.getUTCDay()||7;t.setUTCDate(t.getUTCDate()+4-n);let r=new Date(Date.UTC(t.getUTCFullYear(),0,1)),i=Math.ceil(((t.getTime()-r.getTime())/864e5+1)/7);return String(i).padStart(2,`0`)}var i=class{storage;batchSize;constructor(e){this.storage=e.storage,this.batchSize=e.batchSize||1e3}async aggregate(e){let{periodType:n,periodStart:r,metricKey:i}=e,a=e.periodEnd||t(r,n),o={periodType:n,periodStart:r,periodEnd:a,recordsProcessed:0,summariesCreated:0,summariesUpdated:0,errors:[]},s=await this.storage.getUnaggregatedRecords({metricKey:i,periodStart:r,periodEnd:a,limit:this.batchSize});if(s.length===0)return o;let c=this.groupRecords(s,n);for(let[e,t]of c.entries())try{await this.aggregateGroup(e,t,n,o)}catch(t){let[n,r,i]=e.split(`::`);o.errors.push({metricKey:n,subjectType:r,subjectId:i,error:t instanceof Error?t.message:String(t)})}let l=s.map(e=>e.id);return await this.storage.markRecordsAggregated(l,new Date),o.recordsProcessed=s.length,o}groupRecords(e,t){let r=new Map;for(let i of e){let e=n(i.timestamp,t),a=`${i.metricKey}::${i.subjectType}::${i.subjectId}::${e}`,o=r.get(a)||[];o.push(i),r.set(a,o)}return r}async aggregateGroup(n,r,i,a){let[o,s,c]=n.split(`::`);if(!o||!s||!c||r.length===0)return;let l=r[0],u=e(l.timestamp,i),d=t(l.timestamp,i),f=(await this.storage.getMetric(o))?.aggregationType||`SUM`,p=r.map(e=>e.quantity),m=this.calculateAggregation(p,f);await this.storage.upsertSummary({metricKey:o,subjectType:s,subjectId:c,periodType:i,periodStart:u,periodEnd:d,totalQuantity:m.total,recordCount:r.length,minQuantity:m.min,maxQuantity:m.max,avgQuantity:m.avg}),a.summariesCreated++}calculateAggregation(e,t){if(e.length===0)return{total:0,min:0,max:0,avg:0};let n=Math.min(...e),r=Math.max(...e),i=e.reduce((e,t)=>e+t,0),a=i/e.length,o=e.length,s;switch(t){case`COUNT`:s=o;break;case`SUM`:s=i;break;case`AVG`:s=a;break;case`MAX`:s=r;break;case`MIN`:s=n;break;case`LAST`:s=e[e.length-1]??0;break;default:s=i}return{total:s,min:n,max:r,avg:a}}},a=class{records=[];summaries=new Map;metrics=new Map;addRecord(e){this.records.push(e)}addMetric(e){this.metrics.set(e.key,e)}async getUnaggregatedRecords(e){let t=this.records.filter(t=>{let n=t.timestamp>=e.periodStart&&t.timestamp<e.periodEnd,r=!e.metricKey||t.metricKey===e.metricKey;return n&&r});return e.limit&&(t=t.slice(0,e.limit)),t}async markRecordsAggregated(e){this.records=this.records.filter(t=>!e.includes(t.id))}async upsertSummary(e){let t=`${e.metricKey}::${e.subjectType}::${e.subjectId}::${e.periodType}::${e.periodStart.toISOString()}`,n=this.summaries.get(t);if(n)return n.totalQuantity+=e.totalQuantity,n.recordCount+=e.recordCount,e.minQuantity!==void 0&&(n.minQuantity=Math.min(n.minQuantity??1/0,e.minQuantity)),e.maxQuantity!==void 0&&(n.maxQuantity=Math.max(n.maxQuantity??-1/0,e.maxQuantity)),n;let r={id:`summary-${Date.now()}-${Math.random().toString(36).slice(2)}`,...e};return this.summaries.set(t,r),r}async getMetric(e){return this.metrics.get(e)||null}async listMetrics(){return Array.from(this.metrics.values())}getSummaries(){return Array.from(this.summaries.values())}clear(){this.records=[],this.summaries.clear(),this.metrics.clear()}};export{a as InMemoryUsageStorage,i as UsageAggregator,n as formatPeriodKey,t as getPeriodEnd,e as getPeriodStart};
|