tabletcommand-backend-models 7.4.91 → 7.4.93
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/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/models/battalion.js +16 -0
- package/build/models/battalion.js.map +1 -1
- package/build/models/esri.js +26 -0
- package/build/models/esri.js.map +1 -1
- package/build/models/kindtype-catalog.js +63 -0
- package/build/models/kindtype-catalog.js.map +1 -0
- package/build/models/location.js +24 -1
- package/build/models/location.js.map +1 -1
- package/build/test/0index.js +1 -0
- package/build/test/0index.js.map +1 -1
- package/build/test/battalion.js +14 -0
- package/build/test/battalion.js.map +1 -1
- package/build/test/esri.js +38 -0
- package/build/test/esri.js.map +1 -1
- package/build/test/kindtype-catalog.js +62 -0
- package/build/test/kindtype-catalog.js.map +1 -0
- package/build/test/location.js +30 -0
- package/build/test/location.js.map +1 -1
- package/build/test/mock.js +3 -0
- package/build/test/mock.js.map +1 -1
- package/build/types/kindtype-catalog.js +3 -0
- package/build/types/kindtype-catalog.js.map +1 -0
- package/cspell.json +1 -0
- package/definitions/index.d.ts +6 -0
- package/definitions/index.d.ts.map +1 -1
- package/definitions/models/battalion.d.ts.map +1 -1
- package/definitions/models/esri.d.ts.map +1 -1
- package/definitions/models/kindtype-catalog.d.ts +13 -0
- package/definitions/models/kindtype-catalog.d.ts.map +1 -0
- package/definitions/models/location.d.ts.map +1 -1
- package/definitions/test/kindtype-catalog.d.ts +2 -0
- package/definitions/test/kindtype-catalog.d.ts.map +1 -0
- package/definitions/test/mock.d.ts +3 -0
- package/definitions/test/mock.d.ts.map +1 -1
- package/definitions/types/battalion.d.ts +3 -0
- package/definitions/types/battalion.d.ts.map +1 -1
- package/definitions/types/kindtype-catalog.d.ts +15 -0
- package/definitions/types/kindtype-catalog.d.ts.map +1 -0
- package/definitions/types/location.d.ts +5 -0
- package/definitions/types/location.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/models/battalion.ts +16 -0
- package/src/models/esri.ts +28 -0
- package/src/models/kindtype-catalog.ts +73 -0
- package/src/models/location.ts +24 -1
- package/src/test/0index.ts +1 -0
- package/src/test/battalion.ts +14 -0
- package/src/test/esri.ts +46 -0
- package/src/test/kindtype-catalog.ts +60 -0
- package/src/test/location.ts +31 -0
- package/src/test/mock.ts +3 -0
- package/src/types/battalion.ts +3 -0
- package/src/types/kindtype-catalog.ts +15 -0
- package/src/types/location.ts +5 -0
package/src/test/esri.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assert } from "chai";
|
|
2
2
|
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
3
|
+
import { rejects as assertRejects } from "node:assert/strict";
|
|
3
4
|
import * as m from "../index";
|
|
4
5
|
import * as config from "./config";
|
|
5
6
|
import mockModule from "./mock";
|
|
@@ -59,4 +60,49 @@ describe("Esri", function() {
|
|
|
59
60
|
const props = mapPropsFound[0];
|
|
60
61
|
assert.equal(props?.download, true);
|
|
61
62
|
});
|
|
63
|
+
|
|
64
|
+
it("enforces unique arcGISAuth.username constraint", async function() {
|
|
65
|
+
await new models.Esri({
|
|
66
|
+
departmentId: new mongoose.Types.ObjectId(),
|
|
67
|
+
arcGISAuth: { username: "tc_dup_user" },
|
|
68
|
+
}).save();
|
|
69
|
+
|
|
70
|
+
// A second department claiming the same non-empty username must be rejected.
|
|
71
|
+
// assertRejects fails if the save does NOT reject, so there is no false-positive.
|
|
72
|
+
await assertRejects(
|
|
73
|
+
new models.Esri({
|
|
74
|
+
departmentId: new mongoose.Types.ObjectId(),
|
|
75
|
+
arcGISAuth: { username: "tc_dup_user" },
|
|
76
|
+
}).save(),
|
|
77
|
+
/duplicate key/
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("normalizes an empty arcGISAuth.username to null", async function() {
|
|
82
|
+
// EsriAuth.username defaults to "" (schema shared with auth); an arcGISAuth
|
|
83
|
+
// present without a real username collapses to null so it is never indexed.
|
|
84
|
+
const saved = await new models.Esri({
|
|
85
|
+
departmentId: new mongoose.Types.ObjectId(),
|
|
86
|
+
arcGISAuth: { username: "" },
|
|
87
|
+
}).save();
|
|
88
|
+
assert.isNull(saved.arcGISAuth);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("allows multiple missing/empty arcGISAuth.username and distinct values", async function() {
|
|
92
|
+
// missing arcGISAuth entirely (defaults to null) — not indexed
|
|
93
|
+
await new models.Esri({ departmentId: new mongoose.Types.ObjectId() }).save();
|
|
94
|
+
await new models.Esri({ departmentId: new mongoose.Types.ObjectId() }).save();
|
|
95
|
+
// empty-string username — normalized to null by the pre-save hook, so not indexed.
|
|
96
|
+
// Both must coexist: without normalization the second would collide on "" under $exists.
|
|
97
|
+
const empty1 = await new models.Esri({ departmentId: new mongoose.Types.ObjectId(), arcGISAuth: { username: "" } }).save();
|
|
98
|
+
const empty2 = await new models.Esri({ departmentId: new mongoose.Types.ObjectId(), arcGISAuth: { username: "" } }).save();
|
|
99
|
+
assert.isNull(empty1.arcGISAuth);
|
|
100
|
+
assert.isNull(empty2.arcGISAuth);
|
|
101
|
+
// distinct non-empty usernames — allowed
|
|
102
|
+
await new models.Esri({ departmentId: new mongoose.Types.ObjectId(), arcGISAuth: { username: "tc_user_a" } }).save();
|
|
103
|
+
await new models.Esri({ departmentId: new mongoose.Types.ObjectId(), arcGISAuth: { username: "tc_user_b" } }).save();
|
|
104
|
+
|
|
105
|
+
const count = await models.Esri.countDocuments({});
|
|
106
|
+
assert.equal(count, 6);
|
|
107
|
+
});
|
|
62
108
|
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { assert } from "chai";
|
|
2
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
3
|
+
import * as m from "../index";
|
|
4
|
+
import * as config from "./config";
|
|
5
|
+
|
|
6
|
+
describe("KindTypeCatalog", function() {
|
|
7
|
+
let models: m.BackendModels, mongoose: m.MongooseModule;
|
|
8
|
+
beforeEach(async function() {
|
|
9
|
+
const c = await m.connect(config.url);
|
|
10
|
+
models = c.models; mongoose = c.mongoose;
|
|
11
|
+
await models.KindTypeCatalog.syncIndexes();
|
|
12
|
+
});
|
|
13
|
+
afterEach(async function() {
|
|
14
|
+
await models.KindTypeCatalog.deleteMany({});
|
|
15
|
+
await mongoose.disconnect();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("is saved with a colorization", async function() {
|
|
19
|
+
const sut = await new models.KindTypeCatalog({
|
|
20
|
+
kind: "engine",
|
|
21
|
+
type: "1",
|
|
22
|
+
locationType: "vehicle",
|
|
23
|
+
colorization: { background: "#0000FF", text: "#FFFFFF" },
|
|
24
|
+
}).save();
|
|
25
|
+
assert.equal(sut.kind, "engine");
|
|
26
|
+
assert.equal(sut.type, "1");
|
|
27
|
+
assert.equal(sut.locationType, "vehicle");
|
|
28
|
+
assert.equal(sut.colorization?.background, "#0000FF");
|
|
29
|
+
assert.isTrue(sut.active);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("enforces a unique (kind, type) index", async function() {
|
|
33
|
+
await new models.KindTypeCatalog({ kind: "engine", type: "1", locationType: "vehicle" }).save();
|
|
34
|
+
let err: unknown = null;
|
|
35
|
+
try {
|
|
36
|
+
await new models.KindTypeCatalog({ kind: "engine", type: "1", locationType: "vehicle" }).save();
|
|
37
|
+
} catch (e) {
|
|
38
|
+
err = e;
|
|
39
|
+
}
|
|
40
|
+
assert.isNotNull(err, "expected duplicate (kind,type) to be rejected");
|
|
41
|
+
assert.include(String((err as Error).message), "duplicate key");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("allows the same kind with a different type", async function() {
|
|
45
|
+
await new models.KindTypeCatalog({ kind: "engine", type: "1", locationType: "vehicle" }).save();
|
|
46
|
+
const sut = await new models.KindTypeCatalog({ kind: "engine", type: "2", locationType: "vehicle" }).save();
|
|
47
|
+
assert.equal(sut.type, "2");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("requires a non-empty kind", async function() {
|
|
51
|
+
let err: unknown = null;
|
|
52
|
+
try {
|
|
53
|
+
await new models.KindTypeCatalog({ type: "1", locationType: "vehicle" }).save();
|
|
54
|
+
} catch (e) {
|
|
55
|
+
err = e;
|
|
56
|
+
}
|
|
57
|
+
assert.isNotNull(err, "expected a missing kind to be rejected");
|
|
58
|
+
assert.include(String((err as Error).message), "kind");
|
|
59
|
+
});
|
|
60
|
+
});
|
package/src/test/location.ts
CHANGED
|
@@ -96,4 +96,35 @@ describe("Location", function() {
|
|
|
96
96
|
assert.notEqual(sutVis.indexOf(LocationVisibility.CAD), -1);
|
|
97
97
|
assert.notEqual(sutVis.indexOf(LocationVisibility.Shared), -1);
|
|
98
98
|
});
|
|
99
|
+
|
|
100
|
+
it("persists kind, type, locationType and kindColor", async function() {
|
|
101
|
+
const item = new models.Location({
|
|
102
|
+
departmentId: "d1",
|
|
103
|
+
userId: "u1",
|
|
104
|
+
username: "E1",
|
|
105
|
+
device_type: "ipad",
|
|
106
|
+
kind: "engine",
|
|
107
|
+
type: "1",
|
|
108
|
+
locationType: "vehicle",
|
|
109
|
+
kindColor: { background: "#0000FF", text: "#FFFFFF" },
|
|
110
|
+
});
|
|
111
|
+
const sut = await item.save();
|
|
112
|
+
assert.equal(sut.kind, "engine");
|
|
113
|
+
assert.equal(sut.type, "1");
|
|
114
|
+
assert.equal(sut.locationType, "vehicle");
|
|
115
|
+
assert.equal(sut.kindColor?.background, "#0000FF");
|
|
116
|
+
assert.equal(sut.kindColor?.text, "#FFFFFF");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("does not auto-stamp kindColorChangedAt", async function() {
|
|
120
|
+
const item = new models.Location({
|
|
121
|
+
departmentId: "d1",
|
|
122
|
+
userId: "u1",
|
|
123
|
+
username: "E2",
|
|
124
|
+
device_type: "ipad",
|
|
125
|
+
kindColor: { background: "#0000FF", text: "#FFFFFF" },
|
|
126
|
+
});
|
|
127
|
+
const sut = await item.save();
|
|
128
|
+
assert.isUndefined(sut.kindColorChangedAt);
|
|
129
|
+
});
|
|
99
130
|
});
|
package/src/test/mock.ts
CHANGED
|
@@ -280,6 +280,9 @@ export default function mockModule(dependencies: { mongoose: Mongoose; }) {
|
|
|
280
280
|
agencyId: new mongoose.Types.ObjectId(),
|
|
281
281
|
name: "BattalionUnit Test",
|
|
282
282
|
kindType: "vehicle",
|
|
283
|
+
locationType: "vehicle",
|
|
284
|
+
kind: "engine",
|
|
285
|
+
type: "1",
|
|
283
286
|
friendly_id: "B1",
|
|
284
287
|
local_id: 321,
|
|
285
288
|
personnel: 4,
|
package/src/types/battalion.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Types } from "mongoose";
|
|
2
|
+
import { ColorSchemaType } from "./color";
|
|
3
|
+
|
|
4
|
+
export interface KindTypeCatalogType extends Record<string, unknown> {
|
|
5
|
+
_id: Types.ObjectId,
|
|
6
|
+
id?: string,
|
|
7
|
+
uuid: string,
|
|
8
|
+
kind: string,
|
|
9
|
+
type: string,
|
|
10
|
+
locationType: string,
|
|
11
|
+
colorization?: ColorSchemaType,
|
|
12
|
+
active: boolean,
|
|
13
|
+
modifiedDate: number,
|
|
14
|
+
modified: Date,
|
|
15
|
+
}
|
package/src/types/location.ts
CHANGED
|
@@ -17,6 +17,11 @@ export interface LocationType {
|
|
|
17
17
|
esriId: number,
|
|
18
18
|
heading: number,
|
|
19
19
|
kindType: string,
|
|
20
|
+
kind?: string,
|
|
21
|
+
type?: string,
|
|
22
|
+
locationType?: string,
|
|
23
|
+
kindColor?: ColorSchemaType,
|
|
24
|
+
kindColorChangedAt?: Date,
|
|
20
25
|
location?: { latitude: number, longitude: number, }; // provided by virtual.location
|
|
21
26
|
locationGeoJSON: GeoPoint,
|
|
22
27
|
modified: Date,
|