@musnows/scriverse 0.4.9 → 0.4.11
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/app.js +126 -26
- package/dist/app.js.map +1 -1
- package/dist/collaboration-presence.js +77 -2
- package/dist/collaboration-presence.js.map +1 -1
- package/dist/public/app.js +94 -18
- package/dist/public/display-labels.d.ts +1 -0
- package/dist/public/display-labels.js +8 -0
- package/dist/public/index.html +41 -40
- package/dist/public/markdown.js +16 -0
- package/dist/public/race-hierarchy.js +36 -0
- package/dist/public/relationship-graph.js +32 -10
- package/dist/public/styles.css +39 -20
- package/dist/store.js +3 -3
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -24,10 +24,10 @@ import { assertSafeImportedPlainText, decodeUtf8ImportedText } from "./import-se
|
|
|
24
24
|
import { InvalidRasterImageError, readRasterImageMetadata } from "./image-metadata.js";
|
|
25
25
|
import { createRequestLoggingMiddleware, sanitizeRequestPath } from "./http-logging.js";
|
|
26
26
|
import { accountReference, logger, sanitizeError } from "./logger.js";
|
|
27
|
-
import { runWithRequestActor } from "./request-context.js";
|
|
27
|
+
import { currentRequestActor, runWithRequestActor } from "./request-context.js";
|
|
28
28
|
import { APP_VERSION } from "./version.js";
|
|
29
29
|
import { fullWorkModulePermissions, proseReplacementPermissionModules } from "./work-permissions.js";
|
|
30
|
-
import { CollaborationPresence, presencePageKinds } from "./collaboration-presence.js";
|
|
30
|
+
import { CollaborationPresence, editorPageKey, entityEditorPageKey, modulePageKey, pageLabelForKey, presencePageKinds } from "./collaboration-presence.js";
|
|
31
31
|
import { clearSessionCookie, createCliApiScopeMiddleware, createUserSessionMiddleware, createWorkAuthorizationMiddleware, setSessionCookie, UserAuthService } from "./user-auth.js";
|
|
32
32
|
const nonEmpty = z.string().trim().min(1);
|
|
33
33
|
const identifier = z.string().trim().min(1).max(200);
|
|
@@ -423,6 +423,15 @@ export function createRuntime(options) {
|
|
|
423
423
|
mkdirSync(attachmentStorage.temporaryDirectory, { recursive: true, mode: 0o700 });
|
|
424
424
|
const auth = new UserAuthService(database);
|
|
425
425
|
const collaborationPresence = new CollaborationPresence();
|
|
426
|
+
const publishCollaborativeChange = (workId, pageKey, label = pageLabelForKey(pageKey)) => {
|
|
427
|
+
const actor = currentRequestActor();
|
|
428
|
+
if (!actor || !workId || !pageKey)
|
|
429
|
+
return;
|
|
430
|
+
collaborationPresence.publishChange(workId, pageKey, {
|
|
431
|
+
userId: actor.userId,
|
|
432
|
+
displayName: actor.displayName
|
|
433
|
+
}, label);
|
|
434
|
+
};
|
|
426
435
|
const getDevelopmentUser = () => options.devAuthBypass
|
|
427
436
|
? auth.listUsers().find((user) => user.status === "active") ?? null
|
|
428
437
|
: null;
|
|
@@ -792,11 +801,15 @@ export function createRuntime(options) {
|
|
|
792
801
|
app.patch("/api/chapters/:chapterId", (request, response) => {
|
|
793
802
|
const input = parse(z.object({ title: nonEmpty.max(300).optional(), content: z.string().max(2_000_000).optional(), excludedFromAnalysis: z.boolean().optional(), chapterType: chapterTypeSchema.optional(), source: z.enum(["manual", "auto"]).optional(), changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
794
803
|
const { source, changeNote, expectedVersionNo, ...chapterInput } = input;
|
|
795
|
-
|
|
804
|
+
const chapter = store.saveChapter(request.params.chapterId, chapterInput, source ?? "manual", null, changeNote, expectedVersionNo);
|
|
805
|
+
publishCollaborativeChange(String(chapter.workId), editorPageKey(String(chapter.id)));
|
|
806
|
+
data(response, chapter);
|
|
796
807
|
});
|
|
797
808
|
app.delete("/api/chapters/:chapterId", (request, response) => {
|
|
798
809
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
810
|
+
const chapter = store.getChapter(request.params.chapterId);
|
|
799
811
|
store.deleteChapter(request.params.chapterId, input.expectedVersionNo);
|
|
812
|
+
publishCollaborativeChange(String(chapter.workId), editorPageKey(String(chapter.id)));
|
|
800
813
|
noContent(response);
|
|
801
814
|
});
|
|
802
815
|
app.get("/api/chapters/:chapterId/versions", (request, response) => {
|
|
@@ -809,7 +822,9 @@ export function createRuntime(options) {
|
|
|
809
822
|
});
|
|
810
823
|
app.post("/api/chapters/:chapterId/restore", (request, response) => {
|
|
811
824
|
const input = parse(z.object({ versionNo: z.number().int().positive(), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
812
|
-
|
|
825
|
+
const chapter = store.restoreChapter(request.params.chapterId, input.versionNo, input.expectedVersionNo);
|
|
826
|
+
publishCollaborativeChange(String(chapter.workId), editorPageKey(String(chapter.id)));
|
|
827
|
+
data(response, chapter);
|
|
813
828
|
});
|
|
814
829
|
app.post("/api/chapters/:chapterId/move", (request, response) => {
|
|
815
830
|
const input = parse(z.object({ volumeId: identifier, sortOrder: z.number().int().min(0), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
@@ -823,11 +838,15 @@ export function createRuntime(options) {
|
|
|
823
838
|
app.get("/api/chapters/:chapterId/outline", (request, response) => data(response, store.getChapterOutline(request.params.chapterId)));
|
|
824
839
|
app.put("/api/chapters/:chapterId/outline", (request, response) => {
|
|
825
840
|
const { changeNote, expectedVersionNo, ...input } = parse(chapterOutlineSchema.extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
826
|
-
|
|
841
|
+
const outline = store.upsertChapterOutline(request.params.chapterId, input, "manual", null, changeNote, expectedVersionNo);
|
|
842
|
+
publishCollaborativeChange(String(outline.workId), modulePageKey("outlines"));
|
|
843
|
+
data(response, outline);
|
|
827
844
|
});
|
|
828
845
|
app.delete("/api/chapters/:chapterId/outline", (request, response) => {
|
|
829
846
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
847
|
+
const chapter = store.getChapter(request.params.chapterId);
|
|
830
848
|
store.deleteChapterOutline(request.params.chapterId, input.expectedVersionNo);
|
|
849
|
+
publishCollaborativeChange(String(chapter.workId), modulePageKey("outlines"));
|
|
831
850
|
noContent(response);
|
|
832
851
|
});
|
|
833
852
|
app.get("/api/works/:workId/foreshadows", (request, response) => {
|
|
@@ -841,31 +860,43 @@ export function createRuntime(options) {
|
|
|
841
860
|
: store.listForeshadows(request.params.workId, query.status, query.currentChapterId));
|
|
842
861
|
});
|
|
843
862
|
app.post("/api/works/:workId/foreshadows", (request, response) => {
|
|
844
|
-
|
|
863
|
+
const foreshadow = store.createForeshadow(request.params.workId, parse(foreshadowSchema, request.body));
|
|
864
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("outlines"));
|
|
865
|
+
data(response, foreshadow, 201);
|
|
845
866
|
});
|
|
846
867
|
app.get("/api/foreshadows/:foreshadowId", (request, response) => data(response, store.getForeshadow(request.params.foreshadowId)));
|
|
847
868
|
app.patch("/api/foreshadows/:foreshadowId", (request, response) => {
|
|
848
869
|
const { changeNote, expectedVersionNo, ...input } = parse(foreshadowSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
849
|
-
|
|
870
|
+
const foreshadow = store.updateForeshadow(request.params.foreshadowId, input, "manual", null, changeNote, expectedVersionNo);
|
|
871
|
+
publishCollaborativeChange(String(foreshadow.workId), modulePageKey("outlines"));
|
|
872
|
+
data(response, foreshadow);
|
|
850
873
|
});
|
|
851
874
|
app.delete("/api/foreshadows/:foreshadowId", (request, response) => {
|
|
852
875
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
876
|
+
const foreshadow = store.getForeshadow(request.params.foreshadowId);
|
|
853
877
|
store.deleteForeshadow(request.params.foreshadowId, input.expectedVersionNo);
|
|
878
|
+
publishCollaborativeChange(String(foreshadow.workId), modulePageKey("outlines"));
|
|
854
879
|
noContent(response);
|
|
855
880
|
});
|
|
856
881
|
app.post("/api/foreshadows/:foreshadowId/occurrences", (request, response) => {
|
|
857
882
|
const input = parse(foreshadowOccurrenceSchema.extend({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
858
883
|
const { expectedVersionNo, ...occurrenceInput } = input;
|
|
859
|
-
|
|
884
|
+
const occurrence = store.createForeshadowOccurrence(request.params.foreshadowId, occurrenceInput, expectedVersionNo);
|
|
885
|
+
publishCollaborativeChange(String(occurrence.workId), modulePageKey("outlines"));
|
|
886
|
+
data(response, occurrence, 201);
|
|
860
887
|
});
|
|
861
888
|
app.patch("/api/foreshadow-occurrences/:occurrenceId", (request, response) => {
|
|
862
889
|
const input = parse(foreshadowOccurrenceSchema.partial().extend({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
863
890
|
const { expectedVersionNo, ...occurrenceInput } = input;
|
|
864
|
-
|
|
891
|
+
const occurrence = store.updateForeshadowOccurrence(request.params.occurrenceId, occurrenceInput, expectedVersionNo);
|
|
892
|
+
publishCollaborativeChange(String(occurrence.workId), modulePageKey("outlines"));
|
|
893
|
+
data(response, occurrence);
|
|
865
894
|
});
|
|
866
895
|
app.delete("/api/foreshadow-occurrences/:occurrenceId", (request, response) => {
|
|
867
896
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
897
|
+
const occurrence = store.getForeshadowOccurrence(request.params.occurrenceId);
|
|
868
898
|
store.deleteForeshadowOccurrence(request.params.occurrenceId, input.expectedVersionNo);
|
|
899
|
+
publishCollaborativeChange(String(occurrence.workId), modulePageKey("outlines"));
|
|
869
900
|
noContent(response);
|
|
870
901
|
});
|
|
871
902
|
app.get("/api/works/:workId/settings", (request, response) => {
|
|
@@ -873,16 +904,24 @@ export function createRuntime(options) {
|
|
|
873
904
|
const includeContent = request.query.includeContent === "true";
|
|
874
905
|
data(response, pagination ? store.listSettingsPage(request.params.workId, pagination, includeContent) : store.listSettings(request.params.workId, includeContent));
|
|
875
906
|
});
|
|
876
|
-
app.post("/api/works/:workId/settings", (request, response) =>
|
|
907
|
+
app.post("/api/works/:workId/settings", (request, response) => {
|
|
908
|
+
const setting = store.createSetting(request.params.workId, parse(settingSchema, request.body));
|
|
909
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("settings"));
|
|
910
|
+
data(response, setting, 201);
|
|
911
|
+
});
|
|
877
912
|
app.get("/api/works/:workId/settings/context", (request, response) => data(response, store.listSettings(request.params.workId, true)));
|
|
878
913
|
app.get("/api/settings/:settingId", (request, response) => data(response, store.getSetting(request.params.settingId)));
|
|
879
914
|
app.patch("/api/settings/:settingId", (request, response) => {
|
|
880
915
|
const { changeNote, expectedVersionNo, ...input } = parse(settingSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
881
|
-
|
|
916
|
+
const setting = store.updateSetting(request.params.settingId, input, "manual", null, changeNote, expectedVersionNo);
|
|
917
|
+
publishCollaborativeChange(String(setting.workId), entityEditorPageKey("setting", String(setting.id)));
|
|
918
|
+
data(response, setting);
|
|
882
919
|
});
|
|
883
920
|
app.delete("/api/settings/:settingId", (request, response) => {
|
|
884
921
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
922
|
+
const setting = store.getSetting(request.params.settingId);
|
|
885
923
|
store.deleteSetting(request.params.settingId, input.expectedVersionNo);
|
|
924
|
+
publishCollaborativeChange(String(setting.workId), entityEditorPageKey("setting", String(setting.id)));
|
|
886
925
|
noContent(response);
|
|
887
926
|
});
|
|
888
927
|
app.get("/api/works/:workId/characters", (request, response) => {
|
|
@@ -900,6 +939,7 @@ export function createRuntime(options) {
|
|
|
900
939
|
});
|
|
901
940
|
app.post("/api/works/:workId/characters", (request, response) => {
|
|
902
941
|
const character = store.createCharacter(request.params.workId, parse(characterSchema, request.body));
|
|
942
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("characters"));
|
|
903
943
|
data(response, redactCharacterLinks(character, requestPermissions(request, request.params.workId)), 201);
|
|
904
944
|
});
|
|
905
945
|
app.get("/api/characters/:characterId", (request, response) => {
|
|
@@ -908,6 +948,7 @@ export function createRuntime(options) {
|
|
|
908
948
|
app.patch("/api/characters/:characterId", (request, response) => {
|
|
909
949
|
const { changeNote, expectedVersionNo, ...input } = parse(characterUpdateSchema.extend({ expectedVersionNo: expectedVersionNoSchema }), request.body);
|
|
910
950
|
const character = store.updateCharacter(request.params.characterId, input, "manual", null, changeNote, expectedVersionNo);
|
|
951
|
+
publishCollaborativeChange(String(character.workId), entityEditorPageKey("character", String(character.id)));
|
|
911
952
|
data(response, redactCharacterLinks(character, requestPermissions(request)));
|
|
912
953
|
});
|
|
913
954
|
app.get("/api/characters/:characterId/versions", (request, response) => {
|
|
@@ -919,11 +960,14 @@ export function createRuntime(options) {
|
|
|
919
960
|
app.post("/api/characters/:characterId/restore", (request, response) => {
|
|
920
961
|
const input = parse(z.object({ versionNo: z.number().int().positive(), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
921
962
|
const character = store.restoreCharacter(request.params.characterId, input.versionNo, input.expectedVersionNo);
|
|
963
|
+
publishCollaborativeChange(String(character.workId), entityEditorPageKey("character", String(character.id)));
|
|
922
964
|
data(response, redactCharacterLinks(character, requestPermissions(request)));
|
|
923
965
|
});
|
|
924
966
|
app.delete("/api/characters/:characterId", (request, response) => {
|
|
925
967
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
968
|
+
const character = store.getCharacter(request.params.characterId);
|
|
926
969
|
store.deleteCharacter(request.params.characterId, input.expectedVersionNo);
|
|
970
|
+
publishCollaborativeChange(String(character.workId), entityEditorPageKey("character", String(character.id)));
|
|
927
971
|
noContent(response);
|
|
928
972
|
});
|
|
929
973
|
app.post("/api/characters/:characterId/merge", (request, response) => {
|
|
@@ -947,18 +991,24 @@ export function createRuntime(options) {
|
|
|
947
991
|
: store.listCharacterProfileSections(request.params.characterId));
|
|
948
992
|
});
|
|
949
993
|
app.post("/api/characters/:characterId/sections", (request, response) => {
|
|
950
|
-
|
|
994
|
+
const section = store.createCharacterProfileSection(request.params.characterId, parse(characterProfileSectionSchema, request.body));
|
|
995
|
+
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
996
|
+
data(response, section, 201);
|
|
951
997
|
});
|
|
952
998
|
app.get("/api/character-sections/:sectionId", (request, response) => {
|
|
953
999
|
data(response, store.getCharacterProfileSection(request.params.sectionId));
|
|
954
1000
|
});
|
|
955
1001
|
app.patch("/api/character-sections/:sectionId", (request, response) => {
|
|
956
1002
|
const { changeNote, expectedVersionNo, ...input } = parse(characterProfileSectionSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
957
|
-
|
|
1003
|
+
const section = store.updateCharacterProfileSection(request.params.sectionId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1004
|
+
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
1005
|
+
data(response, section);
|
|
958
1006
|
});
|
|
959
1007
|
app.delete("/api/character-sections/:sectionId", (request, response) => {
|
|
960
1008
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1009
|
+
const section = store.getCharacterProfileSection(request.params.sectionId);
|
|
961
1010
|
store.deleteCharacterProfileSection(request.params.sectionId, input.expectedVersionNo);
|
|
1011
|
+
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
962
1012
|
noContent(response);
|
|
963
1013
|
});
|
|
964
1014
|
app.get("/api/character-sections/:sectionId/versions", (request, response) => {
|
|
@@ -969,7 +1019,9 @@ export function createRuntime(options) {
|
|
|
969
1019
|
});
|
|
970
1020
|
app.post("/api/character-sections/:sectionId/restore", (request, response) => {
|
|
971
1021
|
const input = parse(z.object({ versionNo: z.number().int().positive(), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
972
|
-
|
|
1022
|
+
const section = store.restoreCharacterProfileSection(request.params.sectionId, input.versionNo, input.expectedVersionNo);
|
|
1023
|
+
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
1024
|
+
data(response, section);
|
|
973
1025
|
});
|
|
974
1026
|
app.get("/api/works/:workId/attachments", (request, response) => {
|
|
975
1027
|
const pagination = parsePagination(request.query);
|
|
@@ -1025,6 +1077,7 @@ export function createRuntime(options) {
|
|
|
1025
1077
|
});
|
|
1026
1078
|
app.post("/api/works/:workId/races", (request, response) => {
|
|
1027
1079
|
const race = store.createRace(request.params.workId, parse(raceSchema, request.body));
|
|
1080
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("races"));
|
|
1028
1081
|
data(response, redactRaceMembers(race, requestPermissions(request, request.params.workId)), 201);
|
|
1029
1082
|
});
|
|
1030
1083
|
app.get("/api/races/:raceId", (request, response) => {
|
|
@@ -1033,11 +1086,14 @@ export function createRuntime(options) {
|
|
|
1033
1086
|
app.patch("/api/races/:raceId", (request, response) => {
|
|
1034
1087
|
const { changeNote, expectedVersionNo, ...input } = parse(raceSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1035
1088
|
const race = store.updateRace(request.params.raceId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1089
|
+
publishCollaborativeChange(String(race.workId), entityEditorPageKey("race", String(race.id)));
|
|
1036
1090
|
data(response, redactRaceMembers(race, requestPermissions(request)));
|
|
1037
1091
|
});
|
|
1038
1092
|
app.delete("/api/races/:raceId", (request, response) => {
|
|
1039
1093
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1094
|
+
const race = store.getRace(request.params.raceId);
|
|
1040
1095
|
store.deleteRace(request.params.raceId, input.expectedVersionNo);
|
|
1096
|
+
publishCollaborativeChange(String(race.workId), entityEditorPageKey("race", String(race.id)));
|
|
1041
1097
|
noContent(response);
|
|
1042
1098
|
});
|
|
1043
1099
|
app.post("/api/races/:raceId/merge", (request, response) => {
|
|
@@ -1055,6 +1111,7 @@ export function createRuntime(options) {
|
|
|
1055
1111
|
});
|
|
1056
1112
|
app.post("/api/works/:workId/organizations", (request, response) => {
|
|
1057
1113
|
const organization = store.createOrganization(request.params.workId, parse(organizationSchema, request.body));
|
|
1114
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("organizations"));
|
|
1058
1115
|
data(response, redactOrganizationMembers(organization, requestPermissions(request, request.params.workId)), 201);
|
|
1059
1116
|
});
|
|
1060
1117
|
app.get("/api/organizations/:organizationId", (request, response) => {
|
|
@@ -1063,11 +1120,14 @@ export function createRuntime(options) {
|
|
|
1063
1120
|
app.patch("/api/organizations/:organizationId", (request, response) => {
|
|
1064
1121
|
const { changeNote, expectedVersionNo, ...input } = parse(organizationSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1065
1122
|
const organization = store.updateOrganization(request.params.organizationId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1123
|
+
publishCollaborativeChange(String(organization.workId), entityEditorPageKey("organization", String(organization.id)));
|
|
1066
1124
|
data(response, redactOrganizationMembers(organization, requestPermissions(request)));
|
|
1067
1125
|
});
|
|
1068
1126
|
app.delete("/api/organizations/:organizationId", (request, response) => {
|
|
1069
1127
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1128
|
+
const organization = store.getOrganization(request.params.organizationId);
|
|
1070
1129
|
store.deleteOrganization(request.params.organizationId, input.expectedVersionNo);
|
|
1130
|
+
publishCollaborativeChange(String(organization.workId), entityEditorPageKey("organization", String(organization.id)));
|
|
1071
1131
|
noContent(response);
|
|
1072
1132
|
});
|
|
1073
1133
|
app.post("/api/organizations/:organizationId/merge", (request, response) => {
|
|
@@ -1080,22 +1140,34 @@ export function createRuntime(options) {
|
|
|
1080
1140
|
const pagination = parsePagination(request.query);
|
|
1081
1141
|
data(response, pagination ? store.listTimelineTracksPage(request.params.workId, pagination) : store.listTimelineTracks(request.params.workId));
|
|
1082
1142
|
});
|
|
1083
|
-
app.post("/api/works/:workId/timeline-tracks", (request, response) =>
|
|
1143
|
+
app.post("/api/works/:workId/timeline-tracks", (request, response) => {
|
|
1144
|
+
const track = store.createTimelineTrack(request.params.workId, parse(timelineTrackSchema, request.body));
|
|
1145
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("timeline"));
|
|
1146
|
+
data(response, track, 201);
|
|
1147
|
+
});
|
|
1084
1148
|
app.get("/api/timeline-tracks/:trackId", (request, response) => data(response, store.getTimelineTrack(request.params.trackId)));
|
|
1085
1149
|
app.patch("/api/timeline-tracks/:trackId", (request, response) => {
|
|
1086
1150
|
const { changeNote, expectedVersionNo, ...input } = parse(timelineTrackSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1087
|
-
|
|
1151
|
+
const track = store.updateTimelineTrack(request.params.trackId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1152
|
+
publishCollaborativeChange(String(track.workId), modulePageKey("timeline"));
|
|
1153
|
+
data(response, track);
|
|
1088
1154
|
});
|
|
1089
1155
|
app.delete("/api/timeline-tracks/:trackId", (request, response) => {
|
|
1090
1156
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1157
|
+
const track = store.getTimelineTrack(request.params.trackId);
|
|
1091
1158
|
store.deleteTimelineTrack(request.params.trackId, input.expectedVersionNo);
|
|
1159
|
+
publishCollaborativeChange(String(track.workId), modulePageKey("timeline"));
|
|
1092
1160
|
noContent(response);
|
|
1093
1161
|
});
|
|
1094
1162
|
app.get("/api/works/:workId/timeline", (request, response) => {
|
|
1095
1163
|
const pagination = parsePagination(request.query);
|
|
1096
1164
|
data(response, pagination ? store.listTimelineEventsPage(request.params.workId, pagination) : store.listTimelineEvents(request.params.workId));
|
|
1097
1165
|
});
|
|
1098
|
-
app.post("/api/works/:workId/timeline", (request, response) =>
|
|
1166
|
+
app.post("/api/works/:workId/timeline", (request, response) => {
|
|
1167
|
+
const event = store.createTimelineEvent(request.params.workId, parse(timelineSchema, request.body));
|
|
1168
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("timeline"));
|
|
1169
|
+
data(response, event, 201);
|
|
1170
|
+
});
|
|
1099
1171
|
app.post("/api/works/:workId/timeline/merge", (request, response) => {
|
|
1100
1172
|
const input = parse(z.object({
|
|
1101
1173
|
eventIds: z.array(identifier).min(2),
|
|
@@ -1106,12 +1178,16 @@ export function createRuntime(options) {
|
|
|
1106
1178
|
expectedVersionNos: z.record(identifier, z.number().int().positive()).optional()
|
|
1107
1179
|
}).strict(), request.body);
|
|
1108
1180
|
const { expectedVersionNos, ...mergeInput } = input;
|
|
1109
|
-
|
|
1181
|
+
const merged = store.mergeTimelineEvents(request.params.workId, input.eventIds, mergeInput, expectedVersionNos);
|
|
1182
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("timeline"));
|
|
1183
|
+
data(response, merged, 201);
|
|
1110
1184
|
});
|
|
1111
1185
|
app.get("/api/timeline/:eventId", (request, response) => data(response, store.getTimelineEvent(request.params.eventId)));
|
|
1112
1186
|
app.patch("/api/timeline/:eventId", (request, response) => {
|
|
1113
1187
|
const { changeNote, expectedVersionNo, ...input } = parse(timelineSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1114
|
-
|
|
1188
|
+
const event = store.updateTimelineEvent(request.params.eventId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1189
|
+
publishCollaborativeChange(String(event.workId), modulePageKey("timeline"));
|
|
1190
|
+
data(response, event);
|
|
1115
1191
|
});
|
|
1116
1192
|
app.post("/api/timeline/:eventId/split", (request, response) => {
|
|
1117
1193
|
const input = parse(z.object({
|
|
@@ -1123,11 +1199,17 @@ export function createRuntime(options) {
|
|
|
1123
1199
|
})).min(2),
|
|
1124
1200
|
expectedVersionNo: expectedVersionNoSchema
|
|
1125
1201
|
}).strict(), request.body);
|
|
1126
|
-
|
|
1202
|
+
const split = store.splitTimelineEvent(request.params.eventId, input.parts, input.expectedVersionNo);
|
|
1203
|
+
const first = split[0];
|
|
1204
|
+
if (first)
|
|
1205
|
+
publishCollaborativeChange(String(first.workId), modulePageKey("timeline"));
|
|
1206
|
+
data(response, split, 201);
|
|
1127
1207
|
});
|
|
1128
1208
|
app.delete("/api/timeline/:eventId", (request, response) => {
|
|
1129
1209
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1210
|
+
const event = store.getTimelineEvent(request.params.eventId);
|
|
1130
1211
|
store.deleteTimelineEvent(request.params.eventId, input.expectedVersionNo);
|
|
1212
|
+
publishCollaborativeChange(String(event.workId), modulePageKey("timeline"));
|
|
1131
1213
|
noContent(response);
|
|
1132
1214
|
});
|
|
1133
1215
|
app.get("/api/works/:workId/relationships", (request, response) => {
|
|
@@ -1139,15 +1221,23 @@ export function createRuntime(options) {
|
|
|
1139
1221
|
? store.listRelationshipsPage(request.params.workId, pagination, confidence)
|
|
1140
1222
|
: store.listRelationships(request.params.workId, confidence));
|
|
1141
1223
|
});
|
|
1142
|
-
app.post("/api/works/:workId/relationships", (request, response) =>
|
|
1224
|
+
app.post("/api/works/:workId/relationships", (request, response) => {
|
|
1225
|
+
const relationship = store.createRelationship(request.params.workId, parse(relationshipSchema, request.body));
|
|
1226
|
+
publishCollaborativeChange(request.params.workId, modulePageKey("relationships"));
|
|
1227
|
+
data(response, relationship, 201);
|
|
1228
|
+
});
|
|
1143
1229
|
app.get("/api/relationships/:relationshipId", (request, response) => data(response, store.getRelationship(request.params.relationshipId)));
|
|
1144
1230
|
app.patch("/api/relationships/:relationshipId", (request, response) => {
|
|
1145
1231
|
const { changeNote, expectedVersionNo, ...input } = parse(relationshipSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1146
|
-
|
|
1232
|
+
const relationship = store.updateRelationship(request.params.relationshipId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1233
|
+
publishCollaborativeChange(String(relationship.workId), modulePageKey("relationships"));
|
|
1234
|
+
data(response, relationship);
|
|
1147
1235
|
});
|
|
1148
1236
|
app.delete("/api/relationships/:relationshipId", (request, response) => {
|
|
1149
1237
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1238
|
+
const relationship = store.getRelationship(request.params.relationshipId);
|
|
1150
1239
|
store.deleteRelationship(request.params.relationshipId, input.expectedVersionNo);
|
|
1240
|
+
publishCollaborativeChange(String(relationship.workId), modulePageKey("relationships"));
|
|
1151
1241
|
noContent(response);
|
|
1152
1242
|
});
|
|
1153
1243
|
app.get("/api/entity-versions/:entityType/:entityId", (request, response) => {
|
|
@@ -1513,18 +1603,28 @@ export function createRuntime(options) {
|
|
|
1513
1603
|
response.type("text/html").send(html);
|
|
1514
1604
|
};
|
|
1515
1605
|
app.get(["/", "/index.html"], sendIndexHtml);
|
|
1606
|
+
const setStaticCacheControl = (response) => {
|
|
1607
|
+
const version = response.req.query.v;
|
|
1608
|
+
response.setHeader("Cache-Control", typeof version === "string" && version.length > 0
|
|
1609
|
+
? "public, max-age=31536000, immutable"
|
|
1610
|
+
: "public, max-age=3600, must-revalidate");
|
|
1611
|
+
};
|
|
1516
1612
|
const vditorPath = join(process.cwd(), "node_modules", "vditor", "dist");
|
|
1517
1613
|
if (existsSync(vditorPath)) {
|
|
1518
1614
|
app.use("/vendor/vditor/dist", express.static(vditorPath, {
|
|
1615
|
+
cacheControl: false,
|
|
1519
1616
|
index: false,
|
|
1520
|
-
|
|
1521
|
-
|
|
1617
|
+
etag: true,
|
|
1618
|
+
lastModified: true,
|
|
1619
|
+
setHeaders: setStaticCacheControl
|
|
1522
1620
|
}));
|
|
1523
1621
|
}
|
|
1524
1622
|
app.use(express.static(publicPath, {
|
|
1623
|
+
cacheControl: false,
|
|
1525
1624
|
index: false,
|
|
1526
|
-
|
|
1527
|
-
|
|
1625
|
+
etag: true,
|
|
1626
|
+
lastModified: true,
|
|
1627
|
+
setHeaders: setStaticCacheControl
|
|
1528
1628
|
}));
|
|
1529
1629
|
app.get("/{*path}", (request, response, next) => {
|
|
1530
1630
|
if (request.path.startsWith("/api/"))
|