Rename padId to mapId

v5
Candid Dauth 2024-04-24 12:28:16 +02:00
rodzic 27c089dd69
commit 635fa8885f
30 zmienionych plików z 474 dodań i 143 usunięć

Wyświetl plik

@ -5,7 +5,7 @@ The websocket on the FacilMap server provides different API versions (implemente
## v5.0.0 (API v3)
* “symbol” was renamed to “icon” everywhere. This applies to `Marker.symbol`, `Type.defaultSymbol`, `Type.symbolFixed`, `Type.fields[].controlSymbol` and `Type.fields[].options[].symbol`.
* “pad” was renamed “map” everywhere. This applies to the `padData` and `deletePad` socket events and `getPad` (including its `padId` request property), the `findPads`, `createPad`, `editPad`, `deletePad`, `setPadId` client/socket methods, the `PadNotFoundError`.
* “pad” was renamed “map” everywhere. This applies to the `padData` and `deletePad` socket events and `getPad` (including its `padId` request property), the `findPads`, `createPad`, `editPad`, `deletePad`, `setPadId` client/socket methods, the `PadNotFoundError`, and the `Marker.padId`, `Line.padId`, `Type.padId`, `View.padId` and `HistoryEntry.padId` properties.
## v4.0.0 (API v2)

Wyświetl plik

@ -1,6 +1,6 @@
import { expect, test, vi } from "vitest";
import { createTemporaryMapV2, openClient, retry } from "../utils";
import { SocketVersion, type Line } from "facilmap-types";
import { SocketVersion, type LegacyV2Line } from "facilmap-types";
test("Socket v1 line name", async () => {
// client1: Creates the line and has it in its bbox
@ -56,7 +56,7 @@ test("Socket v1 line name", async () => {
bottom: 6,
left: 6,
data: {}
} satisfies Line;
} satisfies LegacyV2Line;
expect(line).toEqual(expectedLine);

Wyświetl plik

@ -0,0 +1,114 @@
import { expect, test, vi } from "vitest";
import { createTemporaryMapV2, openClient, retry } from "../utils";
import { SocketVersion } from "facilmap-types";
import { cloneDeep } from "lodash-es";
test("Create line (Socket v2)", async () => {
// client1: Creates the line
// client2: Has the map open while the line is created
// client3: Opens the map later
const client1 = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client1, {}, async (createMapData, mapData) => {
const client2 = await openClient(mapData.id, SocketVersion.V2);
const onLine1 = vi.fn();
client1.on("line", onLine1);
const onLine2 = vi.fn();
client2.on("line", onLine2);
const lineType = Object.values(client1.types).find((t) => t.type === "line")!;
const line = await client1.addLine({
routePoints: [
{ lat: 6, lon: 6 },
{ lat: 14, lon: 14 }
],
typeId: lineType.id
});
const expectedLine = {
padId: mapData.id
};
expect(line).toMatchObject(expectedLine);
await retry(() => {
expect(onLine1).toHaveBeenCalledTimes(1);
expect(onLine2).toHaveBeenCalledTimes(1);
});
expect(onLine1).toHaveBeenCalledWith(expect.objectContaining(expectedLine));
expect(onLine2).toHaveBeenCalledWith(expect.objectContaining(expectedLine));
const expectedLineRecord = { [line.id]: expect.objectContaining(expectedLine) };
expect(cloneDeep(client1.lines)).toEqual(expectedLineRecord);
expect(cloneDeep(client2.lines)).toEqual(expectedLineRecord);
const client3 = await openClient(mapData.id, SocketVersion.V2);
expect(cloneDeep(client3.lines)).toEqual(expectedLineRecord);
});
});
test("Edit line (socket v2)", async () => {
// client1: Creates the line and has it in its bbox
// client2: Has the map open
const client1 = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client1, {}, async (createMapData, mapData) => {
const client2 = await openClient(mapData.id, SocketVersion.V2);
const lineType = Object.values(client1.types).find((t) => t.type === "line")!;
const createdLine = await client1.addLine({
routePoints: [
{ lat: 6, lon: 6 },
{ lat: 14, lon: 14 }
],
typeId: lineType.id
});
const onLine1 = vi.fn();
client1.on("line", onLine1);
const onLine2 = vi.fn();
client2.on("line", onLine2);
const newData = {
id: createdLine.id,
width: 20
};
const line = await client1.editLine(newData);
expect(line).toMatchObject({ padId: mapData.id });
await retry(() => {
expect(onLine1).toHaveBeenCalledTimes(1);
expect(onLine2).toHaveBeenCalledTimes(1);
});
expect(onLine1).toHaveBeenCalledWith(expect.objectContaining({ padId: mapData.id }));
expect(onLine2).toHaveBeenCalledWith(expect.objectContaining({ padId: mapData.id }));
});
});
test("Delete line (socket v2)", async () => {
const client = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client, {}, async (createMapData, mapData) => {
const lineType = Object.values(client.types).find((t) => t.type === "line")!;
const createdLine = await client.addLine({
routePoints: [
{ lat: 6, lon: 6 },
{ lat: 14, lon: 14 }
],
typeId: lineType.id
});
const deletedLine = await client.deleteLine({ id: createdLine.id });
expect(deletedLine).toEqual(createdLine);
});
});

Wyświetl plik

