@graffiti-garden/implementation-decentralized 0.0.2 → 0.0.4
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/1-services/4-inboxes-tests.d.ts.map +1 -1
- package/dist/1-services/4-inboxes.d.ts +3 -3
- package/dist/1-services/4-inboxes.d.ts.map +1 -1
- package/dist/3-protocol/3-object-encoding.d.ts.map +1 -1
- package/dist/3-protocol/4-graffiti.d.ts +2 -1
- package/dist/3-protocol/4-graffiti.d.ts.map +1 -1
- package/dist/3-protocol/login-dialog.html.d.ts +1 -1
- package/dist/3-protocol/login-dialog.html.d.ts.map +1 -1
- package/dist/browser/index.js +7 -7
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/login-dialog.html-VTDKJZBG.js +44 -0
- package/dist/browser/login-dialog.html-VTDKJZBG.js.map +7 -0
- package/dist/browser/{style-YUTCEBZV-RWYJV575.js → style-RMTPI5KV-Y5KAOOZR.js} +19 -36
- package/dist/browser/style-RMTPI5KV-Y5KAOOZR.js.map +7 -0
- package/dist/cjs/1-services/4-inboxes-tests.js +2 -0
- package/dist/cjs/1-services/4-inboxes-tests.js.map +2 -2
- package/dist/cjs/1-services/4-inboxes.js +17 -8
- package/dist/cjs/1-services/4-inboxes.js.map +2 -2
- package/dist/cjs/3-protocol/1-sessions.js +1 -1
- package/dist/cjs/3-protocol/1-sessions.js.map +2 -2
- package/dist/cjs/3-protocol/3-object-encoding.js +3 -2
- package/dist/cjs/3-protocol/3-object-encoding.js.map +2 -2
- package/dist/cjs/3-protocol/4-graffiti.js +193 -135
- package/dist/cjs/3-protocol/4-graffiti.js.map +3 -3
- package/dist/cjs/3-protocol/login-dialog.html.js +9 -9
- package/dist/cjs/3-protocol/login-dialog.html.js.map +1 -1
- package/dist/esm/1-services/4-inboxes-tests.js +2 -0
- package/dist/esm/1-services/4-inboxes-tests.js.map +2 -2
- package/dist/esm/1-services/4-inboxes.js +19 -9
- package/dist/esm/1-services/4-inboxes.js.map +2 -2
- package/dist/esm/3-protocol/1-sessions.js +1 -1
- package/dist/esm/3-protocol/1-sessions.js.map +2 -2
- package/dist/esm/3-protocol/3-object-encoding.js +3 -2
- package/dist/esm/3-protocol/3-object-encoding.js.map +2 -2
- package/dist/esm/3-protocol/4-graffiti.js +194 -135
- package/dist/esm/3-protocol/4-graffiti.js.map +3 -3
- package/dist/esm/3-protocol/login-dialog.html.js +9 -9
- package/dist/esm/3-protocol/login-dialog.html.js.map +1 -1
- package/package.json +7 -7
- package/src/1-services/4-inboxes-tests.ts +2 -0
- package/src/1-services/4-inboxes.ts +25 -15
- package/src/3-protocol/1-sessions.ts +1 -1
- package/src/3-protocol/3-object-encoding.ts +4 -2
- package/src/3-protocol/4-graffiti.ts +260 -170
- package/src/3-protocol/login-dialog.html.ts +9 -9
- package/dist/browser/login-dialog.html-XUWYDNNI.js +0 -44
- package/dist/browser/login-dialog.html-XUWYDNNI.js.map +0 -7
- package/dist/browser/style-YUTCEBZV-RWYJV575.js.map +0 -7
|
@@ -29,10 +29,12 @@ import { Authorization } from "../1-services/1-authorization";
|
|
|
29
29
|
import { StorageBuckets } from "../1-services/3-storage-buckets";
|
|
30
30
|
import {
|
|
31
31
|
Inboxes,
|
|
32
|
+
LABELED_MESSAGE_LABEL_KEY,
|
|
32
33
|
LABELED_MESSAGE_MESSAGE_KEY,
|
|
33
34
|
MESSAGE_METADATA_KEY,
|
|
34
35
|
MESSAGE_OBJECT_KEY,
|
|
35
36
|
MESSAGE_TAGS_KEY,
|
|
37
|
+
type LabeledMessage,
|
|
36
38
|
type MessageStream,
|
|
37
39
|
} from "../1-services/4-inboxes";
|
|
38
40
|
|
|
@@ -130,6 +132,8 @@ export interface GraffitiDecentralizedOptions {
|
|
|
130
132
|
defaultInboxEndpoints?: string[];
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
const CONCURRENCY = 16;
|
|
136
|
+
|
|
133
137
|
export class GraffitiDecentralized implements Graffiti {
|
|
134
138
|
protected readonly dids = new DecentralizedIdentifiers();
|
|
135
139
|
protected readonly authorization = new Authorization();
|
|
@@ -239,11 +243,7 @@ export class GraffitiDecentralized implements Graffiti {
|
|
|
239
243
|
) as HTMLInputElement | null;
|
|
240
244
|
input?.setAttribute("value", proposedHandle);
|
|
241
245
|
input?.addEventListener("focus", () => input?.select());
|
|
242
|
-
|
|
243
|
-
setTimeout(() => r(), 0);
|
|
244
|
-
}).then(() => {
|
|
245
|
-
input?.focus();
|
|
246
|
-
});
|
|
246
|
+
setTimeout(() => input?.focus(), 0);
|
|
247
247
|
|
|
248
248
|
template
|
|
249
249
|
?.querySelector("#graffiti-login-handle-form")
|
|
@@ -293,13 +293,16 @@ export class GraffitiDecentralized implements Graffiti {
|
|
|
293
293
|
e.preventDefault();
|
|
294
294
|
this.login_("");
|
|
295
295
|
});
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
296
|
+
|
|
297
|
+
setTimeout(
|
|
298
|
+
() =>
|
|
299
|
+
(
|
|
300
|
+
template?.querySelector(
|
|
301
|
+
"#graffiti-login-new",
|
|
302
|
+
) as HTMLAnchorElement
|
|
303
|
+
)?.focus(),
|
|
304
|
+
0,
|
|
305
|
+
);
|
|
303
306
|
}
|
|
304
307
|
|
|
305
308
|
const createUrl = new URL(this.identityCreatorEndpoint);
|
|
@@ -785,8 +788,6 @@ export class GraffitiDecentralized implements Graffiti {
|
|
|
785
788
|
channels,
|
|
786
789
|
cursors,
|
|
787
790
|
} satisfies infer_<typeof CursorSchema>),
|
|
788
|
-
continue: (session) =>
|
|
789
|
-
this.discoverMeta<Schema>(channels, schema, cursors, session),
|
|
790
791
|
};
|
|
791
792
|
}
|
|
792
793
|
|
|
@@ -795,6 +796,7 @@ export class GraffitiDecentralized implements Graffiti {
|
|
|
795
796
|
return this.discoverMeta<(typeof args)[1]>(channels, schema, {}, session);
|
|
796
797
|
};
|
|
797
798
|
|
|
799
|
+
// @ts-ignore
|
|
798
800
|
continueDiscover: Graffiti["continueDiscover"] = (...args) => {
|
|
799
801
|
const [cursor, session] = args;
|
|
800
802
|
// Extract the channels from the cursor
|
|
@@ -1009,189 +1011,277 @@ export class GraffitiDecentralized implements Graffiti {
|
|
|
1009
1011
|
inboxToken,
|
|
1010
1012
|
) as unknown as MessageStream<Schema>);
|
|
1011
1013
|
|
|
1014
|
+
const inFlight: Promise<SingleEndpointQueryResult<Schema> | void>[] = [];
|
|
1015
|
+
let doneValue: string | null = null;
|
|
1016
|
+
|
|
1012
1017
|
while (true) {
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1018
|
+
while (doneValue === null && inFlight.length < CONCURRENCY) {
|
|
1019
|
+
const itResult = await iterator.next();
|
|
1020
|
+
if (itResult.done) {
|
|
1021
|
+
doneValue = itResult.value;
|
|
1022
|
+
break;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
const processPromise = this.processOneLabeledMessage<Schema>(
|
|
1026
|
+
inboxEndpoint,
|
|
1027
|
+
itResult.value,
|
|
1028
|
+
inboxToken,
|
|
1029
|
+
recipient,
|
|
1030
|
+
).catch((e) => {
|
|
1031
|
+
throw e;
|
|
1032
|
+
});
|
|
1016
1033
|
|
|
1017
|
-
|
|
1034
|
+
inFlight.push(processPromise);
|
|
1035
|
+
}
|
|
1018
1036
|
|
|
1019
|
-
const
|
|
1020
|
-
if (label !== MESSAGE_LABEL_VALID && label !== MESSAGE_LABEL_UNLABELED)
|
|
1021
|
-
continue;
|
|
1037
|
+
const nextProcessedPromise = inFlight.shift();
|
|
1022
1038
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1039
|
+
if (!nextProcessedPromise) {
|
|
1040
|
+
if (doneValue !== null) return doneValue;
|
|
1025
1041
|
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1042
|
+
throw new Error("Process queue empty but no return value");
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
const processed = await nextProcessedPromise;
|
|
1046
|
+
if (processed) yield processed;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
protected async processOneLabeledMessage<Schema extends JSONSchema>(
|
|
1051
|
+
inboxEndpoint: string,
|
|
1052
|
+
result: LabeledMessage<Schema>,
|
|
1053
|
+
inboxToken?: string | null,
|
|
1054
|
+
recipient?: string | null,
|
|
1055
|
+
): Promise<SingleEndpointQueryResult<Schema> | void> {
|
|
1056
|
+
const label = result.l;
|
|
1057
|
+
// Anything invalid or unexpected, we can skip
|
|
1058
|
+
if (
|
|
1059
|
+
label !== MESSAGE_LABEL_VALID &&
|
|
1060
|
+
label !== MESSAGE_LABEL_UNLABELED &&
|
|
1061
|
+
label !== MESSAGE_LABEL_TRASH
|
|
1062
|
+
)
|
|
1063
|
+
return;
|
|
1064
|
+
|
|
1065
|
+
const messageId = result.id;
|
|
1066
|
+
const { o: object, m: metadataBytes, t: receivedTags } = result.m;
|
|
1067
|
+
|
|
1068
|
+
let metadata: MessageMetadata;
|
|
1069
|
+
try {
|
|
1070
|
+
const metadataRaw = dagCborDecode(metadataBytes);
|
|
1071
|
+
metadata = MessageMetadataSchema.parse(metadataRaw);
|
|
1072
|
+
} catch (e) {
|
|
1073
|
+
this.inboxes.label(
|
|
1074
|
+
inboxEndpoint,
|
|
1075
|
+
messageId,
|
|
1076
|
+
MESSAGE_LABEL_INVALID,
|
|
1077
|
+
inboxToken,
|
|
1078
|
+
);
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
const {
|
|
1083
|
+
[MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,
|
|
1084
|
+
[MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,
|
|
1085
|
+
} = metadata;
|
|
1086
|
+
|
|
1087
|
+
const allowedTickets =
|
|
1088
|
+
MESSAGE_DATA_ALLOWED_TICKETS_KEY in metadata
|
|
1089
|
+
? metadata[MESSAGE_DATA_ALLOWED_TICKETS_KEY]
|
|
1090
|
+
: undefined;
|
|
1091
|
+
const announcements =
|
|
1092
|
+
MESSAGE_DATA_ANNOUNCEMENTS_KEY in metadata
|
|
1093
|
+
? metadata[MESSAGE_DATA_ANNOUNCEMENTS_KEY]
|
|
1094
|
+
: undefined;
|
|
1095
|
+
|
|
1096
|
+
if (label === MESSAGE_LABEL_VALID) {
|
|
1097
|
+
return {
|
|
1098
|
+
messageId,
|
|
1099
|
+
object,
|
|
1100
|
+
storageBucketKey,
|
|
1101
|
+
allowedTickets,
|
|
1102
|
+
tags: receivedTags,
|
|
1103
|
+
announcements,
|
|
1104
|
+
};
|
|
1105
|
+
} else if (label === MESSAGE_LABEL_TRASH) {
|
|
1106
|
+
// If it is simply trash, just continue.
|
|
1107
|
+
if (!tombstonedMessageId) return;
|
|
1108
|
+
|
|
1109
|
+
// Make sure the tombstone points to a real message
|
|
1110
|
+
const past = await this.inboxes.get(
|
|
1111
|
+
inboxEndpoint,
|
|
1112
|
+
tombstonedMessageId,
|
|
1113
|
+
inboxToken,
|
|
1114
|
+
);
|
|
1115
|
+
if (
|
|
1116
|
+
!past ||
|
|
1117
|
+
past[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url !== object.url
|
|
1118
|
+
)
|
|
1119
|
+
return;
|
|
1120
|
+
|
|
1121
|
+
// If the referred to message isn't labeled as trash, trash it
|
|
1122
|
+
// This may happen if a trash message is processed on another
|
|
1123
|
+
// device and the device cache is out of date.
|
|
1124
|
+
if (past[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH) {
|
|
1125
|
+
// Label the message as trash
|
|
1031
1126
|
this.inboxes.label(
|
|
1032
1127
|
inboxEndpoint,
|
|
1033
|
-
|
|
1034
|
-
|
|
1128
|
+
tombstonedMessageId,
|
|
1129
|
+
MESSAGE_LABEL_TRASH,
|
|
1035
1130
|
inboxToken,
|
|
1036
1131
|
);
|
|
1037
|
-
continue;
|
|
1038
1132
|
}
|
|
1039
1133
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
? metadata[MESSAGE_DATA_ANNOUNCEMENTS_KEY]
|
|
1052
|
-
: undefined;
|
|
1053
|
-
|
|
1054
|
-
if (label === MESSAGE_LABEL_VALID) {
|
|
1055
|
-
yield {
|
|
1056
|
-
messageId,
|
|
1057
|
-
object,
|
|
1058
|
-
storageBucketKey,
|
|
1059
|
-
allowedTickets,
|
|
1060
|
-
tags: receivedTags,
|
|
1061
|
-
announcements,
|
|
1062
|
-
};
|
|
1063
|
-
continue;
|
|
1064
|
-
}
|
|
1134
|
+
// Return the tombstone
|
|
1135
|
+
return {
|
|
1136
|
+
messageId,
|
|
1137
|
+
tombstone: true,
|
|
1138
|
+
object,
|
|
1139
|
+
storageBucketKey,
|
|
1140
|
+
allowedTickets,
|
|
1141
|
+
tags: receivedTags,
|
|
1142
|
+
announcements,
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1065
1145
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1146
|
+
// Otherwise, unlabeled: try to validate the object
|
|
1147
|
+
let validationError: unknown | undefined = undefined;
|
|
1148
|
+
try {
|
|
1149
|
+
const actor = object.actor;
|
|
1150
|
+
const actorDocument = await this.dids.resolve(actor);
|
|
1151
|
+
const storageBucketService = actorDocument?.service?.find(
|
|
1152
|
+
(service) =>
|
|
1153
|
+
service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET &&
|
|
1154
|
+
service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,
|
|
1155
|
+
);
|
|
1156
|
+
if (!storageBucketService) {
|
|
1157
|
+
throw new GraffitiErrorNotFound(
|
|
1158
|
+
`Actor ${actor} has no storage bucket service`,
|
|
1075
1159
|
);
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
}
|
|
1081
|
-
if (typeof storageBucketService.serviceEndpoint !== "string") {
|
|
1082
|
-
throw new GraffitiErrorNotFound(
|
|
1083
|
-
`Actor ${actor} does not have a valid storage bucket endpoint`,
|
|
1084
|
-
);
|
|
1085
|
-
}
|
|
1086
|
-
const storageBucketEndpoint = storageBucketService.serviceEndpoint;
|
|
1087
|
-
|
|
1088
|
-
const objectBytes = await this.storageBuckets.get(
|
|
1089
|
-
storageBucketEndpoint,
|
|
1090
|
-
storageBucketKey,
|
|
1091
|
-
MAX_OBJECT_SIZE_BYTES,
|
|
1160
|
+
}
|
|
1161
|
+
if (typeof storageBucketService.serviceEndpoint !== "string") {
|
|
1162
|
+
throw new GraffitiErrorNotFound(
|
|
1163
|
+
`Actor ${actor} does not have a valid storage bucket endpoint`,
|
|
1092
1164
|
);
|
|
1165
|
+
}
|
|
1166
|
+
const storageBucketEndpoint = storageBucketService.serviceEndpoint;
|
|
1093
1167
|
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
const privateObjectInfo = allowedTickets
|
|
1100
|
-
? { allowedTickets }
|
|
1101
|
-
: MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata
|
|
1102
|
-
? {
|
|
1103
|
-
recipient: recipient ?? "null",
|
|
1104
|
-
allowedTicket: metadata[MESSAGE_DATA_ALLOWED_TICKET_KEY],
|
|
1105
|
-
allowedIndex: metadata[MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY],
|
|
1106
|
-
}
|
|
1107
|
-
: undefined;
|
|
1168
|
+
const objectBytes = await this.storageBuckets.get(
|
|
1169
|
+
storageBucketEndpoint,
|
|
1170
|
+
storageBucketKey,
|
|
1171
|
+
MAX_OBJECT_SIZE_BYTES,
|
|
1172
|
+
);
|
|
1108
1173
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
objectBytes,
|
|
1113
|
-
privateObjectInfo,
|
|
1174
|
+
if (MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata && !recipient) {
|
|
1175
|
+
throw new GraffitiErrorForbidden(
|
|
1176
|
+
`Recipient is required when allowed ticket is present`,
|
|
1114
1177
|
);
|
|
1115
|
-
} catch (e) {
|
|
1116
|
-
validationError = e;
|
|
1117
1178
|
}
|
|
1179
|
+
const privateObjectInfo = allowedTickets
|
|
1180
|
+
? { allowedTickets }
|
|
1181
|
+
: MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata
|
|
1182
|
+
? {
|
|
1183
|
+
recipient: recipient ?? "null",
|
|
1184
|
+
allowedTicket: metadata[MESSAGE_DATA_ALLOWED_TICKET_KEY],
|
|
1185
|
+
allowedIndex: metadata[MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY],
|
|
1186
|
+
}
|
|
1187
|
+
: undefined;
|
|
1118
1188
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
result &&
|
|
1129
|
-
result[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url ===
|
|
1130
|
-
object.url
|
|
1131
|
-
) {
|
|
1132
|
-
// If it does, label the message as trash, it is no longer needed
|
|
1133
|
-
this.inboxes.label(
|
|
1134
|
-
inboxEndpoint,
|
|
1135
|
-
tombstonedMessageId,
|
|
1136
|
-
MESSAGE_LABEL_TRASH,
|
|
1137
|
-
inboxToken,
|
|
1138
|
-
);
|
|
1139
|
-
}
|
|
1189
|
+
await this.objectEncoding.validate(
|
|
1190
|
+
object,
|
|
1191
|
+
receivedTags,
|
|
1192
|
+
objectBytes,
|
|
1193
|
+
privateObjectInfo,
|
|
1194
|
+
);
|
|
1195
|
+
} catch (e) {
|
|
1196
|
+
validationError = e;
|
|
1197
|
+
}
|
|
1140
1198
|
|
|
1141
|
-
|
|
1199
|
+
if (tombstonedMessageId) {
|
|
1200
|
+
if (validationError instanceof GraffitiErrorNotFound) {
|
|
1201
|
+
// Not found == The tombstone is correct
|
|
1202
|
+
this.inboxes
|
|
1203
|
+
// Get the referenced message
|
|
1204
|
+
.get(inboxEndpoint, tombstonedMessageId, inboxToken)
|
|
1205
|
+
.then((result) => {
|
|
1206
|
+
if (
|
|
1207
|
+
// Make sure that it actually references the object being deleted
|
|
1208
|
+
result &&
|
|
1209
|
+
result[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url ===
|
|
1210
|
+
object.url &&
|
|
1211
|
+
// And that the object is not already marked as trash
|
|
1212
|
+
result[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH
|
|
1213
|
+
) {
|
|
1214
|
+
// If valid but not yet trash, label the message as trash
|
|
1142
1215
|
this.inboxes.label(
|
|
1143
1216
|
inboxEndpoint,
|
|
1144
|
-
|
|
1217
|
+
tombstonedMessageId,
|
|
1145
1218
|
MESSAGE_LABEL_TRASH,
|
|
1146
1219
|
inboxToken,
|
|
1147
1220
|
);
|
|
1148
|
-
}
|
|
1221
|
+
}
|
|
1149
1222
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
}
|
|
1223
|
+
// Then, label the tombstone message as trash
|
|
1224
|
+
this.inboxes.label(
|
|
1225
|
+
inboxEndpoint,
|
|
1226
|
+
messageId,
|
|
1227
|
+
MESSAGE_LABEL_TRASH,
|
|
1228
|
+
inboxToken,
|
|
1229
|
+
);
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
return {
|
|
1233
|
+
messageId,
|
|
1234
|
+
tombstone: true,
|
|
1235
|
+
object,
|
|
1236
|
+
storageBucketKey,
|
|
1237
|
+
allowedTickets,
|
|
1238
|
+
tags: receivedTags,
|
|
1239
|
+
announcements,
|
|
1240
|
+
};
|
|
1169
1241
|
} else {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
}
|
|
1242
|
+
console.error("Recieved an incorrect tombstone object");
|
|
1243
|
+
console.error(validationError);
|
|
1244
|
+
this.inboxes.label(
|
|
1245
|
+
inboxEndpoint,
|
|
1246
|
+
messageId,
|
|
1247
|
+
MESSAGE_LABEL_INVALID,
|
|
1248
|
+
inboxToken,
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
} else {
|
|
1252
|
+
if (validationError === undefined) {
|
|
1253
|
+
this.inboxes.label(
|
|
1254
|
+
inboxEndpoint,
|
|
1255
|
+
messageId,
|
|
1256
|
+
MESSAGE_LABEL_VALID,
|
|
1257
|
+
inboxToken,
|
|
1258
|
+
);
|
|
1259
|
+
return {
|
|
1260
|
+
messageId,
|
|
1261
|
+
object,
|
|
1262
|
+
storageBucketKey,
|
|
1263
|
+
tags: receivedTags,
|
|
1264
|
+
allowedTickets,
|
|
1265
|
+
announcements,
|
|
1266
|
+
};
|
|
1267
|
+
} else if (validationError instanceof GraffitiErrorNotFound) {
|
|
1268
|
+
// Item was deleted before we got a chance to
|
|
1269
|
+
// validate it. Just label the message as trash.
|
|
1270
|
+
this.inboxes.label(
|
|
1271
|
+
inboxEndpoint,
|
|
1272
|
+
messageId,
|
|
1273
|
+
MESSAGE_LABEL_TRASH,
|
|
1274
|
+
inboxToken,
|
|
1275
|
+
);
|
|
1276
|
+
} else {
|
|
1277
|
+
console.error("Recieved an incorrect object");
|
|
1278
|
+
console.error(validationError);
|
|
1279
|
+
this.inboxes.label(
|
|
1280
|
+
inboxEndpoint,
|
|
1281
|
+
messageId,
|
|
1282
|
+
MESSAGE_LABEL_INVALID,
|
|
1283
|
+
inboxToken,
|
|
1284
|
+
);
|
|
1195
1285
|
}
|
|
1196
1286
|
}
|
|
1197
1287
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export const template = `<template id="graffiti-login-welcome">
|
|
2
2
|
<h1>
|
|
3
|
-
<a target="_blank" href="https://graffiti.garden">Graffiti
|
|
3
|
+
<a target="_blank" href="https://graffiti.garden">Graffiti Log In</a>
|
|
4
4
|
</h1>
|
|
5
5
|
|
|
6
6
|
<ul>
|
|
7
|
-
<li><a type="button" id="graffiti-login-new">Create
|
|
8
|
-
<li><button class="secondary" id="graffiti-login-existing">Use
|
|
7
|
+
<li><a type="button" id="graffiti-login-new">Create new Graffiti identity</a></li>
|
|
8
|
+
<li><button class="secondary" id="graffiti-login-existing">Use existing Graffiti identity</button></li>
|
|
9
9
|
</ul>
|
|
10
10
|
|
|
11
11
|
<aside>
|
|
@@ -15,12 +15,12 @@ export const template = `<template id="graffiti-login-welcome">
|
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<template id="graffiti-login-handle">
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
<h1>
|
|
19
|
+
<a target="_blank" href="https://graffiti.garden">Graffiti Log In</a>
|
|
20
|
+
</h1>
|
|
21
21
|
|
|
22
22
|
<form id="graffiti-login-handle-form">
|
|
23
|
-
<label for="username">
|
|
23
|
+
<label for="username">Graffiti handle:</label>
|
|
24
24
|
<input
|
|
25
25
|
type="text"
|
|
26
26
|
name="username"
|
|
@@ -29,7 +29,7 @@ export const template = `<template id="graffiti-login-welcome">
|
|
|
29
29
|
autocapitalize="none"
|
|
30
30
|
spellcheck="false"
|
|
31
31
|
inputmode="url"
|
|
32
|
-
placeholder="
|
|
32
|
+
placeholder="you.graffiti.actor"
|
|
33
33
|
required
|
|
34
34
|
>
|
|
35
35
|
<button id="graffiti-login-handle-submit" type="submit">
|
|
@@ -38,6 +38,6 @@ export const template = `<template id="graffiti-login-welcome">
|
|
|
38
38
|
</form>
|
|
39
39
|
|
|
40
40
|
<p>
|
|
41
|
-
Don't
|
|
41
|
+
Don't have a Graffiti handle? <a id="graffiti-login-new">Create one</a>.
|
|
42
42
|
</p>
|
|
43
43
|
</template>`;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import"./chunk-RFBBAUMM.js";var t=`<template id="graffiti-login-welcome">
|
|
2
|
-
<h1>
|
|
3
|
-
<a target="_blank" href="https://graffiti.garden">Graffiti<wbr> Log In</a>
|
|
4
|
-
</h1>
|
|
5
|
-
|
|
6
|
-
<ul>
|
|
7
|
-
<li><a type="button" id="graffiti-login-new">Create new Graffiti identity</a></li>
|
|
8
|
-
<li><button class="secondary" id="graffiti-login-existing">Use existing Graffiti identity</button></li>
|
|
9
|
-
</ul>
|
|
10
|
-
|
|
11
|
-
<aside>
|
|
12
|
-
This application is built with
|
|
13
|
-
<a target="_blank" href="https://graffiti.garden">Graffiti</a>.
|
|
14
|
-
</aside>
|
|
15
|
-
</template>
|
|
16
|
-
|
|
17
|
-
<template id="graffiti-login-handle">
|
|
18
|
-
<h1>
|
|
19
|
-
<a target="_blank" href="https://graffiti.garden">Graffiti<wbr> Log In</a>
|
|
20
|
-
</h1>
|
|
21
|
-
|
|
22
|
-
<form id="graffiti-login-handle-form">
|
|
23
|
-
<label for="username">Enter your Graffiti handle:</label>
|
|
24
|
-
<input
|
|
25
|
-
type="text"
|
|
26
|
-
name="username"
|
|
27
|
-
id="username"
|
|
28
|
-
autocomplete="username"
|
|
29
|
-
autocapitalize="none"
|
|
30
|
-
spellcheck="false"
|
|
31
|
-
inputmode="url"
|
|
32
|
-
placeholder="example.graffiti.actor"
|
|
33
|
-
required
|
|
34
|
-
>
|
|
35
|
-
<button id="graffiti-login-handle-submit" type="submit">
|
|
36
|
-
Log In
|
|
37
|
-
</button>
|
|
38
|
-
</form>
|
|
39
|
-
|
|
40
|
-
<p>
|
|
41
|
-
Don't have a Graffiti handle? <a id="graffiti-login-new">Create one</a>.
|
|
42
|
-
</p>
|
|
43
|
-
</template>`;export{t as template};
|
|
44
|
-
//# sourceMappingURL=login-dialog.html-XUWYDNNI.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/3-protocol/login-dialog.html.ts"],
|
|
4
|
-
"sourcesContent": ["export const template = `<template id=\"graffiti-login-welcome\">\n <h1>\n <a target=\"_blank\" href=\"https://graffiti.garden\">Graffiti<wbr> Log In</a>\n </h1>\n\n <ul>\n <li><a type=\"button\" id=\"graffiti-login-new\">Create new Graffiti identity</a></li>\n <li><button class=\"secondary\" id=\"graffiti-login-existing\">Use existing Graffiti identity</button></li>\n </ul>\n\n <aside>\n This application is built with\n <a target=\"_blank\" href=\"https://graffiti.garden\">Graffiti</a>.\n </aside>\n</template>\n\n<template id=\"graffiti-login-handle\">\n <h1>\n <a target=\"_blank\" href=\"https://graffiti.garden\">Graffiti<wbr> Log In</a>\n </h1>\n\n <form id=\"graffiti-login-handle-form\">\n <label for=\"username\">Enter your Graffiti handle:</label>\n <input\n type=\"text\"\n name=\"username\"\n id=\"username\"\n autocomplete=\"username\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n inputmode=\"url\"\n placeholder=\"example.graffiti.actor\"\n required\n >\n <button id=\"graffiti-login-handle-submit\" type=\"submit\">\n Log In\n </button>\n </form>\n\n <p>\n Don't have a Graffiti handle? <a id=\"graffiti-login-new\">Create one</a>.\n </p>\n</template>`;\n"],
|
|
5
|
-
"mappings": "4BAAO,IAAMA,EAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
|
|
6
|
-
"names": ["template"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../node_modules/@graffiti-garden/modal/src/style.css"],
|
|
4
|
-
"sourcesContent": [".graffiti-modal {\n --back: rgb(26, 26, 26, 0.85);\n --halfback: rgba(80, 80, 80, 0.85);\n --halfback2: rgba(26, 26, 26, 0.85);\n --hover: rgba(202, 122, 204, 0.3);\n --frontfaded: rgba(190, 190, 190);\n --front: rgba(240, 240, 240);\n --emph: rgb(202, 122, 204);\n --blurpix: 3px;\n border-color: var(--emph);\n box-sizing: border-box;\n border-width: 2px;\n padding: 0;\n margin: 0;\n border-radius: 1rem;\n box-shadow: 0 0 2rem black;\n overflow: hidden;\n opacity: 0;\n transition: opacity 0.3s;\n pointer-events: none;\n display: block;\n min-width: 95dvw;\n min-height: 95dvh;\n height: 95dvh;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n font-family:\n Inter,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n Oxygen,\n Ubuntu,\n Cantarell,\n \"Fira Sans\",\n \"Droid Sans\",\n \"Helvetica Neue\",\n sans-serif;\n color: var(--front);\n font-size: 150%;\n\n * {\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n }\n\n ::selection {\n background: rgba(202, 122, 204, 0.3);\n }\n\n :focus {\n outline: 2px solid var(--front);\n }\n\n header {\n width: 100%;\n display: flex;\n justify-content: flex-end;\n }\n\n main {\n flex: 1;\n max-width: 600px;\n width: 100%;\n gap: 2em;\n padding-top: 4dvh;\n padding-bottom: 4dvh;\n margin-top: 4dvh;\n margin-bottom: 4dvh;\n margin-left: 4dvw;\n margin-right: 4dvw;\n padding-left: 4dvw;\n padding-right: 4dvw;\n background: var(--back);\n border-radius: 1rem;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n scrollbar-color: var(--emph) rgba(0, 0, 0, 0);\n }\n\n ul {\n list-style-type: none;\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n align-items: stretch;\n justify-content: stretch;\n }\n\n aside {\n color: var(--frontfaded);\n }\n\n .secondary,\n a:not([type=\"button\"]) {\n color: var(--emph);\n }\n\n h1 {\n font-size: 120%;\n font-family:\n Rock Salt,\n cursive,\n sans-serif;\n letter-spacing: 0.1em;\n text-align: center;\n color: var(--front);\n }\n\n h1 a:not([type=\"button\"]) {\n color: inherit;\n }\n\n h1 a:hover {\n background: none;\n color: inherit;\n }\n\n button,\n input[type=\"submit\"],\n input[type=\"text\"],\n a[type=\"button\"] {\n font-size: inherit;\n width: 100%;\n text-align: center;\n display: block;\n border-radius: 1rem;\n border: 2px solid var(--emph);\n padding: 1em;\n padding-top: 0.5em;\n padding-bottom: 0.5em;\n transition: 0.1s;\n text-overflow: ellipsis;\n background: none;\n line-height: 1.2em;\n }\n\n input[type=\"text\"] {\n font-weight: 500;\n background: var(--front);\n text-align: left;\n color: black;\n }\n\n header button {\n border-radius: 0 0 0 1rem;\n border-right: none;\n border-top: none;\n background-color: var(--halfback2);\n width: fit-content;\n position: relative;\n overflow: hidden;\n }\n\n header button::before {\n z-index: -1;\n top: 0;\n left: 0;\n height: 100%;\n position: absolute;\n width: 100%;\n content: \"\";\n background-color: var(--back);\n }\n\n @media (max-width: 600px) {\n main {\n border-radius: 0;\n margin: auto;\n overflow: auto;\n }\n\n header button {\n border-radius: 0;\n border-left: none;\n width: 100%;\n }\n\n html {\n justify-content: safe center;\n }\n }\n\n a {\n text-decoration: none;\n }\n\n :is(button, ul a, input[type=\"submit\"]):hover {\n cursor: pointer;\n background: var(--hover);\n color: var(--front);\n }\n\n a:hover {\n text-decoration: underline;\n cursor: pointer;\n }\n\n form {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n gap: 0.5em;\n }\n\n iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]).secondary {\n color: rgb(244, 213, 244);\n background: rgba(26, 26, 26, 0.6);\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]):not(.secondary) {\n background: var(--hover);\n color: white;\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]):hover {\n background: rgba(202, 122, 204, 0.6);\n color: white;\n text-decoration: none;\n }\n\n h3 {\n color: var(--frontfaded);\n }\n\n h2 {\n text-align: center;\n font-weight: 500;\n font-size: 150%;\n background: var(--halfback2);\n padding: 1rem;\n border-radius: 1rem;\n border: 1px solid var(--frontfaded);\n color: var(--front);\n }\n\n main > div {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: 0.5rem;\n }\n}\n\n.graffiti-modal[open] {\n pointer-events: inherit;\n opacity: 1;\n}\n\n.graffiti-modal::backdrop {\n background-color: black;\n opacity: 0.5;\n}\n\n.graffiti-modal::before {\n content: \"\";\n position: fixed;\n left: 0;\n right: 0;\n z-index: -1;\n background-image: url(graffiti.jpg);\n background-size: cover;\n background-repeat: no-repeat;\n background-position: 50% 50%;\n height: calc(100% + 2 * var(--blurpix));\n width: calc(100% + 2 * var(--blurpix));\n filter: blur(var(--blurpix));\n margin: calc(-1 * var(--blurpix));\n}\n"],
|
|
5
|
-
"mappings": "4BAAA,IAAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;",
|
|
6
|
-
"names": ["style_default"]
|
|
7
|
-
}
|