@zucker-framework/things 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/LICENSE +201 -0
- package/NOTICE +22 -0
- package/THIRD_PARTY_NOTICES +4 -0
- package/dist/index.d.mts +560 -0
- package/dist/index.d.ts +560 -0
- package/dist/index.js +451 -0
- package/dist/index.mjs +415 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,451 @@
|
|
|
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 __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
DefaultThingsDataService: () => DefaultThingsDataService,
|
|
25
|
+
EventLevel: () => EventLevel,
|
|
26
|
+
InMemoryThingManager: () => InMemoryThingManager,
|
|
27
|
+
PropertyAccessMode: () => PropertyAccessMode,
|
|
28
|
+
ThingState: () => ThingState,
|
|
29
|
+
ThingsModule: () => ThingsModule,
|
|
30
|
+
convertValue: () => convertValue,
|
|
31
|
+
createEventMessage: () => createEventMessage,
|
|
32
|
+
createMessageId: () => createMessageId,
|
|
33
|
+
createMetadata: () => createMetadata,
|
|
34
|
+
createReportPropertyMessage: () => createReportPropertyMessage,
|
|
35
|
+
mergeMetadata: () => mergeMetadata
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/data-type.ts
|
|
40
|
+
function convertValue(type, raw) {
|
|
41
|
+
if (raw === null || raw === void 0) return raw;
|
|
42
|
+
switch (type.id) {
|
|
43
|
+
case "int":
|
|
44
|
+
case "long": {
|
|
45
|
+
const n = Number(raw);
|
|
46
|
+
return isNaN(n) ? raw : Math.trunc(n);
|
|
47
|
+
}
|
|
48
|
+
case "float":
|
|
49
|
+
case "double": {
|
|
50
|
+
const n = Number(raw);
|
|
51
|
+
if (isNaN(n)) return raw;
|
|
52
|
+
if (type.scale !== void 0) {
|
|
53
|
+
return parseFloat(n.toFixed(type.scale));
|
|
54
|
+
}
|
|
55
|
+
return n;
|
|
56
|
+
}
|
|
57
|
+
case "boolean": {
|
|
58
|
+
if (typeof raw === "boolean") return raw;
|
|
59
|
+
const tv = type.trueValue ?? "true";
|
|
60
|
+
const fv = type.falseValue ?? "false";
|
|
61
|
+
if (String(raw) === tv) return true;
|
|
62
|
+
if (String(raw) === fv) return false;
|
|
63
|
+
return Boolean(raw);
|
|
64
|
+
}
|
|
65
|
+
case "string":
|
|
66
|
+
case "password":
|
|
67
|
+
return String(raw);
|
|
68
|
+
case "date": {
|
|
69
|
+
if (raw instanceof Date) return raw.getTime();
|
|
70
|
+
const n = Number(raw);
|
|
71
|
+
return isNaN(n) ? new Date(String(raw)).getTime() : n;
|
|
72
|
+
}
|
|
73
|
+
case "enum": {
|
|
74
|
+
const match = type.elements.find((e) => e.value === raw || String(e.value) === String(raw));
|
|
75
|
+
return match ? match.value : raw;
|
|
76
|
+
}
|
|
77
|
+
default:
|
|
78
|
+
return raw;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
__name(convertValue, "convertValue");
|
|
82
|
+
|
|
83
|
+
// src/metadata.ts
|
|
84
|
+
var PropertyAccessMode = /* @__PURE__ */ (function(PropertyAccessMode2) {
|
|
85
|
+
PropertyAccessMode2["READ"] = "r";
|
|
86
|
+
PropertyAccessMode2["WRITE"] = "w";
|
|
87
|
+
PropertyAccessMode2["READ_WRITE"] = "rw";
|
|
88
|
+
return PropertyAccessMode2;
|
|
89
|
+
})({});
|
|
90
|
+
var EventLevel = /* @__PURE__ */ (function(EventLevel2) {
|
|
91
|
+
EventLevel2["OTHER"] = "other";
|
|
92
|
+
EventLevel2["WARN"] = "warn";
|
|
93
|
+
EventLevel2["ERROR"] = "error";
|
|
94
|
+
return EventLevel2;
|
|
95
|
+
})({});
|
|
96
|
+
function mergeMetadata(base, patch) {
|
|
97
|
+
const mergeList = /* @__PURE__ */ __name((a, b = []) => {
|
|
98
|
+
const map = new Map(a.map((i) => [
|
|
99
|
+
i.id,
|
|
100
|
+
i
|
|
101
|
+
]));
|
|
102
|
+
for (const item of b) {
|
|
103
|
+
map.set(item.id, item);
|
|
104
|
+
}
|
|
105
|
+
return Array.from(map.values());
|
|
106
|
+
}, "mergeList");
|
|
107
|
+
return {
|
|
108
|
+
properties: mergeList(base.properties, patch.properties),
|
|
109
|
+
functions: mergeList(base.functions, patch.functions),
|
|
110
|
+
events: mergeList(base.events, patch.events),
|
|
111
|
+
tags: mergeList(base.tags ?? [], patch.tags)
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
__name(mergeMetadata, "mergeMetadata");
|
|
115
|
+
function createMetadata(partial = {}) {
|
|
116
|
+
return {
|
|
117
|
+
properties: partial.properties ?? [],
|
|
118
|
+
functions: partial.functions ?? [],
|
|
119
|
+
events: partial.events ?? [],
|
|
120
|
+
tags: partial.tags ?? []
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
__name(createMetadata, "createMetadata");
|
|
124
|
+
|
|
125
|
+
// src/thing.ts
|
|
126
|
+
var ThingState = /* @__PURE__ */ (function(ThingState2) {
|
|
127
|
+
ThingState2["INACTIVE"] = "notActive";
|
|
128
|
+
ThingState2["OFFLINE"] = "offline";
|
|
129
|
+
ThingState2["ONLINE"] = "online";
|
|
130
|
+
return ThingState2;
|
|
131
|
+
})({});
|
|
132
|
+
|
|
133
|
+
// src/thing-manager.ts
|
|
134
|
+
var import_common = require("@nestjs/common");
|
|
135
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
136
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
137
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
138
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
139
|
+
} else {
|
|
140
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
141
|
+
if (d = decorators[i]) {
|
|
142
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
147
|
+
}
|
|
148
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
149
|
+
var InMemoryThingManager = class {
|
|
150
|
+
static {
|
|
151
|
+
__name(this, "InMemoryThingManager");
|
|
152
|
+
}
|
|
153
|
+
types = /* @__PURE__ */ new Map();
|
|
154
|
+
things = /* @__PURE__ */ new Map();
|
|
155
|
+
async getThingType(typeId) {
|
|
156
|
+
return this.types.get(typeId);
|
|
157
|
+
}
|
|
158
|
+
async registerThingType(type) {
|
|
159
|
+
this.types.set(type.id, type);
|
|
160
|
+
}
|
|
161
|
+
async getThing(thingId) {
|
|
162
|
+
return this.things.get(thingId);
|
|
163
|
+
}
|
|
164
|
+
async registerThing(thing) {
|
|
165
|
+
const existing = this.things.get(thing.id);
|
|
166
|
+
this.things.set(thing.id, {
|
|
167
|
+
...existing,
|
|
168
|
+
...thing,
|
|
169
|
+
state: existing?.state ?? ThingState.INACTIVE
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async unregisterThing(thingId) {
|
|
173
|
+
this.things.delete(thingId);
|
|
174
|
+
}
|
|
175
|
+
async updateState(thingId, state, timestamp) {
|
|
176
|
+
const thing = this.things.get(thingId);
|
|
177
|
+
if (!thing) return;
|
|
178
|
+
const update = {
|
|
179
|
+
state
|
|
180
|
+
};
|
|
181
|
+
if (state === ThingState.ONLINE) {
|
|
182
|
+
update.onlineTime = timestamp ?? Date.now();
|
|
183
|
+
} else if (state === ThingState.OFFLINE) {
|
|
184
|
+
update.offlineTime = timestamp ?? Date.now();
|
|
185
|
+
}
|
|
186
|
+
this.things.set(thingId, {
|
|
187
|
+
...thing,
|
|
188
|
+
...update
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async getEffectiveMetadata(thingId) {
|
|
192
|
+
const thing = this.things.get(thingId);
|
|
193
|
+
if (!thing) return void 0;
|
|
194
|
+
const type = this.types.get(thing.thingTypeId);
|
|
195
|
+
if (!type) return void 0;
|
|
196
|
+
if (!thing.metadataPatch) {
|
|
197
|
+
return type.metadata;
|
|
198
|
+
}
|
|
199
|
+
return mergeMetadata(type.metadata, thing.metadataPatch);
|
|
200
|
+
}
|
|
201
|
+
/** 获取指定类型的所有实例 */
|
|
202
|
+
getThingsByType(typeId) {
|
|
203
|
+
return Array.from(this.things.values()).filter((t) => t.thingTypeId === typeId);
|
|
204
|
+
}
|
|
205
|
+
/** 获取所有在线实例数量 */
|
|
206
|
+
countOnline() {
|
|
207
|
+
return Array.from(this.things.values()).filter((t) => t.state === ThingState.ONLINE).length;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
InMemoryThingManager = _ts_decorate([
|
|
211
|
+
(0, import_common.Injectable)()
|
|
212
|
+
], InMemoryThingManager);
|
|
213
|
+
|
|
214
|
+
// src/message.ts
|
|
215
|
+
function createMessageId() {
|
|
216
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
217
|
+
}
|
|
218
|
+
__name(createMessageId, "createMessageId");
|
|
219
|
+
function createReportPropertyMessage(thingId, thingType, properties, extra) {
|
|
220
|
+
return {
|
|
221
|
+
messageType: "ReportProperty",
|
|
222
|
+
messageId: createMessageId(),
|
|
223
|
+
thingId,
|
|
224
|
+
thingType,
|
|
225
|
+
timestamp: Date.now(),
|
|
226
|
+
properties,
|
|
227
|
+
...extra
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
__name(createReportPropertyMessage, "createReportPropertyMessage");
|
|
231
|
+
function createEventMessage(thingId, thingType, event, data) {
|
|
232
|
+
return {
|
|
233
|
+
messageType: "Event",
|
|
234
|
+
messageId: createMessageId(),
|
|
235
|
+
thingId,
|
|
236
|
+
thingType,
|
|
237
|
+
timestamp: Date.now(),
|
|
238
|
+
event,
|
|
239
|
+
data
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
__name(createEventMessage, "createEventMessage");
|
|
243
|
+
|
|
244
|
+
// src/property-log.ts
|
|
245
|
+
var import_common2 = require("@nestjs/common");
|
|
246
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
247
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
248
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
249
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
250
|
+
} else {
|
|
251
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
252
|
+
if (d = decorators[i]) {
|
|
253
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
258
|
+
}
|
|
259
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
260
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
261
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
262
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
266
|
+
var DefaultThingsDataService = class {
|
|
267
|
+
static {
|
|
268
|
+
__name(this, "DefaultThingsDataService");
|
|
269
|
+
}
|
|
270
|
+
tsService;
|
|
271
|
+
constructor(tsService) {
|
|
272
|
+
this.tsService = tsService;
|
|
273
|
+
}
|
|
274
|
+
propertyMetric(thingType) {
|
|
275
|
+
return `thing_property_${thingType}`;
|
|
276
|
+
}
|
|
277
|
+
eventMetric(thingType, eventId) {
|
|
278
|
+
return `thing_event_${thingType}_${eventId}`;
|
|
279
|
+
}
|
|
280
|
+
async saveProperties(message) {
|
|
281
|
+
const metric = this.propertyMetric(message.thingType);
|
|
282
|
+
const points = Object.entries(message.properties).map(([key, value]) => ({
|
|
283
|
+
timestamp: message.propertySourceTimes?.[key] ?? message.timestamp,
|
|
284
|
+
tags: {
|
|
285
|
+
thingId: message.thingId,
|
|
286
|
+
thingType: message.thingType,
|
|
287
|
+
property: key
|
|
288
|
+
},
|
|
289
|
+
values: {
|
|
290
|
+
value: typeof value === "object" ? JSON.stringify(value) : value,
|
|
291
|
+
state: message.propertyStates?.[key] ?? "success"
|
|
292
|
+
}
|
|
293
|
+
}));
|
|
294
|
+
for (const point of points) {
|
|
295
|
+
const propMetric = `thing_property_${message.thingType}_${point.tags["property"]}`;
|
|
296
|
+
await this.tsService.save({
|
|
297
|
+
...point,
|
|
298
|
+
tags: {
|
|
299
|
+
thingId: point.tags["thingId"],
|
|
300
|
+
thingType: point.tags["thingType"]
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
void propMetric;
|
|
304
|
+
}
|
|
305
|
+
if (points.length > 0) {
|
|
306
|
+
await this.tsService.saveBatch(points.map((p) => ({
|
|
307
|
+
...p,
|
|
308
|
+
tags: {
|
|
309
|
+
...p.tags
|
|
310
|
+
},
|
|
311
|
+
values: {
|
|
312
|
+
...p.values,
|
|
313
|
+
metric
|
|
314
|
+
}
|
|
315
|
+
})));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
async saveEvent(message) {
|
|
319
|
+
const metric = this.eventMetric(message.thingType, message.event);
|
|
320
|
+
const data = {
|
|
321
|
+
timestamp: message.timestamp,
|
|
322
|
+
tags: {
|
|
323
|
+
thingId: message.thingId,
|
|
324
|
+
thingType: message.thingType,
|
|
325
|
+
event: message.event
|
|
326
|
+
},
|
|
327
|
+
values: {
|
|
328
|
+
data: typeof message.data === "object" ? JSON.stringify(message.data) : message.data,
|
|
329
|
+
metric
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
await this.tsService.save(data);
|
|
333
|
+
}
|
|
334
|
+
async queryPropertyLogs(query) {
|
|
335
|
+
const tsQuery = {
|
|
336
|
+
metric: this.propertyMetric(query.thingType),
|
|
337
|
+
from: query.from,
|
|
338
|
+
to: query.to,
|
|
339
|
+
tags: {
|
|
340
|
+
thingId: query.thingId,
|
|
341
|
+
property: query.id
|
|
342
|
+
},
|
|
343
|
+
limit: query.limit,
|
|
344
|
+
order: query.order
|
|
345
|
+
};
|
|
346
|
+
const results = await this.tsService.query(tsQuery);
|
|
347
|
+
return results.map((r) => ({
|
|
348
|
+
property: String(r.tags["property"] ?? query.id),
|
|
349
|
+
value: r.values["value"],
|
|
350
|
+
thingId: String(r.tags["thingId"]),
|
|
351
|
+
thingType: String(r.tags["thingType"] ?? query.thingType),
|
|
352
|
+
timestamp: r.timestamp,
|
|
353
|
+
state: r.values["state"]
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
async queryEventLogs(query) {
|
|
357
|
+
const tsQuery = {
|
|
358
|
+
metric: this.eventMetric(query.thingType, query.id),
|
|
359
|
+
from: query.from,
|
|
360
|
+
to: query.to,
|
|
361
|
+
tags: {
|
|
362
|
+
thingId: query.thingId
|
|
363
|
+
},
|
|
364
|
+
limit: query.limit,
|
|
365
|
+
order: query.order
|
|
366
|
+
};
|
|
367
|
+
const results = await this.tsService.query(tsQuery);
|
|
368
|
+
return results.map((r) => {
|
|
369
|
+
let data = r.values["data"];
|
|
370
|
+
if (typeof data === "string") {
|
|
371
|
+
try {
|
|
372
|
+
data = JSON.parse(data);
|
|
373
|
+
} catch {
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
event: String(r.tags["event"] ?? query.id),
|
|
378
|
+
data,
|
|
379
|
+
thingId: String(r.tags["thingId"]),
|
|
380
|
+
thingType: String(r.tags["thingType"] ?? query.thingType),
|
|
381
|
+
timestamp: r.timestamp
|
|
382
|
+
};
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
async aggregateProperties(thingId, thingType, property, aggQuery) {
|
|
386
|
+
const query = {
|
|
387
|
+
...aggQuery,
|
|
388
|
+
metric: this.propertyMetric(thingType),
|
|
389
|
+
tags: {
|
|
390
|
+
...aggQuery.tags,
|
|
391
|
+
thingId,
|
|
392
|
+
property
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
return this.tsService.aggregate(query);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
DefaultThingsDataService = _ts_decorate2([
|
|
399
|
+
(0, import_common2.Injectable)(),
|
|
400
|
+
_ts_metadata("design:type", Function),
|
|
401
|
+
_ts_metadata("design:paramtypes", [
|
|
402
|
+
typeof TimeSeriesService === "undefined" ? Object : TimeSeriesService
|
|
403
|
+
])
|
|
404
|
+
], DefaultThingsDataService);
|
|
405
|
+
|
|
406
|
+
// src/things.module.ts
|
|
407
|
+
var import_common3 = require("@nestjs/common");
|
|
408
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
409
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
410
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
411
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
412
|
+
} else {
|
|
413
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
414
|
+
if (d = decorators[i]) {
|
|
415
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
420
|
+
}
|
|
421
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
422
|
+
var ThingsModule = class {
|
|
423
|
+
static {
|
|
424
|
+
__name(this, "ThingsModule");
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
ThingsModule = _ts_decorate3([
|
|
428
|
+
(0, import_common3.Module)({
|
|
429
|
+
providers: [
|
|
430
|
+
InMemoryThingManager
|
|
431
|
+
],
|
|
432
|
+
exports: [
|
|
433
|
+
InMemoryThingManager
|
|
434
|
+
]
|
|
435
|
+
})
|
|
436
|
+
], ThingsModule);
|
|
437
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
438
|
+
0 && (module.exports = {
|
|
439
|
+
DefaultThingsDataService,
|
|
440
|
+
EventLevel,
|
|
441
|
+
InMemoryThingManager,
|
|
442
|
+
PropertyAccessMode,
|
|
443
|
+
ThingState,
|
|
444
|
+
ThingsModule,
|
|
445
|
+
convertValue,
|
|
446
|
+
createEventMessage,
|
|
447
|
+
createMessageId,
|
|
448
|
+
createMetadata,
|
|
449
|
+
createReportPropertyMessage,
|
|
450
|
+
mergeMetadata
|
|
451
|
+
});
|