@ -33,7 +33,8 @@ test("Create marker (Socket v2)", async () => {
});
const expectedMarker = {
symbol: "test"
symbol: "test",
padId: mapData.id
};
expect(marker).toMatchObject(expectedMarker);
@ -97,7 +98,7 @@ test("Edit marker (socket v2)", async () => {
};
const marker = await client1.editMarker(newData);
expect(marker).toMatchObject({ symbol: "icon" });
expect(marker).toMatchObject({ symbol: "icon", padId: mapData.id });
await retry(() => {
expect(onMarker1).toHaveBeenCalledTimes(1);
@ -105,8 +106,8 @@ test("Edit marker (socket v2)", async () => {
expect(onMarker3).toHaveBeenCalledTimes(1);
});
expect(onMarker1).toHaveBeenCalledWith(expect.objectContaining({ symbol: "icon" }));
expect(onMarker2).toHaveBeenCalledWith(expect.objectContaining({ symbol: "icon" }));
expect(onMarker1).toHaveBeenCalledWith(expect.objectContaining({ symbol: "icon", padId: mapData.id }));
expect(onMarker2).toHaveBeenCalledWith(expect.objectContaining({ symbol: "icon", padId: mapData.id }));
expect(onMarker3).toHaveBeenCalledWith(expect.objectContaining({ icon: "icon" }));
});
});
@ -145,11 +146,11 @@ test("Get marker (socket v2)", async () => {
symbol: "icon"
});
expect(await client.getMarker({ id: marker.id })).toMatchObject({ symbol: "icon" });
expect(await client.getMarker({ id: marker.id })).toMatchObject({ symbol: "icon", padId: mapData.id });
});
});
test("Find marker", async () => {
test("Find marker (socket v2)", async () => {
const client = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client, {}, async (createMapData, mapData) => {

Wyświetl plik

@ -42,17 +42,17 @@ test("Create type (socket v2)", async () => {
expect(onType1).toHaveBeenNthCalledWith(1, expect.objectContaining(type));
expect(cloneDeep(client1.types)).toEqual({
[typeResult.id]: expect.objectContaining(type)
[typeResult.id]: expect.objectContaining({ ...type, padId: mapData.id })
});
expect(onType2).toHaveBeenNthCalledWith(1, expect.objectContaining(type));
expect(cloneDeep(client2.types)).toEqual({
[typeResult.id]: expect.objectContaining(type)
[typeResult.id]: expect.objectContaining({ ...type, padId: mapData.id })
});
const client3 = await openClient(mapData.id, SocketVersion.V2);
expect(cloneDeep(client3.types)).toEqual({
[typeResult.id]: expect.objectContaining(type)
[typeResult.id]: expect.objectContaining({ ...type, padId: mapData.id })
});
const client4 = await openClient(mapData.id);
@ -109,21 +109,21 @@ test("Update type (socket v2)", async () => {
const typeResult = await client1.editType(update);
expect(typeResult).toMatchObject(update);
expect(typeResult).toMatchObject({ ...update, padId: mapData.id });
await retry(async () => {
expect(onType1).toBeCalledTimes(1);
expect(onType2).toBeCalledTimes(1);
});
expect(onType1).toHaveBeenNthCalledWith(1, expect.objectContaining(update));
expect(onType1).toHaveBeenNthCalledWith(1, expect.objectContaining({ ...update, padId: mapData.id }));
expect(cloneDeep(client1.types)).toEqual({
[createdType.id]: expect.objectContaining(update)
[createdType.id]: expect.objectContaining({ ...update, padId: mapData.id })
});
expect(onType2).toHaveBeenNthCalledWith(1, expect.objectContaining(update));
expect(onType2).toHaveBeenNthCalledWith(1, expect.objectContaining({ ...update, padId: mapData.id }));
expect(cloneDeep(client2.types)).toEqual({
[createdType.id]: expect.objectContaining(update)
[createdType.id]: expect.objectContaining({ ...update, padId: mapData.id })
});
const client3 = await openClient(mapData.id);

Wyświetl plik

@ -0,0 +1,114 @@
import { expect, test, vi } from "vitest";
import { createTemporaryMapV2, openClient, retry } from "../utils";
import { SocketVersion } from "facilmap-types";
import { cloneDeep } from "lodash-es";
test("Create view (Socket v2)", async () => {
// client1: Creates the view
// client2: Has the map open while the view is created
// client3: Opens the map later
const client1 = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client1, {}, async (createMapData, mapData) => {
const client2 = await openClient(mapData.id, SocketVersion.V2);
const onView1 = vi.fn();
client1.on("view", onView1);
const onView2 = vi.fn();
client2.on("view", onView2);
const view = await client1.addView({
name: "Test view 1",
left: -10,
right: 10,
top: -20,
bottom: 20,
baseLayer: "Mpnk",
layers: []
});
const expectedView = {
padId: mapData.id
};
expect(view).toMatchObject(expectedView);
await retry(() => {
expect(onView1).toHaveBeenCalledTimes(1);
expect(onView2).toHaveBeenCalledTimes(1);
});
expect(onView1).toHaveBeenCalledWith(expect.objectContaining(expectedView));
expect(onView2).toHaveBeenCalledWith(expect.objectContaining(expectedView));
const expectedViewRecord = { [view.id]: expect.objectContaining(expectedView) };
expect(cloneDeep(client1.views)).toEqual(expectedViewRecord);
expect(cloneDeep(client2.views)).toEqual(expectedViewRecord);
const client3 = await openClient(mapData.id, SocketVersion.V2);
expect(cloneDeep(client3.views)).toEqual(expectedViewRecord);
});
});
test("Edit view (socket v2)", async () => {
// client1: Creates the view and has it in its bbox
// client2: Has the map open
const client1 = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client1, {}, async (createMapData, mapData) => {
const client2 = await openClient(mapData.id, SocketVersion.V2);
const createdView = await client1.addView({
name: "Test view 1",
left: -10,
right: 10,
top: -20,
bottom: 20,
baseLayer: "Mpnk",
layers: []
});
const onView1 = vi.fn();
client1.on("view", onView1);
const onView2 = vi.fn();
client2.on("view", onView2);
const newData = {
id: createdView.id,
baseLayer: "Lima"
};
const view = await client1.editView(newData);
expect(view).toMatchObject({ padId: mapData.id });
await retry(() => {
expect(onView1).toHaveBeenCalledTimes(1);
expect(onView2).toHaveBeenCalledTimes(1);
});
expect(onView1).toHaveBeenCalledWith(expect.objectContaining({ padId: mapData.id }));
expect(onView2).toHaveBeenCalledWith(expect.objectContaining({ padId: mapData.id }));
});
});
test("Delete view (socket v2)", async () => {
const client = await openClient(undefined, SocketVersion.V2);
await createTemporaryMapV2(client, {}, async (createMapData, mapData) => {
const createdView = await client.addView({
name: "Test view 1",
left: -10,
right: 10,
top: -20,
bottom: 20,
baseLayer: "Mpnk",
layers: []
});
const deletedView = await client.deleteView({ id: createdView.id });
expect(deletedView).toEqual(createdView);
});
});

Wyświetl plik

@ -49,7 +49,7 @@ test("Create line (using default values)", async () => {
{ lat: 14, lon: 14 }
],
typeId: lineType.id,
padId: mapData.id,
mapId: mapData.id,
name: "",
mode: "",
colour: "0000ff",
@ -146,7 +146,7 @@ test("Create line (using custom values)", async () => {
const expectedLine = {
id: line.id,
padId: mapData.id,
mapId: mapData.id,
...omit(data, ["trackPoints"]),
top: 14,
right: 14,
@ -245,7 +245,7 @@ test("Edit line", async () => {
const line = await client1.editLine(newData);
const expectedLine = {
padId: mapData.id,
mapId: mapData.id,
...omit(newData, ["trackPoints"]),
top: 14,
right: 14,

Wyświetl plik

@ -39,7 +39,7 @@ test("Create marker (using default values)", async () => {
lat: 10,
lon: 10,
typeId: markerType.id,
padId: mapData.id,
mapId: mapData.id,
name: "",
colour: "ff0000",
size: 30,
@ -92,7 +92,7 @@ test("Create marker (using custom values)", async () => {
const expectedMarker = {
id: marker.id,
padId: mapData.id,
mapId: mapData.id,
...data
};
@ -154,7 +154,7 @@ test("Edit marker", async () => {
const marker = await client1.editMarker(newData);
const expectedMarker = {
padId: mapData.id,
mapId: mapData.id,
...newData
};
@ -248,7 +248,7 @@ test("Get marker", async () => {
lat: 10,
lon: 10,
typeId: markerType.id,
padId: mapData.id,
mapId: mapData.id,
name: "",
colour: "ff0000",
size: 30,

Wyświetl plik

@ -36,7 +36,7 @@ test("Default types are added", async () => {
defaultMode: '',
modeFixed: false,
showInLegend: false,
padId: mapData.id
mapId: mapData.id
},
{
fields: [
@ -61,7 +61,7 @@ test("Default types are added", async () => {
defaultMode: '',
modeFixed: false,
showInLegend: false,
padId: mapData.id
mapId: mapData.id
}
] satisfies Array<Type>;
@ -107,7 +107,7 @@ test("Create type (marker, default settings)", async () => {
const expectedType: Type = {
...type,
id: typeResult.id,
padId: mapData.id,
mapId: mapData.id,
idx: 0,
defaultColour: "ff0000",
colourFixed: false,
@ -178,7 +178,7 @@ test("Create type (line, default settings)", async () => {
const expectedType: Type = {
...type,
id: typeResult.id,
padId: mapData.id,
mapId: mapData.id,
idx: 0,
defaultColour: "0000ff",
colourFixed: false,
@ -263,7 +263,7 @@ test("Create type (custom settings)", async () => {
const expectedType: Type = {
...type,
id: typeResult.id,
padId: mapData.id
mapId: mapData.id
};
expect(typeResult).toEqual(expectedType);
@ -327,7 +327,7 @@ test("Update type", async () => {
const expectedType: Type = {
...update,
padId: mapData.id,
mapId: mapData.id,
type: "marker"
};

Wyświetl plik

@ -33,7 +33,7 @@ test("Create view (default values)", async () => {
idx: 0,
filter: null,
id: viewResult.id,
padId: mapData.id
mapId: mapData.id
};
expect(viewResult).toEqual(expectedView);
@ -84,7 +84,7 @@ test("Create view (custom values)", async () => {
const expectedView: View = {
...view,
id: viewResult.id,
padId: mapData.id
mapId: mapData.id
};
expect(viewResult).toEqual(expectedView);
@ -134,7 +134,7 @@ test("Update view", async () => {
const expectedView: View = {
...update,
padId: mapData.id
mapId: mapData.id
};
expect(view).toEqual(expectedView);

Wyświetl plik

@ -189,7 +189,7 @@ export default class LinesLayer extends FeatureGroup {
return new Promise<Point[] | undefined>((resolve) => {
const line: Line & { trackPoints: BasicTrackPoints } = {
id: -1,
padId: "",
mapId: "",
top: 0,
right: 0,
bottom: 0,

Wyświetl plik

@ -120,7 +120,7 @@ export default class DatabaseHelpers {
async _updateObjectStyles(objects: Marker | Line | AsyncIterable<Marker | Line>): Promise<void> {
const types: Record<ID, Type> = { };
for await (const object of Symbol.asyncIterator in objects ? objects : arrayToAsyncIterator([objects])) {
const mapId = object.padId;
const mapId = object.mapId;
if(!types[object.typeId]) {
types[object.typeId] = await this._db.types.getType(mapId, object.typeId);
@ -140,7 +140,7 @@ export default class DatabaseHelpers {
async _mapObjectExists(type: string, mapId: MapId, id: ID): Promise<boolean> {
const entry = await this._db._conn.model(type).findOne({
where: { padId: mapId, id: id },
where: { mapId, id: id },
attributes: ['id']
});
return entry != null;
@ -150,7 +150,7 @@ export default class DatabaseHelpers {
const includeData = [ "Marker", "Line" ].includes(type);
const entry = await this._db._conn.model(type).findOne({
where: { id: id, padId: mapId },
where: { id: id, mapId },
include: includeData ? [ this._db._conn.model(type + "Data") ] : [ ],
nest: true
});
@ -198,7 +198,7 @@ export default class DatabaseHelpers {
const makeHistory = [ "Marker", "Line", "View", "Type" ].includes(type);
const obj = this._db._conn.model(type).build(data);
(obj as any).padId = mapId;
(obj as any).mapId = mapId;
const result: any = (await obj.save()).toJSON();
@ -225,7 +225,7 @@ export default class DatabaseHelpers {
const oldObject = await this._getMapObject(type, mapId, objId);
if(Object.keys(data).length > 0 && (!includeData || !isEqual(Object.keys(data), ["data"])))
await this._db._conn.model(type).update(data, { where: { id: objId, padId: mapId } });
await this._db._conn.model(type).update(data, { where: { id: objId, mapId } });
const newObject: any = await this._getMapObject(type, mapId, objId);
@ -365,9 +365,9 @@ export default class DatabaseHelpers {
if(!isEqual(object.data, newData)) {
if(isLine)
await this._db.lines.updateLine(object.padId, object.id, { data: newData }, true); // Last param true to not create history entry
await this._db.lines.updateLine(object.mapId, object.id, { data: newData }, true); // Last param true to not create history entry
else
await this._db.markers.updateMarker(object.padId, object.id, { data: newData }, true); // Last param true to not create history entry
await this._db.markers.updateMarker(object.mapId, object.id, { data: newData }, true); // Last param true to not create history entry
}
}
}

Wyświetl plik

@ -13,7 +13,7 @@ interface HistoryModel extends Model<InferAttributes<HistoryModel>, InferCreatio
objectId: ID;
objectBefore: string | null;
objectAfter: string | null;
padId: ForeignKey<MapData["id"]>;
mapId: ForeignKey<MapData["id"]>;
toJSON: () => HistoryEntry;
}
@ -33,7 +33,7 @@ export default class DatabaseHistory {
time: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
type: { type: DataTypes.ENUM("Marker", "Line", "View", "Type", "Map"), allowNull: false },
action: { type: DataTypes.ENUM("create", "update", "delete"), allowNull: false },
objectId: { type: DataTypes.INTEGER(), allowNull: true }, // Is null when type is pad
objectId: { type: DataTypes.INTEGER(), allowNull: true }, // Is null when type is map
objectBefore: {
type: DataTypes.TEXT,
allowNull: true,
@ -65,14 +65,14 @@ export default class DatabaseHistory {
afterInit(): void {
this._db.maps.MapModel.hasMany(this.HistoryModel, makeNotNullForeignKey("History", "padId"));
this.HistoryModel.belongsTo(this._db.maps.MapModel, makeNotNullForeignKey("pad", "padId"));
this._db.maps.MapModel.hasMany(this.HistoryModel, makeNotNullForeignKey("History", "mapId"));
this.HistoryModel.belongsTo(this._db.maps.MapModel, makeNotNullForeignKey("map", "mapId"));
}
async addHistoryEntry(mapId: MapId, data: HistoryEntryCreate): Promise<HistoryEntry> {
const oldEntryIds = (await this.HistoryModel.findAll({
where: { padId: mapId },
where: { mapId },
order: [[ "time", "DESC" ]],
offset: this.HISTORY_ENTRIES-1,
attributes: [ "id" ]
@ -82,17 +82,17 @@ export default class DatabaseHistory {
if(data.type != "Map") {
if(dataClone.objectBefore) {
delete (dataClone.objectBefore as any).id;
delete (dataClone.objectBefore as any).padId;
delete (dataClone.objectBefore as any).mapId;
}
if(dataClone.objectAfter) {
delete (dataClone.objectAfter as any).id;
delete (dataClone.objectAfter as any).padId;
delete (dataClone.objectAfter as any).mapId;
}
}
const [newEntry] = await Promise.all([
this._db.helpers._createMapObject<HistoryEntry>("History", mapId, dataClone),
oldEntryIds.length > 0 ? this.HistoryModel.destroy({ where: { padId: mapId, id: oldEntryIds } }) : undefined
oldEntryIds.length > 0 ? this.HistoryModel.destroy({ where: { mapId: mapId, id: oldEntryIds } }) : undefined
]);
this._db.emit("addHistoryEntry", mapId, newEntry);
@ -189,14 +189,14 @@ export default class DatabaseHistory {
break;
}
await this.HistoryModel.update({ objectId: newObj.id }, { where: { padId: mapId, type: entry.type, objectId: entry.objectId } });
await this.HistoryModel.update({ objectId: newObj.id }, { where: { mapId, type: entry.type, objectId: entry.objectId } });
this._db.emit("historyChange", mapId);
}
}
async clearHistory(mapId: MapId): Promise<void> {
await this.HistoryModel.destroy({ where: { padId: mapId } });
await this.HistoryModel.destroy({ where: { mapId } });
}
}

Wyświetl plik

@ -16,7 +16,7 @@ export type LineWithTrackPoints = Line & {
export interface LineModel extends Model<InferAttributes<LineModel>, InferCreationAttributes<LineModel>> {
id: CreationOptional<ID>;
padId: ForeignKey<MapModel["id"]>;
mapId: ForeignKey<MapModel["id"]>;
routePoints: Point[];
typeId: ForeignKey<TypeModel["id"]>;
mode: RouteMode;
@ -172,8 +172,8 @@ export default class DatabaseLines {
}
afterInit(): void {
this.LineModel.belongsTo(this._db.maps.MapModel, makeNotNullForeignKey("pad", "padId"));
this._db.maps.MapModel.hasMany(this.LineModel, { foreignKey: "padId" });
this.LineModel.belongsTo(this._db.maps.MapModel, makeNotNullForeignKey("map", "mapId"));
this._db.maps.MapModel.hasMany(this.LineModel, { foreignKey: "mapId" });
// TODO: Cascade
this.LineModel.belongsTo(this._db.types.TypeModel, makeNotNullForeignKey("type", "typeId", true));
@ -245,12 +245,12 @@ export default class DatabaseLines {
delete update.trackPoints; // They came if mode is track
if (Object.keys(update).length > 0) {
const newLine = await this._db.helpers._updateMapObject<Line>("Line", originalLine.padId, originalLine.id, update, noHistory);
const newLine = await this._db.helpers._updateMapObject<Line>("Line", originalLine.mapId, originalLine.id, update, noHistory);
this._db.emit("line", originalLine.padId, newLine);
this._db.emit("line", originalLine.mapId, newLine);
if(routeInfo)
await this._setLinePoints(originalLine.padId, originalLine.id, routeInfo.trackPoints);
await this._setLinePoints(originalLine.mapId, originalLine.id, routeInfo.trackPoints);
return newLine;
} else {
@ -280,7 +280,7 @@ export default class DatabaseLines {
}
async* getLinePointsForMap(mapId: MapId, bboxWithZoom: BboxWithZoom & BboxWithExcept): AsyncIterable<{ id: ID; trackPoints: TrackPoint[] }> {
const lines = await this.LineModel.findAll({ attributes: ["id"], where: { padId: mapId } });
const lines = await this.LineModel.findAll({ attributes: ["id"], where: { mapId } });
const chunks = chunk(lines.map((line) => line.id), 50000);
for (const lineIds of chunks) {
const linePoints = await this.LinePointModel.findAll({

Wyświetl plik

@ -10,7 +10,7 @@ import { getI18n } from "../i18n.js";
export interface MarkerModel extends Model<InferAttributes<MarkerModel>, InferCreationAttributes<MarkerModel>> {
id: CreationOptional<ID>;
padId: ForeignKey<MapModel["id"]>;
mapId: ForeignKey<MapModel["id"]>;
pos: GeoJsonPoint;
lat: Latitude;
lon: Longitude;
@ -69,8 +69,8 @@ export default class DatabaseMarkers {
const MapModel = this._db.maps.MapModel;
const TypeModel = this._db.types.TypeModel;
MapModel.hasMany(this.MarkerModel, makeNotNullForeignKey("Markers", "padId"));
this.MarkerModel.belongsTo(MapModel, makeNotNullForeignKey("pad", "padId"));
MapModel.hasMany(this.MarkerModel, makeNotNullForeignKey("Markers", "mapId"));
this.MarkerModel.belongsTo(MapModel, makeNotNullForeignKey("map", "mapId"));
this.MarkerModel.belongsTo(TypeModel, makeNotNullForeignKey("type", "typeId", true));
this.MarkerDataModel.belongsTo(this.MarkerModel, makeNotNullForeignKey("marker", "markerId"));
@ -82,7 +82,7 @@ export default class DatabaseMarkers {
}
getMapMarkersByType(mapId: MapId, typeId: ID): AsyncIterable<Marker> {
return this._db.helpers._getMapObjects<Marker>("Marker", mapId, { where: { padId: mapId, typeId: typeId } });
return this._db.helpers._getMapObjects<Marker>("Marker", mapId, { where: { mapId, typeId: typeId } });
}
getMarker(mapId: MapId, markerId: ID): Promise<Marker> {
@ -125,14 +125,14 @@ export default class DatabaseMarkers {
const update = resolveUpdateMarker(originalMarker, data, newType);
if (Object.keys(update).length > 0) {
const result = await this._db.helpers._updateMapObject<Marker>("Marker", originalMarker.padId, originalMarker.id, update, noHistory);
const result = await this._db.helpers._updateMapObject<Marker>("Marker", originalMarker.mapId, originalMarker.id, update, noHistory);
this._db.emit("marker", originalMarker.padId, result);
this._db.emit("marker", originalMarker.mapId, result);
if (update.lat != null && update.lon != null && update.ele === undefined) {
getElevationForPoint({ lat: update.lat, lon: update.lon }).then(async (ele) => {
if (ele != null) {
await this.updateMarker(originalMarker.padId, originalMarker.id, { ele }, true);
await this.updateMarker(originalMarker.mapId, originalMarker.id, { ele }, true);
}
}).catch((err) => {
console.warn("Error updating marker elevation", err);

Wyświetl plik

@ -70,6 +70,12 @@ export default class DatabaseMigrations {
await queryInterface.renameColumn('Markers', 'symbol', 'icon');
}
// Rename Marker.padId to Marker.mapId
if (markerAttrs.padId) {
console.log("DB migration: Rename Markers.padId to Markers.mapId");
await queryInterface.renameColumn("Markers", "padId", "mapId");
}
const lineAttrs = await queryInterface.describeTable('Lines');
@ -85,6 +91,12 @@ export default class DatabaseMigrations {
await this._db.lines.LineModel.update({ mode: "car" }, { where: { mode: { [Op.in]: [ "fastest", "shortest" ] } } });
}
// Rename Line.padId to Line.mapId
if (lineAttrs.padId) {
console.log("DB migration: Rename Lines.padId to Lines.mapId");
await queryInterface.renameColumn("Lines", "padId", "mapId");
}
const typeAttrs = await queryInterface.describeTable('Types');
@ -100,6 +112,21 @@ export default class DatabaseMigrations {
await queryInterface.renameColumn('Types', 'symbolFixed', 'iconFixed');
}
// Rename Type.padId to type.mapId
if (typeAttrs.padId) {
console.log("DB migration: Rename Types.padId to Types.mapId");
await queryInterface.renameColumn("Types", "padId", "mapId");
}
const viewAttrs = await queryInterface.describeTable("Views");
// Rename View.padId to View.mapId
if (viewAttrs.padId) {
console.log("DB migration: Rename Views.padId to Views.mapId");
await queryInterface.renameColumn("Views", "padId", "mapId");
}
const mapAttrs = await queryInterface.describeTable('Maps');
@ -120,6 +147,15 @@ export default class DatabaseMigrations {
await MapModel.update({writeId}, { where: { id: map.id } });
}
}
const historyAttrs = await queryInterface.describeTable("History");
// Rename HistoryEntry.padId to HistoryEntry.mapId
if (historyAttrs.padId) {
console.log("DB migration: Rename History.padId to History.mapId");
await queryInterface.renameColumn("History", "padId", "mapId");
}
}
@ -382,7 +418,7 @@ export default class DatabaseMigrations {
const newFields = type.fields; // type.fields is a getter, we cannot modify the object directly
const dropdowns = newFields.filter((field) => field.type == "dropdown");
if(dropdowns.length > 0) {
const objectStream = (type.type == "line" ? this._db.lines.getMapLinesByType(type.padId, type.id) : this._db.markers.getMapMarkersByType(type.padId, type.id));
const objectStream = (type.type == "line" ? this._db.lines.getMapLinesByType(type.mapId, type.id) : this._db.markers.getMapMarkersByType(type.mapId, type.id));
for await (const object of objectStream) {
const newData = cloneDeep(object.data);
@ -391,11 +427,11 @@ export default class DatabaseMigrations {
if(newVal)
newData[dropdown.name] = newVal.value;
else if(newData[dropdown.name])
console.log(`DB migration: Warning: Dropdown key ${newData[dropdown.name]} for field ${dropdown.name} of type ${type.name} of map ${type.padId} does not exist.`);
console.log(`DB migration: Warning: Dropdown key ${newData[dropdown.name]} for field ${dropdown.name} of type ${type.name} of map ${type.mapId} does not exist.`);
}
if(!isEqual(newData, object.data))
return this._db.helpers._updateMapObject(type.type == "line" ? "Line" : "Marker", object.padId, object.id, {data: newData}, true);
return this._db.helpers._updateMapObject(type.type == "line" ? "Line" : "Marker", object.mapId, object.id, {data: newData}, true);
}
dropdowns.forEach((dropdown) => {
@ -404,7 +440,7 @@ export default class DatabaseMigrations {
if(newDefault)
dropdown.default = newDefault.value;
else
console.log(`DB migration: Warning: Default dropdown key ${dropdown.default} for field ${dropdown.name} of type ${type.name} of map ${type.padId} does not exist.`);
console.log(`DB migration: Warning: Default dropdown key ${dropdown.default} for field ${dropdown.name} of type ${type.name} of map ${type.mapId} does not exist.`);
}
dropdown.options?.forEach((option: any) => {
@ -412,7 +448,7 @@ export default class DatabaseMigrations {
});
});
await this._db.helpers._updateMapObject("Type", type.padId, type.id, {fields: newFields}, true);
await this._db.helpers._updateMapObject("Type", type.mapId, type.id, {fields: newFields}, true);
}
}
@ -450,7 +486,7 @@ export default class DatabaseMigrations {
let i = 0;
for await (const { marker, ele } of stream) {
await this._db.helpers._updateMapObject("Marker", marker.padId, marker.id, { ele }, true);
await this._db.helpers._updateMapObject("Marker", marker.mapId, marker.id, { ele }, true);
if (++i % 1000 === 0) {
console.log(`DB migration: Elevation migration ${i}/${markers.length}`);
@ -493,7 +529,7 @@ export default class DatabaseMigrations {
}
}
await this._db.helpers._updateMapObject("Type", type.padId, type.id, { showInLegend }, true);
await this._db.helpers._updateMapObject("Type", type.mapId, type.id, { showInLegend }, true);
}
await this._db.meta.setMeta("hasLegendOption", "1");
@ -518,9 +554,9 @@ export default class DatabaseMigrations {
});
if(isNaN(bbox.top) || isNaN(bbox.left) || isNaN(bbox.bottom) || isNaN(bbox.right)) // This is a broken line without track points
await this._db.helpers._deleteMapObject("Line", line.padId, line.id);
await this._db.helpers._deleteMapObject("Line", line.mapId, line.id);
else
await this._db.helpers._updateMapObject("Line", line.padId, line.id, bbox, true);
await this._db.helpers._updateMapObject("Line", line.mapId, line.id, bbox, true);
}
await this._db.meta.setMeta("hasBboxes", "1");
@ -644,17 +680,17 @@ export default class DatabaseMigrations {
console.log("DB migration: Set initial values for Types.idx");
const allTypes = await this._db.types.TypeModel.findAll({
attributes: ["id", "padId"]
attributes: ["id", "mapId"]
});
let lastIndex: Record<MapId, number> = Object.create(null);
for (const type of allTypes) {
if (!Object.prototype.hasOwnProperty.call(lastIndex, type.padId)) {
lastIndex[type.padId] = -1;
if (!Object.prototype.hasOwnProperty.call(lastIndex, type.mapId)) {
lastIndex[type.mapId] = -1;
}
await type.update({ idx: ++lastIndex[type.padId] });
await type.update({ idx: ++lastIndex[type.mapId] });
}
await this._db.meta.setMeta("typesIdxMigrationCompleted", "1");
@ -668,17 +704,17 @@ export default class DatabaseMigrations {
console.log("DB migration: Set initial values for Views.idx");
const allViews = await this._db.views.ViewModel.findAll({
attributes: ["id", "padId"]
attributes: ["id", "mapId"]
});
let lastIndex: Record<MapId, number> = Object.create(null);
for (const view of allViews) {
if (!Object.prototype.hasOwnProperty.call(lastIndex, view.padId)) {
lastIndex[view.padId] = -1;
if (!Object.prototype.hasOwnProperty.call(lastIndex, view.mapId)) {
lastIndex[view.mapId] = -1;
}
await view.update({ idx: ++lastIndex[view.padId] });
await view.update({ idx: ++lastIndex[view.mapId] });
}
await this._db.meta.setMeta("viewsIdxMigrationCompleted", "1");

Wyświetl plik

@ -18,7 +18,7 @@ export default class DatabaseSearch {
const model = this._db._conn.model(kind) as ModelStatic<MarkerModel | LineModel>;
const objs = await model.findAll<MarkerModel | LineModel>({
where: and(
{ padId: mapId },
{ mapId },
where(fn("lower", col(`${kind}.name`)), {[Op.like]: `%${searchText.toLowerCase()}%`})
),
attributes: [ "id", "name", "typeId" ].concat(kind == "Marker" ? [ "pos", "lat", "lon", "icon" ] : [ "top", "left", "bottom", "right" ])

Wyświetl plik

@ -11,7 +11,7 @@ export interface TypeModel extends Model<InferAttributes<TypeModel>, InferCreati
name: string;
type: "marker" | "line";
idx: number;
padId: ForeignKey<MapModel["id"]>;
mapId: ForeignKey<MapModel["id"]>;
defaultColour: Colour;
colourFixed: boolean;
defaultSize: Size;
@ -85,8 +85,8 @@ export default class DatabaseTypes {
afterInit(): void {
const MapModel = this._db.maps.MapModel;
this.TypeModel.belongsTo(MapModel, makeNotNullForeignKey("pad", "padId"));
MapModel.hasMany(this.TypeModel, { foreignKey: "padId" });
this.TypeModel.belongsTo(MapModel, makeNotNullForeignKey("map", "mapId"));
MapModel.hasMany(this.TypeModel, { foreignKey: "mapId" });
}
getTypes(mapId: MapId): AsyncIterable<Type> {
@ -107,7 +107,7 @@ export default class DatabaseTypes {
for (const obj of newIndexes) {
if ((typeId == null || obj.id !== typeId) && obj.oldIdx !== obj.newIdx) {
const result = await this._db.helpers._updateMapObject<Type>("Type", mapId, obj.id, { idx: obj.newIdx }, true);
this._db.emit("type", result.padId, result);
this._db.emit("type", result.mapId, result);
}
}
@ -121,7 +121,7 @@ export default class DatabaseTypes {
...data,
idx
});
this._db.emit("type", createdType.padId, createdType);
this._db.emit("type", createdType.mapId, createdType);
return createdType;
}
@ -154,12 +154,12 @@ export default class DatabaseTypes {
}
const result = await this._db.helpers._updateMapObject<Type>("Type", mapId, typeId, data);
this._db.emit("type", result.padId, result);
this._db.emit("type", result.mapId, result);
if(Object.keys(rename).length > 0)
await this._db.helpers.renameObjectDataField(mapId, result.id, rename, result.type == "line");
await this.recalculateObjectStylesForType(result.padId, typeId, result.type == "line");
await this.recalculateObjectStylesForType(result.mapId, typeId, result.type == "line");
return result;
}
@ -170,8 +170,8 @@ export default class DatabaseTypes {
async isTypeUsed(mapId: MapId, typeId: ID): Promise<boolean> {
const [ marker, line ] = await Promise.all([
this._db.markers.MarkerModel.findOne({ where: { padId: mapId, typeId: typeId } }),
this._db.lines.LineModel.findOne({ where: { padId: mapId, typeId: typeId } })
this._db.markers.MarkerModel.findOne({ where: { mapId, typeId: typeId } }),
this._db.lines.LineModel.findOne({ where: { mapId, typeId: typeId } })
]);
return !!marker || !!line;

Wyświetl plik

@ -8,7 +8,7 @@ import { insertIdx } from "facilmap-utils";
export interface ViewModel extends Model<InferAttributes<ViewModel>, InferCreationAttributes<ViewModel>> {
id: CreationOptional<ID>;
padId: ForeignKey<MapModel["id"]>;
mapId: ForeignKey<MapModel["id"]>;
name: string;
idx: number;
baseLayer: string;
@ -58,8 +58,8 @@ export default class DatabaseViews {
}
afterInit(): void {
this.ViewModel.belongsTo(this._db.maps.MapModel, makeNotNullForeignKey("pad", "padId"));
this._db.maps.MapModel.hasMany(this.ViewModel, { foreignKey: "padId" });
this.ViewModel.belongsTo(this._db.maps.MapModel, makeNotNullForeignKey("map", "mapId"));
this._db.maps.MapModel.hasMany(this.ViewModel, { foreignKey: "mapId" });
}
getViews(mapId: MapId): AsyncIterable<View> {

Wyświetl plik

@ -27,9 +27,9 @@ export function exportGeoJson(database: Database, mapId: MapId, filter?: string)
searchEngines: mapData.searchEngines,
description: mapData.description,
clusterMarkers: mapData.clusterMarkers,
views: jsonStreamArray(mapAsyncIterator(database.views.getViews(mapId), (view) => omit(view, ["id", "padId"])))
views: jsonStreamArray(mapAsyncIterator(database.views.getViews(mapId), (view) => omit(view, ["id", "mapId"])))
}),
types: mapValues(types, (type) => omit(type, ["id", "padId"])),
types: mapValues(types, (type) => omit(type, ["id", "mapId"])),
features: jsonStreamArray(concatAsyncIterators(
flatMapAsyncIterator(database.markers.getMapMarkers(mapId), (marker) => {
if (filterFunc(marker, types[marker.typeId])) {

Wyświetl plik

@ -1,4 +1,4 @@
import { SocketVersion, type SocketEvents, type MultipleEvents, type MapData, type Line, type FindMapsResult, type FindOnMapLine, type SocketServerToClientEmitArgs, type LegacyV2FindOnMapMarker, type LegacyV2Marker, type LegacyV2FindOnMapResult } from "facilmap-types";
import { SocketVersion, type SocketEvents, type MultipleEvents, type MapData, type FindMapsResult, type FindOnMapLine, type SocketServerToClientEmitArgs, type LegacyV2FindOnMapMarker, type LegacyV2Marker, type LegacyV2FindOnMapResult, type LegacyV2Line } from "facilmap-types";
import { SocketConnectionV2 } from "./socket-v2";
import { mapMultipleEvents, type SocketConnection, type SocketHandlers } from "./socket-common";
import { normalizeLineName, normalizeMarkerName, normalizeMapName } from "facilmap-utils";
@ -18,7 +18,7 @@ function prepareMarker<M extends LegacyV2Marker | LegacyV2FindOnMapMarker>(marke
};
}
function prepareLine<L extends Line | FindOnMapLine>(line: L): L {
function prepareLine<L extends LegacyV2Line | FindOnMapLine>(line: L): L {
return {
...line,
name: normalizeLineName(line.name)
@ -68,24 +68,24 @@ export class SocketConnectionV1 implements SocketConnection<SocketVersion.V1> {
}
getSocketHandlers(): SocketHandlers<SocketVersion.V1> {
const socketHandlers = this.socketV2.getSocketHandlers();
const socketHandlersV2 = this.socketV2.getSocketHandlers();
return {
...socketHandlers,
setPadId: mapResult(socketHandlers.setPadId, (events) => prepareMultiple(events)),
updateBbox: mapResult(socketHandlers.updateBbox, (events) => prepareMultiple(events)),
getPad: mapResult(socketHandlers.getPad, (result) => result ? prepareMapData(result) : result),
findPads: mapResult(socketHandlers.findPads, (result) => ({ ...result, results: result.results.map((r) => prepareMapData(r)) })),
createPad: mapResult(socketHandlers.createPad, (events) => prepareMultiple(events)),
editPad: mapResult(socketHandlers.editPad, (mapData) => prepareMapData(mapData)),
getMarker: mapResult(socketHandlers.getMarker, (marker) => prepareMarker(marker)),
addMarker: mapResult(socketHandlers.addMarker, (marker) => prepareMarker(marker)),
editMarker: mapResult(socketHandlers.editMarker, (marker) => prepareMarker(marker)),
deleteMarker: mapResult(socketHandlers.deleteMarker, (marker) => prepareMarker(marker)),
addLine: mapResult(socketHandlers.addLine, (line) => prepareLine(line)),
editLine: mapResult(socketHandlers.editLine, (line) => prepareLine(line)),
deleteLine: mapResult(socketHandlers.deleteLine, (line) => prepareLine(line)),
findOnMap: mapResult(socketHandlers.findOnMap, (results) => results.map((r) => prepareMapResult(r)))
...socketHandlersV2,
setPadId: mapResult(socketHandlersV2.setPadId, (events) => prepareMultiple(events)),
updateBbox: mapResult(socketHandlersV2.updateBbox, (events) => prepareMultiple(events)),
getPad: mapResult(socketHandlersV2.getPad, (result) => result ? prepareMapData(result) : result),
findPads: mapResult(socketHandlersV2.findPads, (result) => ({ ...result, results: result.results.map((r) => prepareMapData(r)) })),
createPad: mapResult(socketHandlersV2.createPad, (events) => prepareMultiple(events)),
editPad: mapResult(socketHandlersV2.editPad, (mapData) => prepareMapData(mapData)),
getMarker: mapResult(socketHandlersV2.getMarker, (marker) => prepareMarker(marker)),
addMarker: mapResult(socketHandlersV2.addMarker, (marker) => prepareMarker(marker)),
editMarker: mapResult(socketHandlersV2.editMarker, (marker) => prepareMarker(marker)),
deleteMarker: mapResult(socketHandlersV2.deleteMarker, (marker) => prepareMarker(marker)),
addLine: mapResult(socketHandlersV2.addLine, (line) => prepareLine(line)),
editLine: mapResult(socketHandlersV2.editLine, (line) => prepareLine(line)),
deleteLine: mapResult(socketHandlersV2.deleteLine, (line) => prepareLine(line)),
findOnMap: mapResult(socketHandlersV2.findOnMap, (results) => results.map((r) => prepareMapResult(r)))
};
}

Wyświetl plik

@ -1,4 +1,4 @@
import { SocketVersion, type SocketEvents, type MultipleEvents, type FindOnMapResult, type SocketServerToClientEmitArgs, legacyV2MarkerToCurrent, currentMarkerToLegacyV2, currentTypeToLegacyV2, legacyV2TypeToCurrent, mapHistoryEntry, MapNotFoundError } from "facilmap-types";
import { SocketVersion, type SocketEvents, type MultipleEvents, type FindOnMapResult, type SocketServerToClientEmitArgs, legacyV2MarkerToCurrent, currentMarkerToLegacyV2, currentTypeToLegacyV2, legacyV2TypeToCurrent, mapHistoryEntry, MapNotFoundError, currentLineToLegacyV2, currentViewToLegacyV2, currentHistoryEntryToLegacyV2 } from "facilmap-types";
import { mapMultipleEvents, type SocketConnection, type SocketHandlers } from "./socket-common";
import { SocketConnectionV3 } from "./socket-v3";
import type Database from "../database/database";
@ -7,21 +7,35 @@ import { omit } from "lodash-es";
function prepareEvent(...args: SocketServerToClientEmitArgs<SocketVersion.V3>): Array<SocketServerToClientEmitArgs<SocketVersion.V2>> {
if (args[0] === "marker") {
return [[args[0], currentMarkerToLegacyV2(args[1])]];
} else if (args[0] === "line") {
return [[args[0], currentLineToLegacyV2(args[1])]];
} else if (args[0] === "type") {
return [[args[0], currentTypeToLegacyV2(args[1])]];
} else if (args[0] === "view") {
return [[args[0], currentViewToLegacyV2(args[1])]];
} else if (args[0] === "history") {
if (args[1].type === "Marker") {
return [[
args[0],
mapHistoryEntry(args[1], (obj) => obj && currentMarkerToLegacyV2(obj))
currentHistoryEntryToLegacyV2(mapHistoryEntry(args[1], (obj) => obj && currentMarkerToLegacyV2(obj)))
]];
} else if (args[1].type === "Line") {
return [[
args[0],
currentHistoryEntryToLegacyV2(mapHistoryEntry(args[1], (obj) => obj && currentLineToLegacyV2(obj)))
]];
} else if (args[1].type === "Type") {
return [[
args[0],
mapHistoryEntry(args[1], (obj) => obj && currentTypeToLegacyV2(obj))
currentHistoryEntryToLegacyV2(mapHistoryEntry(args[1], (obj) => obj && currentTypeToLegacyV2(obj)))
]];
} else if (args[1].type === "View") {
return [[
args[0],
currentHistoryEntryToLegacyV2(mapHistoryEntry(args[1], (obj) => obj && currentViewToLegacyV2(obj)))
]];
} else {
return [[args[0], args[1]]];
return [[args[0], currentHistoryEntryToLegacyV2(args[1])]];
}
} else if (args[0] === "mapData") {
return [["padData", args[1]]];
@ -87,6 +101,12 @@ export class SocketConnectionV2 implements SocketConnection<SocketVersion.V2> {
revertHistoryEntry: async (entry) => prepareMultiple(await socketHandlersV3.revertHistoryEntry(entry)),
getMarker: async (data) => currentMarkerToLegacyV2(await socketHandlersV3.getMarker(data)),
deleteMarker: async (data) => currentMarkerToLegacyV2(await socketHandlersV3.deleteMarker(data)),
addLine: async (line) => currentLineToLegacyV2(await socketHandlersV3.addLine(line)),
editLine: async (line) => currentLineToLegacyV2(await socketHandlersV3.editLine(line)),
deleteLine: async (data) => currentLineToLegacyV2(await socketHandlersV3.deleteLine(data)),
addView: async (view) => currentViewToLegacyV2(await socketHandlersV3.addView(view)),
editView: async (view) => currentViewToLegacyV2(await socketHandlersV3.editView(view)),
deleteView: async (view) => currentViewToLegacyV2(await socketHandlersV3.deleteView(view)),
findOnMap: async (data) => (await socketHandlersV3.findOnMap(data)).map((result) => prepareMapResultOutput(result)),
deleteType: async (data) => currentTypeToLegacyV2(await socketHandlersV3.deleteType(data))
};

Wyświetl plik

@ -5,16 +5,16 @@ import type { ID } from "./base.js";
import type { Marker } from "./marker.js";
import type { Line } from "./line.js";
export type MarkerFeature = Feature<Point, Omit<Marker, "id" | "padId" | "lat" | "lon" | "ele">>;
export type LineFeature = Feature<LineString, Omit<Line, "id" | "padId" | "top" | "left" | "right" | "bottom" | "extraInfo" | "ascent" | "descent">>;
export type MarkerFeature = Feature<Point, Omit<Marker, "id" | "mapId" | "lat" | "lon" | "ele">>;
export type LineFeature = Feature<LineString, Omit<Line, "id" | "mapId" | "top" | "left" | "right" | "bottom" | "extraInfo" | "ascent" | "descent">>;
export interface GeoJsonExtensions {
name: string;
searchEngines: boolean;
description: string;
clusterMarkers: boolean;
views: Array<Omit<View, "id" | "padId">>;
types: Record<ID, Omit<Type, "id" | "padId">>;
views: Array<Omit<View, "id" | "mapId">>;
types: Record<ID, Omit<Type, "id" | "mapId">>;
}
export type GeoJsonExport = Omit<FeatureCollection, "features"> & {

Wyświetl plik

@ -25,7 +25,7 @@ export type GenericHistoryEntry<ObjectTypes extends Record<HistoryEntryType, any
time: string;
type: Type;
action: Action;
padId: MapId;
mapId: MapId;
} & (Action extends "create" ? {
objectBefore?: undefined;
} : {
@ -44,4 +44,4 @@ export type GenericHistoryEntry<ObjectTypes extends Record<HistoryEntryType, any
export type HistoryEntry = GenericHistoryEntry<HistoryEntryObjectTypes>;
export type HistoryEntryCreate = Omit<HistoryEntry, "id" | "time" | "padId">;
export type HistoryEntryCreate = Omit<HistoryEntry, "id" | "time" | "mapId">;

Wyświetl plik

@ -30,7 +30,7 @@ export const lineValidator = cruValidator({
ascent: onlyRead(z.number().or(z.null())),
descent: onlyRead(z.number().or(z.null())),
time: onlyRead(z.number().or(z.null())),
padId: onlyRead(mapIdValidator),
mapId: onlyRead(mapIdValidator),
trackPoints: exceptRead(z.array(trackPointValidator.create).optional())
});

Wyświetl plik

@ -4,7 +4,7 @@ import * as z from "zod";
export const markerValidator = cruValidator({
id: onlyRead(idValidator),
padId: onlyRead(mapIdValidator),
mapId: onlyRead(mapIdValidator),
...mapValues(pointValidator.shape, optionalUpdate),
typeId: optionalUpdate(idValidator),
name: optionalCreate(z.string().trim().max(100), ""),

Wyświetl plik

@ -28,7 +28,7 @@ export const lineTemplateRequestValidator = z.object({
});
export type LineTemplateRequest = z.infer<typeof lineTemplateRequestValidator>;
export type LineTemplate = Omit<Line, "id" | "routePoints" | "extraInfo" | keyof Bbox | "distance" | "ascent" | "descent" | "time" | "padId">;
export type LineTemplate = Omit<Line, "id" | "routePoints" | "extraInfo" | keyof Bbox | "distance" | "ascent" | "descent" | "time" | "mapId">;
export const lineExportRequestValidator = z.object({
id: idValidator,

Wyświetl plik

@ -1,4 +1,4 @@
import { idValidator, type ReplaceProperties } from "../base.js";
import { idValidator, type MapId, type ReplaceProperties } from "../base.js";
import { markerValidator } from "../marker.js";
import { refineRawTypeValidator, rawTypeValidator, fieldOptionValidator, refineRawFieldOptionsValidator, fieldValidator, refineRawFieldsValidator, defaultFields } from "../type.js";
import type { MultipleEvents } from "../events.js";
@ -8,19 +8,29 @@ import type { CRU, CRUType } from "../cru.js";
import * as z from "zod";
import type { GenericHistoryEntry, HistoryEntryObjectTypes } from "../historyEntry.js";
import { omit } from "lodash-es";
import { lineValidator } from "../line.js";
import { viewValidator } from "../view.js";
// Socket v2:
// - “icon” is called “symbol” in `Marker.symbol`, `Type.defaultSymbol`, `Type.symbolFixed`, `Type.fields[].controlSymbol` and
// `Type.fields[].options[].symbol`.
// - “map” is called “pad” in events, types, methods
// - "MapNotFoundError" is called "PadNotFoundError"
export const legacyV2MarkerValidator = {
read: markerValidator.read.omit({ icon: true }).extend({ symbol: markerValidator.read.shape.icon }),
read: markerValidator.read.omit({ icon: true, mapId: true }).extend({ symbol: markerValidator.read.shape.icon, padId: markerValidator.read.shape.mapId }),
create: markerValidator.create.omit({ icon: true }).extend({ symbol: markerValidator.create.shape.icon }),
update: markerValidator.update.omit({ icon: true }).extend({ symbol: markerValidator.update.shape.icon })
};
export type LegacyV2Marker<Mode extends CRU = CRU.READ> = CRUType<Mode, typeof legacyV2MarkerValidator>;
export const legacyV2LineValidator = {
read: lineValidator.read.omit({ mapId: true }).extend({ padId: lineValidator.read.shape.mapId }),
create: lineValidator.create,
update: lineValidator.update
};
export type LegacyV2Line<Mode extends CRU = CRU.READ> = CRUType<Mode, typeof legacyV2LineValidator>;
export const legacyV2FieldOptionsValidator = refineRawFieldOptionsValidator({
read: z.array(fieldOptionValidator.read.omit({ icon: true }).extend({ symbol: fieldOptionValidator.read.shape.icon })),
create: z.array(fieldOptionValidator.create.omit({ icon: true }).extend({ symbol: fieldOptionValidator.create.shape.icon })),
@ -43,10 +53,11 @@ export const legacyV2FieldsValidator = refineRawFieldsValidator({
});
export const legacyV2TypeValidator = refineRawTypeValidator({
read: rawTypeValidator.read.omit({ defaultIcon: true, iconFixed: true, fields: true }).extend({
read: rawTypeValidator.read.omit({ defaultIcon: true, iconFixed: true, fields: true, mapId: true }).extend({
defaultSymbol: rawTypeValidator.read.shape.defaultIcon,
symbolFixed: rawTypeValidator.read.shape.iconFixed,
fields: legacyV2FieldsValidator.read
fields: legacyV2FieldsValidator.read,
padId: rawTypeValidator.read.shape.mapId
}),
create: rawTypeValidator.create.omit({ defaultIcon: true, iconFixed: true }).extend({
defaultSymbol: rawTypeValidator.create.shape.defaultIcon,
@ -61,13 +72,24 @@ export const legacyV2TypeValidator = refineRawTypeValidator({
});
export type LegacyV2Type<Mode extends CRU = CRU.READ> = CRUType<Mode, typeof legacyV2TypeValidator>;
export const legacyV2ViewValidator = {
read: viewValidator.read.omit({ mapId: true }).extend({ padId: viewValidator.read.shape.mapId }),
create: viewValidator.create,
update: viewValidator.update
};
export type LegacyV2View<Mode extends CRU = CRU.READ> = CRUType<Mode, typeof legacyV2ViewValidator>;
export type LegacyV2FindOnMapMarker = RenameProperty<FindOnMapMarker, "icon", "symbol", false>;
export type LegacyV2FindOnMapResult = LegacyV2FindOnMapMarker | Exclude<FindOnMapResult, FindOnMapMarker>;
export type LegacyV2HistoryEntry = GenericHistoryEntry<ReplaceProperties<HistoryEntryObjectTypes, {
export type LegacyV2HistoryEntry = Omit<GenericHistoryEntry<ReplaceProperties<HistoryEntryObjectTypes, {
Marker: Omit<LegacyV2Marker, "id">;
Line: Omit<LegacyV2Line, "id">;
Type: Omit<LegacyV2Type, "id">;
}>>;
View: Omit<LegacyV2View, "id">;
}>>, "mapId"> & {
padId: MapId;
};
export const legacyV2GetMapQueryValidator = z.object({
padId: z.string()
@ -100,16 +122,24 @@ export type ResponseDataMapV2 = ReplaceProperties<Omit<ResponseDataMapV3, "getMa
addMarker: LegacyV2Marker;
editMarker: LegacyV2Marker;
deleteMarker: LegacyV2Marker;
addLine: LegacyV2Line;
editLine: LegacyV2Line;
deleteLine: LegacyV2Line;
findOnMap: Array<LegacyV2FindOnMapResult>;
addType: LegacyV2Type;
editType: LegacyV2Type;
deleteType: LegacyV2Type;
addView: LegacyV2View;
editView: LegacyV2View;
deleteView: LegacyV2View;
setPadId: MultipleEvents<MapEventsV2>;
}>;
export type MapEventsV2 = ReplaceProperties<Omit<MapEventsV3, "mapData" | "deleteMap">, {
marker: [LegacyV2Marker];
line: [LegacyV2Line];
type: [LegacyV2Type];
view: [LegacyV2View];
history: [LegacyV2HistoryEntry];
padData: MapEventsV3["mapData"];
deletePad: MapEventsV3["deleteMap"];
@ -119,8 +149,12 @@ export function legacyV2MarkerToCurrent<M extends Record<keyof any, any>, KeepOl
return renameProperty(marker, "symbol", "icon", keepOld);
}
export function currentMarkerToLegacyV2<M extends Record<keyof any, any>, KeepOld extends boolean = false>(marker: M, keepOld?: KeepOld): RenameProperty<M, "icon", "symbol", KeepOld> {
return renameProperty(marker, "icon", "symbol", keepOld);
export function currentMarkerToLegacyV2<M extends Record<keyof any, any>, KeepOld extends boolean = false>(marker: M, keepOld?: KeepOld): RenameProperty<RenameProperty<M, "icon", "symbol", KeepOld>, "mapId", "padId", KeepOld> {
return renameProperty(renameProperty(marker, "icon", "symbol", keepOld), "mapId", "padId", keepOld);
}
export function currentLineToLegacyV2<L extends Record<keyof any, any>, KeepOld extends boolean = false>(line: L, keepOld?: KeepOld): RenameProperty<L, "mapId", "padId", KeepOld> {
return renameProperty(line, "mapId", "padId", keepOld);
}
type RenameNestedArrayProperty<T, Key extends keyof any, From extends keyof any, To extends keyof any, KeepOld extends boolean = false> = (
@ -135,6 +169,8 @@ type RenameNestedNestedArrayProperty<T, Key1 extends keyof any, Key2 extends key
);
type RenameTypeProperties<
T,
MapIdKeyOld extends keyof any,
MapIdKeyNew extends keyof any,
DefaultIconKeyOld extends keyof any,
DefaultIconKeyNew extends keyof any,
IconFixedKeyOld extends keyof any,
@ -147,14 +183,16 @@ type RenameTypeProperties<
> = RenameNestedNestedArrayProperty<
RenameNestedArrayProperty<
RenameProperty<
RenameProperty<T, DefaultIconKeyOld, DefaultIconKeyNew, KeepOld>,
RenameProperty<
RenameProperty<T, MapIdKeyOld, MapIdKeyNew, KeepOld>,
DefaultIconKeyOld, DefaultIconKeyNew, KeepOld>,
IconFixedKeyOld, IconFixedKeyNew, KeepOld
>, "fields", ControlIconKeyOld, ControlIconKeyNew, KeepOld
>, "fields", "options", OptionIconKeyOld, OptionIconKeyNew, KeepOld
>;
export function legacyV2TypeToCurrent<T extends Record<keyof any, any>, KeepOld extends boolean = false>(type: T, keepOld?: KeepOld): RenameTypeProperties<T, "defaultSymbol", "defaultIcon", "symbolFixed", "iconFixed", "controlSymbol", "controlIcon", "symbol", "icon", KeepOld> {
const renamedType = renameProperty(renameProperty(type, "defaultSymbol", "defaultIcon", keepOld), "symbolFixed", "iconFixed", keepOld) as any;
export function legacyV2TypeToCurrent<T extends Record<keyof any, any>, KeepOld extends boolean = false>(type: T, keepOld?: KeepOld): RenameTypeProperties<T, "padId", "mapId", "defaultSymbol", "defaultIcon", "symbolFixed", "iconFixed", "controlSymbol", "controlIcon", "symbol", "icon", KeepOld> {
const renamedType = renameProperty(renameProperty(renameProperty(type, "defaultSymbol", "defaultIcon", keepOld), "symbolFixed", "iconFixed", keepOld), "padId", "mapId", keepOld) as any;
if (renamedType.fields && Array.isArray(renamedType.fields)) {
renamedType.fields = renamedType.fields.map((field: any) => {
@ -169,8 +207,8 @@ export function legacyV2TypeToCurrent<T extends Record<keyof any, any>, KeepOld
return renamedType;
}
export function currentTypeToLegacyV2<T extends Record<keyof any, any>, KeepOld extends boolean = false>(type: T, keepOld?: KeepOld): RenameTypeProperties<T, "defaultIcon", "defaultSymbol", "iconFixed", "symbolFixed", "controlIcon", "controlSymbol", "icon", "symbol", KeepOld> {
const renamedType = renameProperty(renameProperty(type, "defaultIcon", "defaultSymbol", keepOld), "iconFixed", "symbolFixed", keepOld) as any;
export function currentTypeToLegacyV2<T extends Record<keyof any, any>, KeepOld extends boolean = false>(type: T, keepOld?: KeepOld): RenameTypeProperties<T, "mapId", "padId", "defaultIcon", "defaultSymbol", "iconFixed", "symbolFixed", "controlIcon", "controlSymbol", "icon", "symbol", KeepOld> {
const renamedType = renameProperty(renameProperty(renameProperty(type, "defaultIcon", "defaultSymbol", keepOld), "iconFixed", "symbolFixed", keepOld), "mapId", "padId", keepOld) as any;
if (renamedType.fields && Array.isArray(renamedType.fields)) {
renamedType.fields = renamedType.fields.map((field: any) => {
@ -183,4 +221,12 @@ export function currentTypeToLegacyV2<T extends Record<keyof any, any>, KeepOld
}
return renamedType;
}
export function currentViewToLegacyV2<V extends Record<keyof any, any>, KeepOld extends boolean = false>(view: V, keepOld?: KeepOld): RenameProperty<V, "mapId", "padId", KeepOld> {
return renameProperty(view, "mapId", "padId", keepOld);
}
export function currentHistoryEntryToLegacyV2<H extends Record<keyof any, any>>(historyEntry: H): RenameProperty<H, "mapId", "padId"> {
return renameProperty(historyEntry, "mapId", "padId");
}

Wyświetl plik

@ -127,7 +127,7 @@ export const defaultFields = (): Field[] => [ { name: "Description", type: "text
export const rawTypeValidator = cruValidator({
id: onlyRead(idValidator),
type: exceptUpdate(objectTypeValidator),
padId: onlyRead(mapIdValidator),
mapId: onlyRead(mapIdValidator),
name: optionalUpdate(z.string().trim().min(1).max(100)),
idx: optionalCreate(z.number().int().min(0)),

Wyświetl plik

@ -4,7 +4,7 @@ import * as z from "zod";
export const viewValidator = cruValidator({
id: onlyRead(idValidator),
padId: onlyRead(mapIdValidator),
mapId: onlyRead(mapIdValidator),
name: optionalUpdate(z.string().trim().min(1).max(100)),
idx: optionalCreate(z.number().int().min(0)),