@mieweb/pulsevault 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -1
- package/OPERATIONS.md +24 -10
- package/PROTOCOL.md +38 -1
- package/README.md +168 -29
- package/assets/README.md +33 -0
- package/assets/badge-app-store.svg +46 -0
- package/assets/badge-google-play.png +0 -0
- package/assets/pulse-logo-mono.svg +10 -0
- package/assets/pulse-logo.svg +14 -0
- package/dist/app.d.ts +24 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +20 -2
- package/dist/app.js.map +1 -1
- package/dist/augment.d.ts +3 -0
- package/dist/augment.d.ts.map +1 -1
- package/dist/augment.js.map +1 -1
- package/dist/core.d.ts +89 -4
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +301 -40
- package/dist/core.js.map +1 -1
- package/dist/lib/authorize.d.ts +28 -6
- package/dist/lib/authorize.d.ts.map +1 -1
- package/dist/lib/capability-token.d.ts +26 -0
- package/dist/lib/capability-token.d.ts.map +1 -1
- package/dist/lib/capability-token.js +73 -5
- package/dist/lib/capability-token.js.map +1 -1
- package/dist/lib/completion.d.ts +135 -0
- package/dist/lib/completion.d.ts.map +1 -0
- package/dist/lib/completion.js +288 -0
- package/dist/lib/completion.js.map +1 -0
- package/dist/lib/options.d.ts.map +1 -1
- package/dist/lib/options.js +2 -0
- package/dist/lib/options.js.map +1 -1
- package/dist/lib/protocol-version.gen.js +1 -1
- package/dist/lib/pulsevaultTus.d.ts +28 -26
- package/dist/lib/pulsevaultTus.d.ts.map +1 -1
- package/dist/lib/pulsevaultTus.js +114 -31
- package/dist/lib/pulsevaultTus.js.map +1 -1
- package/dist/routes/pulsevault.d.ts +12 -1
- package/dist/routes/pulsevault.d.ts.map +1 -1
- package/dist/routes/pulsevault.js +92 -1
- package/dist/routes/pulsevault.js.map +1 -1
- package/dist/storage/local.d.ts +7 -1
- package/dist/storage/local.d.ts.map +1 -1
- package/dist/storage/local.js +173 -8
- package/dist/storage/local.js.map +1 -1
- package/dist/storage/s3.d.ts +7 -1
- package/dist/storage/s3.d.ts.map +1 -1
- package/dist/storage/s3.js +236 -14
- package/dist/storage/s3.js.map +1 -1
- package/dist/storage/types.d.ts +73 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/package.json +6 -4
- package/protocol/openapi.json +247 -1
- package/protocol/schemas/artifact-status.schema.json +49 -0
- package/protocol/schemas/capability-token.schema.json +3 -0
package/protocol/openapi.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Pulse upload protocol",
|
|
5
5
|
"description": "The HTTP surface of the Pulse upload protocol, as implemented by @mieweb/pulsevault. Generated from the plugin's route schemas — see PROTOCOL.md for the full contract.",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.3"
|
|
7
7
|
},
|
|
8
8
|
"components": {
|
|
9
9
|
"schemas": {}
|
|
@@ -1047,6 +1047,252 @@
|
|
|
1047
1047
|
}
|
|
1048
1048
|
}
|
|
1049
1049
|
}
|
|
1050
|
+
},
|
|
1051
|
+
"/pulsevault/artifacts/{artifactId}/status": {
|
|
1052
|
+
"get": {
|
|
1053
|
+
"summary": "Where an upload is: uploading, processing or ready",
|
|
1054
|
+
"tags": [
|
|
1055
|
+
"pulsevault"
|
|
1056
|
+
],
|
|
1057
|
+
"description": "Reports the artifact's state (`unknown`, `uploading`, `processing` while a web-ready conversion rewrites it, `ready`), its kind and `relatedTo`, the bytes received against its declared length, whether the host's `onUploadComplete` has finished (`acknowledged`), and what the host recorded with `recordOutcome` (`outcome`). Runs the `authorize` hook with `phase: \"status\"`; `createCapabilityAuthorize` grants it to the pairing token and to a view token. Never cached.",
|
|
1058
|
+
"parameters": [
|
|
1059
|
+
{
|
|
1060
|
+
"schema": {
|
|
1061
|
+
"type": "string"
|
|
1062
|
+
},
|
|
1063
|
+
"in": "query",
|
|
1064
|
+
"name": "token",
|
|
1065
|
+
"required": false,
|
|
1066
|
+
"description": "Optional bearer token (the pairing token or a view token), forwarded to the `authorize` hook as `ctx.token` for browsers that can’t set a header."
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
"schema": {
|
|
1070
|
+
"type": "string",
|
|
1071
|
+
"format": "uuid"
|
|
1072
|
+
},
|
|
1073
|
+
"in": "path",
|
|
1074
|
+
"name": "artifactId",
|
|
1075
|
+
"required": true,
|
|
1076
|
+
"description": "UUID of the upload to report on."
|
|
1077
|
+
}
|
|
1078
|
+
],
|
|
1079
|
+
"responses": {
|
|
1080
|
+
"200": {
|
|
1081
|
+
"description": "Where an upload is (PROTOCOL.md §6.5, protocol 2.3): for a page waiting on it, so the host needs no table of its own. Authorized like opening the artifact. Never cached.",
|
|
1082
|
+
"content": {
|
|
1083
|
+
"application/json": {
|
|
1084
|
+
"schema": {
|
|
1085
|
+
"title": "GET /artifacts/<id>/status response",
|
|
1086
|
+
"description": "Where an upload is (PROTOCOL.md §6.5, protocol 2.3): for a page waiting on it, so the host needs no table of its own. Authorized like opening the artifact. Never cached.",
|
|
1087
|
+
"type": "object",
|
|
1088
|
+
"required": [
|
|
1089
|
+
"artifactId",
|
|
1090
|
+
"state"
|
|
1091
|
+
],
|
|
1092
|
+
"properties": {
|
|
1093
|
+
"artifactId": {
|
|
1094
|
+
"type": "string",
|
|
1095
|
+
"format": "uuid",
|
|
1096
|
+
"description": "The artifact asked about."
|
|
1097
|
+
},
|
|
1098
|
+
"state": {
|
|
1099
|
+
"type": "string",
|
|
1100
|
+
"enum": [
|
|
1101
|
+
"unknown",
|
|
1102
|
+
"uploading",
|
|
1103
|
+
"processing",
|
|
1104
|
+
"ready"
|
|
1105
|
+
],
|
|
1106
|
+
"description": "`unknown` for an id the server has never seen; `uploading` until the final byte; `processing` while the server converts the bytes for the web; `ready` once the artifact is served."
|
|
1107
|
+
},
|
|
1108
|
+
"kind": {
|
|
1109
|
+
"type": "string",
|
|
1110
|
+
"enum": [
|
|
1111
|
+
"video",
|
|
1112
|
+
"project",
|
|
1113
|
+
"captions",
|
|
1114
|
+
"thumbnail"
|
|
1115
|
+
],
|
|
1116
|
+
"description": "Artifact kind. Absent when `state` is `unknown`."
|
|
1117
|
+
},
|
|
1118
|
+
"relatedTo": {
|
|
1119
|
+
"type": "string",
|
|
1120
|
+
"format": "uuid",
|
|
1121
|
+
"description": "The video this artifact belongs to, if it declared one."
|
|
1122
|
+
},
|
|
1123
|
+
"name": {
|
|
1124
|
+
"type": "string",
|
|
1125
|
+
"description": "The display name the client sent (`Upload-Metadata.name`), if any."
|
|
1126
|
+
},
|
|
1127
|
+
"bytesReceived": {
|
|
1128
|
+
"type": "number",
|
|
1129
|
+
"description": "Bytes received so far while `uploading`, or stored once finished, when the server knows."
|
|
1130
|
+
},
|
|
1131
|
+
"size": {
|
|
1132
|
+
"type": "number",
|
|
1133
|
+
"description": "The upload's declared length, when the server knows."
|
|
1134
|
+
},
|
|
1135
|
+
"acknowledged": {
|
|
1136
|
+
"type": "boolean",
|
|
1137
|
+
"description": "Whether the host has finished handling the completed upload (its `onUploadComplete` returned)."
|
|
1138
|
+
},
|
|
1139
|
+
"outcome": {
|
|
1140
|
+
"description": "What the host recorded about where the upload went, or why it didn't. Any JSON; absent until the host records one."
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
"400": {
|
|
1148
|
+
"description": "`artifactId` is not a valid UUID.",
|
|
1149
|
+
"content": {
|
|
1150
|
+
"application/json": {
|
|
1151
|
+
"schema": {
|
|
1152
|
+
"description": "`artifactId` is not a valid UUID.",
|
|
1153
|
+
"type": "object",
|
|
1154
|
+
"properties": {
|
|
1155
|
+
"ok": {
|
|
1156
|
+
"type": "boolean"
|
|
1157
|
+
},
|
|
1158
|
+
"error": {
|
|
1159
|
+
"type": "string"
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1162
|
+
"required": [
|
|
1163
|
+
"ok",
|
|
1164
|
+
"error"
|
|
1165
|
+
]
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
},
|
|
1170
|
+
"403": {
|
|
1171
|
+
"description": "Authorize hook rejected the request.",
|
|
1172
|
+
"content": {
|
|
1173
|
+
"application/json": {
|
|
1174
|
+
"schema": {
|
|
1175
|
+
"description": "Authorize hook rejected the request.",
|
|
1176
|
+
"type": "object",
|
|
1177
|
+
"properties": {
|
|
1178
|
+
"ok": {
|
|
1179
|
+
"type": "boolean"
|
|
1180
|
+
},
|
|
1181
|
+
"error": {
|
|
1182
|
+
"type": "string"
|
|
1183
|
+
}
|
|
1184
|
+
},
|
|
1185
|
+
"required": [
|
|
1186
|
+
"ok",
|
|
1187
|
+
"error"
|
|
1188
|
+
]
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1196
|
+
"/pulsevault/artifacts/{artifactId}/poster": {
|
|
1197
|
+
"get": {
|
|
1198
|
+
"summary": "Serve a video's poster frame",
|
|
1199
|
+
"tags": [
|
|
1200
|
+
"pulsevault"
|
|
1201
|
+
],
|
|
1202
|
+
"description": "Streams or redirects to the finished thumbnail `relatedTo` the video, exactly as `GET /artifacts/:artifactId` would serve it. Runs the `authorize` hook with `phase: \"resolve\"` on the video, so whoever may watch it may see its poster. 404 until the poster has landed.",
|
|
1203
|
+
"parameters": [
|
|
1204
|
+
{
|
|
1205
|
+
"schema": {
|
|
1206
|
+
"type": "string"
|
|
1207
|
+
},
|
|
1208
|
+
"in": "query",
|
|
1209
|
+
"name": "token",
|
|
1210
|
+
"required": false,
|
|
1211
|
+
"description": "Optional bearer token for pre-authenticated watch links, forwarded to the `authorize` hook as `ctx.token`."
|
|
1212
|
+
},
|
|
1213
|
+
{
|
|
1214
|
+
"schema": {
|
|
1215
|
+
"type": "string",
|
|
1216
|
+
"format": "uuid"
|
|
1217
|
+
},
|
|
1218
|
+
"in": "path",
|
|
1219
|
+
"name": "artifactId",
|
|
1220
|
+
"required": true,
|
|
1221
|
+
"description": "UUID of the video (the pulse's anchor artifact)."
|
|
1222
|
+
}
|
|
1223
|
+
],
|
|
1224
|
+
"responses": {
|
|
1225
|
+
"400": {
|
|
1226
|
+
"description": "`artifactId` is not a valid UUID.",
|
|
1227
|
+
"content": {
|
|
1228
|
+
"application/json": {
|
|
1229
|
+
"schema": {
|
|
1230
|
+
"description": "`artifactId` is not a valid UUID.",
|
|
1231
|
+
"type": "object",
|
|
1232
|
+
"properties": {
|
|
1233
|
+
"ok": {
|
|
1234
|
+
"type": "boolean"
|
|
1235
|
+
},
|
|
1236
|
+
"error": {
|
|
1237
|
+
"type": "string"
|
|
1238
|
+
}
|
|
1239
|
+
},
|
|
1240
|
+
"required": [
|
|
1241
|
+
"ok",
|
|
1242
|
+
"error"
|
|
1243
|
+
]
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
},
|
|
1248
|
+
"403": {
|
|
1249
|
+
"description": "Authorize hook rejected the request.",
|
|
1250
|
+
"content": {
|
|
1251
|
+
"application/json": {
|
|
1252
|
+
"schema": {
|
|
1253
|
+
"description": "Authorize hook rejected the request.",
|
|
1254
|
+
"type": "object",
|
|
1255
|
+
"properties": {
|
|
1256
|
+
"ok": {
|
|
1257
|
+
"type": "boolean"
|
|
1258
|
+
},
|
|
1259
|
+
"error": {
|
|
1260
|
+
"type": "string"
|
|
1261
|
+
}
|
|
1262
|
+
},
|
|
1263
|
+
"required": [
|
|
1264
|
+
"ok",
|
|
1265
|
+
"error"
|
|
1266
|
+
]
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
},
|
|
1271
|
+
"404": {
|
|
1272
|
+
"description": "The video has no finished poster frame.",
|
|
1273
|
+
"content": {
|
|
1274
|
+
"application/json": {
|
|
1275
|
+
"schema": {
|
|
1276
|
+
"description": "The video has no finished poster frame.",
|
|
1277
|
+
"type": "object",
|
|
1278
|
+
"properties": {
|
|
1279
|
+
"ok": {
|
|
1280
|
+
"type": "boolean"
|
|
1281
|
+
},
|
|
1282
|
+
"error": {
|
|
1283
|
+
"type": "string"
|
|
1284
|
+
}
|
|
1285
|
+
},
|
|
1286
|
+
"required": [
|
|
1287
|
+
"ok",
|
|
1288
|
+
"error"
|
|
1289
|
+
]
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1050
1296
|
}
|
|
1051
1297
|
},
|
|
1052
1298
|
"tags": [
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/mieweb/pulsevault/blob/main/protocol/schemas/artifact-status.schema.json",
|
|
4
|
+
"title": "GET /artifacts/<id>/status response",
|
|
5
|
+
"description": "Where an upload is (PROTOCOL.md §6.5, protocol 2.3): for a page waiting on it, so the host needs no table of its own. Authorized like opening the artifact. Never cached.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["artifactId", "state"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"artifactId": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"format": "uuid",
|
|
12
|
+
"description": "The artifact asked about."
|
|
13
|
+
},
|
|
14
|
+
"state": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": ["unknown", "uploading", "processing", "ready"],
|
|
17
|
+
"description": "`unknown` for an id the server has never seen; `uploading` until the final byte; `processing` while the server converts the bytes for the web; `ready` once the artifact is served."
|
|
18
|
+
},
|
|
19
|
+
"kind": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": ["video", "project", "captions", "thumbnail"],
|
|
22
|
+
"description": "Artifact kind. Absent when `state` is `unknown`."
|
|
23
|
+
},
|
|
24
|
+
"relatedTo": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"format": "uuid",
|
|
27
|
+
"description": "The video this artifact belongs to, if it declared one."
|
|
28
|
+
},
|
|
29
|
+
"name": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "The display name the client sent (`Upload-Metadata.name`), if any."
|
|
32
|
+
},
|
|
33
|
+
"bytesReceived": {
|
|
34
|
+
"type": "number",
|
|
35
|
+
"description": "Bytes received so far while `uploading`, or stored once finished, when the server knows."
|
|
36
|
+
},
|
|
37
|
+
"size": {
|
|
38
|
+
"type": "number",
|
|
39
|
+
"description": "The upload's declared length, when the server knows."
|
|
40
|
+
},
|
|
41
|
+
"acknowledged": {
|
|
42
|
+
"type": "boolean",
|
|
43
|
+
"description": "Whether the host has finished handling the completed upload (its `onUploadComplete` returned)."
|
|
44
|
+
},
|
|
45
|
+
"outcome": {
|
|
46
|
+
"description": "What the host recorded about where the upload went, or why it didn't. Any JSON; absent until the host records one."
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -31,6 +31,9 @@
|
|
|
31
31
|
"type": "string",
|
|
32
32
|
"enum": ["view"],
|
|
33
33
|
"description": "`view` on a read-only view token (§5.5), which only opens artifacts and is signed with a key derived from the secret. Absent on the capability token an upload uses."
|
|
34
|
+
},
|
|
35
|
+
"ctx": {
|
|
36
|
+
"description": "Opaque host data signed into the token (protocol 2.3): who the upload is for, where it goes. The server stores it with the artifact the token creates and hands it back to its own hooks; a client never reads it. Any JSON, at most 1 KiB encoded."
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
}
|