@mieweb/pulsevault 0.5.0 → 0.7.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +152 -1
  2. package/OPERATIONS.md +123 -46
  3. package/PROTOCOL.md +27 -5
  4. package/README.md +31 -8
  5. package/dist/app.d.ts +8 -7
  6. package/dist/app.d.ts.map +1 -1
  7. package/dist/app.js +4 -3
  8. package/dist/app.js.map +1 -1
  9. package/dist/core.d.ts +23 -9
  10. package/dist/core.d.ts.map +1 -1
  11. package/dist/core.js +106 -21
  12. package/dist/core.js.map +1 -1
  13. package/dist/lib/completion.d.ts +22 -5
  14. package/dist/lib/completion.d.ts.map +1 -1
  15. package/dist/lib/completion.js +247 -35
  16. package/dist/lib/completion.js.map +1 -1
  17. package/dist/lib/deeplinks.d.ts +18 -2
  18. package/dist/lib/deeplinks.d.ts.map +1 -1
  19. package/dist/lib/deeplinks.js +13 -2
  20. package/dist/lib/deeplinks.js.map +1 -1
  21. package/dist/lib/magic.d.ts +41 -1
  22. package/dist/lib/magic.d.ts.map +1 -1
  23. package/dist/lib/magic.js +104 -0
  24. package/dist/lib/magic.js.map +1 -1
  25. package/dist/lib/options.d.ts +2 -0
  26. package/dist/lib/options.d.ts.map +1 -1
  27. package/dist/lib/options.js +8 -4
  28. package/dist/lib/options.js.map +1 -1
  29. package/dist/lib/protocol-version.gen.js +1 -1
  30. package/dist/lib/pulsevaultTus.d.ts.map +1 -1
  31. package/dist/lib/pulsevaultTus.js +35 -1
  32. package/dist/lib/pulsevaultTus.js.map +1 -1
  33. package/dist/lib/web-ready.d.ts +145 -18
  34. package/dist/lib/web-ready.d.ts.map +1 -1
  35. package/dist/lib/web-ready.js +484 -91
  36. package/dist/lib/web-ready.js.map +1 -1
  37. package/dist/storage/local.d.ts +3 -1
  38. package/dist/storage/local.d.ts.map +1 -1
  39. package/dist/storage/local.js +310 -50
  40. package/dist/storage/local.js.map +1 -1
  41. package/dist/storage/s3.d.ts.map +1 -1
  42. package/dist/storage/s3.js +21 -1
  43. package/dist/storage/s3.js.map +1 -1
  44. package/dist/storage/types.d.ts +89 -4
  45. package/dist/storage/types.d.ts.map +1 -1
  46. package/dist/storage/types.js +7 -0
  47. package/dist/storage/types.js.map +1 -1
  48. package/package.json +2 -2
  49. package/protocol/openapi.json +26 -3
  50. package/protocol/schemas/artifact-status.schema.json +13 -1
  51. package/protocol/schemas/deep-link.schema.json +2 -2
  52. package/scripts/web-ready-migrate.mjs +35 -11
@@ -1,5 +1,9 @@
1
- import { ensureWebReady } from './web-ready.js';
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { CONFORM_TARGET, ensureWebReady, extractPosterFrame, validateWebReadyOptions, } from './web-ready.js';
2
5
  import { consoleLogger } from './request.js';
6
+ import { uploadIdOf } from '../storage/types.js';
3
7
  const DEFAULT_REPLAY_INTERVAL_SECONDS = 300;
4
8
  /** The first replay after start: late enough for the host to finish booting. */
5
9
  const FIRST_REPLAY_DELAY_MS = 5_000;
@@ -11,14 +15,15 @@ export function validateCompletionOptions(opts) {
11
15
  if (typeof opts.storage.getLocalPath !== 'function') {
12
16
  throw new TypeError('`webReady` needs a storage adapter with `getLocalPath` (the local adapter): ffmpeg rewrites the file in place');
13
17
  }
14
- if (typeof opts.storage.patchArtifact !== 'function') {
15
- throw new TypeError('`webReady` needs a storage adapter with `patchArtifact`');
18
+ if (typeof opts.storage.patchArtifact !== 'function' || typeof opts.storage.describeArtifact !== 'function') {
19
+ throw new TypeError('`webReady` needs a storage adapter with `patchArtifact` and `describeArtifact`');
16
20
  }
17
21
  if (typeof opts.webReady === 'object') {
18
22
  const { concurrency } = opts.webReady;
19
23
  if (concurrency !== undefined && !(Number.isInteger(concurrency) && concurrency >= 1)) {
20
24
  throw new TypeError('`webReady.concurrency` must be a positive integer');
21
25
  }
26
+ validateWebReadyOptions(opts.webReady);
22
27
  }
23
28
  }
24
29
  if (opts.replay) {
@@ -42,11 +47,15 @@ function contextFor(meta, upload, replay) {
42
47
  size: upload.size,
43
48
  uploadId: upload.uploadId,
44
49
  filename: meta?.filename ?? '',
45
- ext: meta?.ext ?? '',
50
+ // `filename`'s extension, as documented: the uploaded one, even once a conversion changed it.
51
+ ext: meta ? (meta.sourceExt ?? meta.ext) : '',
46
52
  ...(meta?.relatedTo ? { relatedTo: meta.relatedTo } : {}),
47
53
  ...(meta?.name ? { name: meta.name } : {}),
48
54
  ...(meta?.appVersion ? { appVersion: meta.appVersion } : {}),
49
55
  ...(meta?.context !== undefined ? { context: meta.context } : {}),
56
+ // What a conversion did, once one was recorded: a replayed hook gets it too, so a host that
57
+ // names the file from it (an `.mp4` once a WebM was conformed) gets it right the second time.
58
+ ...(meta?.converted && meta.webReady ? { webReady: meta.webReady } : {}),
50
59
  replay,
51
60
  };
52
61
  }
@@ -104,6 +113,121 @@ export function createCompletionRunner(opts) {
104
113
  const queue = createQueue(webReady?.concurrency ?? 1);
105
114
  const replayEvery = opts.replay === false ? null : (opts.replay?.intervalSeconds ?? DEFAULT_REPLAY_INTERVAL_SECONDS) * 1000;
106
115
  const converts = (kind) => webReady !== undefined && kind === 'video';
116
+ const postersOn = webReady !== undefined &&
117
+ webReady.poster !== false &&
118
+ typeof storage.storeArtifact === 'function' &&
119
+ typeof storage.listRelated === 'function';
120
+ /**
121
+ * `videoId`'s thumbnail: `'ready'` once one is stored (its pulse sent one, or one was made),
122
+ * `'pending'` while one is still uploading — it may yet arrive, or be abandoned — else `'none'`.
123
+ */
124
+ const thumbnailState = async (videoId) => {
125
+ let state = 'none';
126
+ for await (const record of storage.listRelated(videoId)) {
127
+ if (record.kind !== 'thumbnail')
128
+ continue;
129
+ if (record.ready)
130
+ return 'ready';
131
+ state = 'pending';
132
+ }
133
+ return state;
134
+ };
135
+ /**
136
+ * A poster for `videoId` when it has no thumbnail: a frame of the stored (conformed) file,
137
+ * stored as a thumbnail `relatedTo` it. One at a time per video as it is now (its id and
138
+ * `generation`), whichever path asked: a new upload of the id never joins a run on the old one.
139
+ * Never throws: a video without a poster still plays. Resolves `'retry'` when it should be
140
+ * tried again later (a thumbnail still uploading, the frame or the store failed, or the video
141
+ * changed meanwhile), else `'done'`.
142
+ */
143
+ const posterRuns = new Map();
144
+ const makePoster = async (videoId) => {
145
+ if (!postersOn)
146
+ return 'done';
147
+ let video;
148
+ try {
149
+ video = await describe(videoId);
150
+ }
151
+ catch (err) {
152
+ logger.error({ err, artifactId: videoId }, 'pulsevault could not make a poster');
153
+ return 'retry';
154
+ }
155
+ if (!video?.ready)
156
+ return 'done';
157
+ // A video stored before generations were kept has none; any new upload of its id gets one.
158
+ const generation = video.generation ?? null;
159
+ const key = `${videoId}:${generation ?? ''}`;
160
+ const running = posterRuns.get(key);
161
+ if (running)
162
+ return running;
163
+ const run = (async () => {
164
+ try {
165
+ const before = await thumbnailState(videoId);
166
+ if (before !== 'none')
167
+ return before === 'ready' ? 'done' : 'retry';
168
+ const localPath = await storage.getLocalPath?.(videoId);
169
+ if (typeof localPath !== 'string')
170
+ return 'done';
171
+ const bytes = await extractPosterFrame(localPath, { ...webReady, logger });
172
+ if (!bytes)
173
+ return 'retry';
174
+ // A client thumbnail that arrived while the frame was made: no poster needed. One that
175
+ // lands after this check still wins, in `getPulse`, over the `generated` poster.
176
+ const after = await thumbnailState(videoId);
177
+ if (after !== 'none')
178
+ return after === 'ready' ? 'done' : 'retry';
179
+ // Refused when the video was deleted or uploaded again meanwhile: not done, so the next
180
+ // ask for its poster tries the video as it is then.
181
+ const stored = await storage.storeArtifact({
182
+ artifactId: randomUUID(),
183
+ kind: 'thumbnail',
184
+ ext: '.jpg',
185
+ filename: 'poster.jpg',
186
+ relatedTo: videoId,
187
+ relatedGeneration: generation,
188
+ bytes,
189
+ });
190
+ return stored ? 'done' : 'retry';
191
+ }
192
+ catch (err) {
193
+ logger.error({ err, artifactId: videoId }, 'pulsevault could not make a poster');
194
+ return 'retry';
195
+ }
196
+ })().finally(() => posterRuns.delete(key));
197
+ posterRuns.set(key, run);
198
+ return run;
199
+ };
200
+ /**
201
+ * Videos `posterFor` settled in this process, so a feed of old videos asks once each. A video
202
+ * that should be tried again (a thumbnail still uploading, a failed frame, a conversion not
203
+ * done yet) leaves the set, and its next poster request tries again. Cleared past the cap,
204
+ * which only means a retry.
205
+ */
206
+ const POSTER_TRIED_LIMIT = 10_000;
207
+ const posterTried = new Set();
208
+ const posterFor = (artifactId) => {
209
+ if (!postersOn || posterTried.has(artifactId))
210
+ return;
211
+ if (posterTried.size >= POSTER_TRIED_LIMIT)
212
+ posterTried.clear();
213
+ posterTried.add(artifactId);
214
+ void queue.run(async () => {
215
+ let outcome = 'retry';
216
+ try {
217
+ const meta = await describe(artifactId);
218
+ if (!meta || meta.kind !== 'video')
219
+ outcome = 'done';
220
+ // A video still waiting on its conversion gets its poster there.
221
+ else if (meta.ready && meta.converted)
222
+ outcome = await makePoster(artifactId);
223
+ }
224
+ catch (err) {
225
+ logger.error({ err, artifactId }, 'pulsevault could not make a poster');
226
+ }
227
+ if (outcome === 'retry')
228
+ posterTried.delete(artifactId);
229
+ });
230
+ };
107
231
  const describe = (artifactId) => storage.describeArtifact ? storage.describeArtifact(artifactId) : Promise.resolve(null);
108
232
  const record = async (artifactId, patch) => {
109
233
  try {
@@ -114,24 +238,105 @@ export function createCompletionRunner(opts) {
114
238
  logger.error({ err, artifactId, patch }, 'pulsevault could not record a completion step');
115
239
  }
116
240
  };
117
- /** Rule 1. Never throws: a failed conversion serves the original bytes and is tried again later. */
118
- const convert = (ctx) => new Promise((resolve) => {
241
+ /**
242
+ * Record a conversion's result, and install the file it wrote (`outputPath`, a temporary
243
+ * `.mp4` beside the stored file), in one patch under the adapter's lock: only for the upload
244
+ * the conversion began on (`generation`) and only while no other pass has recorded one
245
+ * (`unlessConverted`). Another container's original is deleted by the patch once the sidecar
246
+ * names the `.mp4`. When the patch doesn't apply — the artifact was removed, or reserved again,
247
+ * or converted elsewhere meanwhile — or fails, the file it wrote goes and nothing else
248
+ * changes. Until a record is written the original serves and the next pass converts again.
249
+ * `storedExt`: the extension of the file the conversion ran on, when it isn't the one the
250
+ * sidecar names (the local adapter found the converted `.mp4` under a sidecar written from a
251
+ * copy older than the conversion): the record names that file again. Resolves whether this
252
+ * record applied.
253
+ */
254
+ const recordConversion = async (artifactId, generation, result, outputPath, storedExt) => {
255
+ let applied = false;
256
+ try {
257
+ applied =
258
+ (await storage.patchArtifact?.(artifactId, {
259
+ converted: true,
260
+ webReady: result,
261
+ unlessConverted: true,
262
+ generation,
263
+ ...(outputPath
264
+ ? { file: outputPath, ext: CONFORM_TARGET.extension }
265
+ : storedExt
266
+ ? { ext: storedExt }
267
+ : {}),
268
+ })) ?? false;
269
+ }
270
+ catch (err) {
271
+ logger.error({ err, artifactId }, 'pulsevault could not record a web-ready conversion');
272
+ }
273
+ if (!applied && outputPath)
274
+ await fs.rm(outputPath, { force: true });
275
+ return applied;
276
+ };
277
+ /**
278
+ * Rule 1, for the reservation the work was scheduled for (`generation`; `undefined` when the
279
+ * adapter can't say). Never throws: a failed conversion serves the original bytes, and says why.
280
+ */
281
+ const convert = (ctx, generation) => new Promise((resolve) => {
119
282
  void queue.run(async () => {
120
283
  try {
284
+ // What was read before this job waited for its slot may be stale: the artifact may
285
+ // have been removed — and its id reserved again by another upload, which isn't this
286
+ // job's — or converted by another instance on the same disk, meanwhile.
287
+ const fresh = await describe(ctx.artifactId);
288
+ if (!fresh || !fresh.ready || (generation !== undefined && (fresh.generation ?? null) !== generation)) {
289
+ resolve(undefined);
290
+ return;
291
+ }
292
+ if (fresh.converted) {
293
+ resolve(fresh.webReady);
294
+ return;
295
+ }
121
296
  const localPath = await storage.getLocalPath?.(ctx.artifactId);
122
- const result = typeof localPath === 'string'
123
- ? await ensureWebReady(localPath, { ...webReady, logger })
124
- : { action: 'skipped', reason: 'no local path for this artifact' };
125
- await record(ctx.artifactId, { converted: true });
126
- await onArtifactEvent?.({
127
- phase: 'processed',
128
- artifactId: ctx.artifactId,
129
- kind: ctx.kind,
130
- size: ctx.size,
131
- reason: result.reason,
132
- webReady: result,
133
- });
297
+ // `install: false`: the file is installed by the record below, under the adapter's
298
+ // lock and conditions, never renamed over the stored file from here. Only with a
299
+ // generation: a conversion takes long enough for the id to be removed and uploaded
300
+ // again, and without one the record couldn't tell this upload from that one.
301
+ const { outputPath, ...result } = typeof localPath !== 'string'
302
+ ? { action: 'skipped', reason: 'no local path for this artifact', outputPath: undefined }
303
+ : !fresh.generation
304
+ ? { action: 'skipped', reason: 'the storage adapter keeps no generation for this upload', outputPath: undefined }
305
+ : await ensureWebReady(localPath, { ...webReady, logger, install: false });
306
+ const expected = generation !== undefined ? generation : (fresh.generation ?? null);
307
+ const localExt = typeof localPath === 'string' ? path.extname(localPath).toLowerCase() : '';
308
+ const storedExt = localExt && localExt !== fresh.ext ? localExt : undefined;
309
+ if (!(await recordConversion(ctx.artifactId, expected, result, outputPath, storedExt))) {
310
+ // Lost to another pass: its result, but only while the id is still this reservation's
311
+ // (a removal and a new upload of the id would hand back the new upload's result).
312
+ const now = await describe(ctx.artifactId);
313
+ resolve(now && (now.generation ?? null) === expected ? now.webReady : undefined);
314
+ return;
315
+ }
316
+ // The result is recorded: an observer that throws is the observer's failure, not the
317
+ // conversion's, and doesn't hide the result from the hook that follows it.
318
+ try {
319
+ await onArtifactEvent?.({
320
+ phase: 'processed',
321
+ artifactId: ctx.artifactId,
322
+ kind: ctx.kind,
323
+ size: ctx.size,
324
+ reason: result.reason,
325
+ webReady: result,
326
+ });
327
+ }
328
+ catch (err) {
329
+ logger.error({ err, artifactId: ctx.artifactId }, 'pulsevault onArtifactEvent (processed) failed');
330
+ }
331
+ // In the same slot. With `completeAfter` the hook waits for it, so the host is told of
332
+ // the video with its poster; otherwise the conversion settles first, as it always has.
333
+ // A new upload of the id starts fresh for the poster route's make-on-miss, too.
334
+ posterTried.delete(ctx.artifactId);
335
+ if (completeAfter)
336
+ await makePoster(ctx.artifactId);
134
337
  resolve(result);
338
+ if (!completeAfter)
339
+ await makePoster(ctx.artifactId);
135
340
  }
136
341
  catch (err) {
137
342
  logger.error({ err, artifactId: ctx.artifactId }, 'pulsevault web-ready conversion failed');
@@ -139,14 +344,18 @@ export function createCompletionRunner(opts) {
139
344
  }
140
345
  });
141
346
  });
142
- /** Rule 2. Rethrows what the hook threw. */
143
- const hook = async (request, ctx) => {
347
+ /** Rule 2, recorded only on the reservation it ran for. Rethrows what the hook threw. */
348
+ const hook = async (request, ctx, generation) => {
144
349
  if (onUploadComplete)
145
350
  await onUploadComplete(request, ctx);
146
- await record(ctx.artifactId, { acknowledged: true });
351
+ await record(ctx.artifactId, { acknowledged: true, ...(generation !== undefined ? { generation } : {}) });
147
352
  };
148
- /** One artifact is settled by one caller at a time; a second caller joins the first. */
353
+ /**
354
+ * One upload is settled by one caller at a time; a second caller joins the first. Keyed by the
355
+ * reservation too: a new upload of an id that was removed is never joined to the old one's.
356
+ */
149
357
  const settling = new Map();
358
+ const settlingKey = (artifactId, generation) => `${artifactId}/${generation ?? ''}`;
150
359
  /**
151
360
  * Apply the rule to one finished artifact. The request that finished the upload waits on the
152
361
  * result: it rejects when the hook threw, so the client gets a non-2xx — except with
@@ -155,7 +364,9 @@ export function createCompletionRunner(opts) {
155
364
  * logged and left for the next pass.
156
365
  */
157
366
  const settle = (request, meta, upload, replay) => {
158
- const running = settling.get(upload.artifactId);
367
+ const generation = meta ? (meta.generation ?? null) : undefined;
368
+ const key = settlingKey(upload.artifactId, generation);
369
+ const running = settling.get(key);
159
370
  if (running)
160
371
  return running;
161
372
  const ctx = contextFor(meta, upload, replay);
@@ -169,32 +380,32 @@ export function createCompletionRunner(opts) {
169
380
  if (needsConversion && completeAfter) {
170
381
  // Nothing for the request to wait on: the hook follows the conversion.
171
382
  run = (async () => {
172
- const result = await convert(ctx);
383
+ const result = await convert(ctx, generation);
173
384
  if (!needsHook)
174
385
  return;
175
386
  try {
176
- await hook(request, { ...ctx, ...(result ? { webReady: result } : {}) });
387
+ await hook(request, { ...ctx, ...(result ? { webReady: result } : {}) }, generation);
177
388
  }
178
389
  catch (err) {
179
390
  logger.error({ err, artifactId: ctx.artifactId, kind: ctx.kind }, 'pulsevault onUploadComplete failed after web-ready; it will be tried again');
180
391
  }
181
392
  })();
182
- settling.set(upload.artifactId, run);
183
- void run.finally(() => settling.delete(upload.artifactId));
393
+ settling.set(key, run);
394
+ void run.finally(() => settling.delete(key));
184
395
  return Promise.resolve();
185
396
  }
186
397
  run = (async () => {
187
- const conversion = needsConversion ? convert(ctx) : Promise.resolve(undefined);
398
+ const conversion = needsConversion ? convert(ctx, generation) : Promise.resolve(undefined);
188
399
  try {
189
400
  if (needsHook)
190
- await hook(request, ctx);
401
+ await hook(request, ctx, generation);
191
402
  }
192
403
  finally {
193
404
  // The settle covers the conversion too, so a replay doesn't queue it again meanwhile.
194
- void conversion.finally(() => settling.delete(upload.artifactId));
405
+ void conversion.finally(() => settling.delete(key));
195
406
  }
196
407
  })();
197
- settling.set(upload.artifactId, run);
408
+ settling.set(key, run);
198
409
  return run;
199
410
  };
200
411
  const complete = async (request, upload) => settle(request, await describe(upload.artifactId), upload, false);
@@ -219,7 +430,7 @@ export function createCompletionRunner(opts) {
219
430
  }
220
431
  const pending = [];
221
432
  for await (const record of storage.listArtifacts()) {
222
- if (!record.ready || settling.has(record.artifactId))
433
+ if (!record.ready)
223
434
  continue;
224
435
  let meta;
225
436
  try {
@@ -229,11 +440,11 @@ export function createCompletionRunner(opts) {
229
440
  logger.error({ err, artifactId: record.artifactId }, 'pulsevault replay could not read an artifact');
230
441
  continue;
231
442
  }
232
- if (!meta || !meta.ready || settling.has(meta.artifactId))
443
+ if (!meta || !meta.ready || settling.has(settlingKey(meta.artifactId, meta.generation ?? null)))
233
444
  continue;
234
445
  if (meta.acknowledged && !(converts(meta.kind) && !meta.converted))
235
446
  continue;
236
- const uploadId = `${meta.kind}/${meta.artifactId}${meta.ext}`;
447
+ const uploadId = uploadIdOf(meta);
237
448
  const upload = {
238
449
  artifactId: meta.artifactId,
239
450
  kind: meta.kind,
@@ -269,6 +480,7 @@ export function createCompletionRunner(opts) {
269
480
  complete,
270
481
  replay,
271
482
  converts,
483
+ posterFor,
272
484
  start: () => {
273
485
  if (timer || stopped)
274
486
  return;
@@ -281,7 +493,7 @@ export function createCompletionRunner(opts) {
281
493
  timer = null;
282
494
  await replaying?.catch(() => []);
283
495
  await queue.drain();
284
- await Promise.allSettled([...settling.values()]);
496
+ await Promise.allSettled([...settling.values(), ...posterRuns.values()]);
285
497
  },
286
498
  };
287
499
  }
@@ -1 +1 @@
1
- {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/lib/completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA6C,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAiD,MAAM,cAAc,CAAC;AA2H5F,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAC5C,gFAAgF;AAChF,MAAM,qBAAqB,GAAG,KAAK,CAAC;AACpC,kFAAkF;AAClF,MAAM,cAAc,GAAsB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAM1D,2FAA2F;AAC3F,MAAM,UAAU,yBAAyB,CACvC,IAAsE;IAEtE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,IAAI,OAAQ,IAAI,CAAC,OAA4B,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;YAC1E,MAAM,IAAI,SAAS,CACjB,+GAA+G,CAChH,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;YACrD,MAAM,IAAI,SAAS,CAAC,yDAAyD,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;YACtC,IAAI,WAAW,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,IAAI,CAAC,CAAC,EAAE,CAAC;gBACtF,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACxC,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;YAChG,MAAM,IAAI,SAAS,CAAC,0EAA0E,CAAC,CAAC;QAClG,CAAC;QACD,4FAA4F;QAC5F,6CAA6C;QAC7C,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACxE,IAAI,OAAO,aAAa,KAAK,UAAU,IAAI,OAAO,gBAAgB,KAAK,UAAU,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE,CAAC;YACzH,MAAM,IAAI,SAAS,CACjB,kIAAkI,CACnI,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,kEAAkE;AAClE,SAAS,UAAU,CACjB,IAAmC,EACnC,MAAsB,EACtB,MAAe;IAEf,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE;QAC9B,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE;QACpB,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,MAAM;KACP,CAAC;AACJ,CAAC;AAED,6FAA6F;AAC7F,SAAS,WAAW,CAAC,WAAmB;IACtC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAC;IACzC,MAAM,GAAG,GAAG,CAAC,GAAwB,EAAiB,EAAE;QACtD,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE;YACvB,IAAI,MAAM,IAAI,WAAW;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YACvF,MAAM,EAAE,CAAC;YACT,IAAI,CAAC;gBACH,MAAM,GAAG,EAAE,CAAC;YACd,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,CAAC;gBACT,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,OAAO,OAAO,CAAC,IAAI,GAAG,CAAC;YAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC;IACF,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA6B;IAClE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC;IAC5C,MAAM,QAAQ,GAA0C,IAAI,CAAC,QAAQ;QACnE,CAAC,CAAC,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ;YACjC,CAAC,CAAC,IAAI,CAAC,QAAQ;YACf,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,aAAa,GAAG,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACvD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,WAAW,IAAI,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GACf,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,IAAI,+BAA+B,CAAC,GAAG,IAAI,CAAC;IAE1G,MAAM,QAAQ,GAAG,CAAC,IAAgB,EAAW,EAAE,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO,CAAC;IAE3F,MAAM,QAAQ,GAAG,CAAC,UAAkB,EAA0C,EAAE,CAC9E,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1F,MAAM,MAAM,GAAG,KAAK,EAAE,UAAkB,EAAE,KAAgD,EAAE,EAAE;QAC5F,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,0FAA0F;YAC1F,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,+CAA+C,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC,CAAC;IAEF,oGAAoG;IACpG,MAAM,OAAO,GAAG,CAAC,GAAoC,EAAuC,EAAE,CAC5F,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACtB,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;YACxB,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAO,OAA4B,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACrF,MAAM,MAAM,GACV,OAAO,SAAS,KAAK,QAAQ;oBAC3B,CAAC,CAAC,MAAM,cAAc,CAAC,SAAS,EAAE,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC1D,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;gBACvE,MAAM,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClD,MAAM,eAAe,EAAE,CAAC;oBACtB,KAAK,EAAE,WAAW;oBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,QAAQ,EAAE,MAAM;iBACjB,CAAC,CAAC;gBACH,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,EAAE,wCAAwC,CAAC,CAAC;gBAC5F,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,4CAA4C;IAC5C,MAAM,IAAI,GAAG,KAAK,EAChB,OAA0B,EAC1B,GAAoC,EACrB,EAAE;QACjB,IAAI,gBAAgB;YAAE,MAAM,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3D,MAAM,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC;IAEF,wFAAwF;IACxF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IAElD;;;;;;OAMG;IACH,MAAM,MAAM,GAAG,CACb,OAA0B,EAC1B,IAAmC,EACnC,MAAsB,EACtB,MAAe,EACA,EAAE;QACjB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAChD,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,0FAA0F;QAC1F,8DAA8D;QAC9D,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAClF,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAE7D,IAAI,GAAkB,CAAC;QACvB,IAAI,eAAe,IAAI,aAAa,EAAE,CAAC;YACrC,uEAAuE;YACvE,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE;gBAChB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,CAAC,SAAS;oBAAE,OAAO;gBACvB,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC3E,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,KAAK,CACV,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EACnD,4EAA4E,CAC7E,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;YACL,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YACrC,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YAC3D,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE;YAChB,MAAM,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/E,IAAI,CAAC;gBACH,IAAI,SAAS;oBAAE,MAAM,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC1C,CAAC;oBAAS,CAAC;gBACT,sFAAsF;gBACtF,KAAK,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,EAAE,OAA0B,EAAE,MAAsB,EAAiB,EAAE,CAC3F,MAAM,CAAC,OAAO,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAEpE,8FAA8F;IAC9F,MAAM,UAAU,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;QAC7D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC3D,OAAO,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,SAAS,GAA6B,IAAI,CAAC;IAC/C,MAAM,MAAM,GAAG,GAAsB,EAAE;QACrC,IAAI,SAAS;YAAE,OAAO,SAAS,CAAC;QAChC,SAAS,GAAG,CAAC,KAAK,IAAI,EAAE;YACtB,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,IAAI,OAAO,OAAO,CAAC,aAAa,KAAK,UAAU,IAAI,OAAO,OAAO,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;gBAClG,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,MAAM,OAAO,GAAoB,EAAE,CAAC;YACpC,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;gBACnD,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;oBAAE,SAAS;gBAC/D,IAAI,IAAmC,CAAC;gBACxC,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBAC3D,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,8CAA8C,CAAC,CAAC;oBACrG,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC;oBAAE,SAAS;gBACpE,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;oBAAE,SAAS;gBAC7E,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC9D,MAAM,MAAM,GAAmB;oBAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,MAAM,UAAU,CAAC,QAAQ,CAAC;oBAChC,QAAQ;iBACT,CAAC;gBACF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC/B,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBACvD,MAAM,CAAC,KAAK,CACV,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EACrD,sEAAsE,CACvE,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC;YACJ,CAAC;YACD,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;YAChB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,IAAI,KAAK,GAA0B,IAAI,CAAC;IACxC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAQ,EAAE;QACzC,IAAI,OAAO,IAAI,WAAW,KAAK,IAAI;YAAE,OAAO;QAC5C,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,KAAK,GAAG,IAAI,CAAC;YACb,KAAK,MAAM,EAAE;iBACV,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,qCAAqC,CAAC,CAAC;iBAC5E,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1C,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,KAAK,EAAE,GAAG,EAAE;YACV,IAAI,KAAK,IAAI,OAAO;gBAAE,OAAO;YAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,WAAW,IAAI,qBAAqB,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,GAAG,IAAI,CAAC;YACb,MAAM,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACjC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/lib/completion.ts"],"names":[],"mappings":"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"}
@@ -16,10 +16,26 @@ export type UploadLinkOptions = {
16
16
  * step. Generate with `crypto.randomUUID()`.
17
17
  */
18
18
  artifactId: string;
19
+ /**
20
+ * Which of the two equivalent link forms to build (PROTOCOL.md §3):
21
+ * - `'pulsecam'` (default): `pulsecam://?<params>`, which every Pulse app opens.
22
+ * - `'https'`: `https://mieweb.github.io/pulse/open#<params>`, a Universal Link / App Link.
23
+ * Phone cameras open it, it opens Pulse when it's installed, and its page sends the person
24
+ * to the store when it isn't. The parameters ride in the fragment, so the link host never
25
+ * receives the token. Only Pulse releases that claim the link host open it directly; an
26
+ * older Pulse lands on the page, whose "Open it" button falls back to `pulsecam://`.
27
+ */
28
+ form?: 'pulsecam' | 'https';
19
29
  };
20
30
  /**
21
- * Build a `pulsecam://` deep link that opens the Pulse app directly on the
22
- * upload screen for a specific artifact, pointed at this server.
31
+ * Where the https form of a pairing link points: the page on the link host the Pulse app
32
+ * claims. Fixed, because an app can only claim domains it was built with.
33
+ */
34
+ export declare const PULSE_OPEN_URL = "https://mieweb.github.io/pulse/open";
35
+ /**
36
+ * Build a pairing link that opens the Pulse app directly on the upload screen
37
+ * for a specific artifact, pointed at this server: `pulsecam://?<params>`, or
38
+ * with `form: 'https'`, `${PULSE_OPEN_URL}#<params>`.
23
39
  *
24
40
  * No `mode` param — there's only one mode, so it was always redundant. `v`
25
41
  * lets the app refuse/explain a future incompatible link shape instead of
@@ -1 +1 @@
1
- {"version":3,"file":"deeplinks.d.ts","sourceRoot":"","sources":["../../src/lib/deeplinks.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,gJAAgJ;IAChJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AA4BF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAqB/D"}
1
+ {"version":3,"file":"deeplinks.d.ts","sourceRoot":"","sources":["../../src/lib/deeplinks.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,gJAAgJ;IAChJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CAC7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,wCAAwC,CAAC;AA4BpE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAyB/D"}
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Where the https form of a pairing link points: the page on the link host the Pulse app
3
+ * claims. Fixed, because an app can only claim domains it was built with.
4
+ */
5
+ export const PULSE_OPEN_URL = 'https://mieweb.github.io/pulse/open';
1
6
  /** Deep-link wire format version. Bump when the param shape changes incompatibly. */
2
7
  const LINK_VERSION = '1';
3
8
  /**
@@ -23,8 +28,9 @@ function isPrivateDevOrigin(url) {
23
28
  );
24
29
  }
25
30
  /**
26
- * Build a `pulsecam://` deep link that opens the Pulse app directly on the
27
- * upload screen for a specific artifact, pointed at this server.
31
+ * Build a pairing link that opens the Pulse app directly on the upload screen
32
+ * for a specific artifact, pointed at this server: `pulsecam://?<params>`, or
33
+ * with `form: 'https'`, `${PULSE_OPEN_URL}#<params>`.
28
34
  *
29
35
  * No `mode` param — there's only one mode, so it was always redundant. `v`
30
36
  * lets the app refuse/explain a future incompatible link shape instead of
@@ -37,6 +43,9 @@ function isPrivateDevOrigin(url) {
37
43
  * issued in the first place.
38
44
  */
39
45
  export function buildUploadLink(opts) {
46
+ if (opts.form !== undefined && opts.form !== 'pulsecam' && opts.form !== 'https') {
47
+ throw new Error(`buildUploadLink: \`form\` must be 'pulsecam' or 'https' (got "${String(opts.form)}")`);
48
+ }
40
49
  let server;
41
50
  try {
42
51
  server = new URL(opts.server);
@@ -55,6 +64,8 @@ export function buildUploadLink(opts) {
55
64
  });
56
65
  if (opts.token)
57
66
  params.set('token', opts.token);
67
+ if (opts.form === 'https')
68
+ return `${PULSE_OPEN_URL}#${params.toString()}`;
58
69
  return `pulsecam://?${params.toString()}`;
59
70
  }
60
71
  //# sourceMappingURL=deeplinks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deeplinks.js","sourceRoot":"","sources":["../../src/lib/deeplinks.ts"],"names":[],"mappings":"AAoBA,qFAAqF;AACrF,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,GAAQ;IAClC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC1B,OAAO,CACL,IAAI,KAAK,WAAW;QACpB,IAAI,KAAK,WAAW;QACpB,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;QAChC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;QACjC,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC;QAChD,mDAAmD,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,0BAA0B;QAC5F,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa;KAChD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,IAAuB;IACrD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,sDAAsD,IAAI,CAAC,MAAM,OAAO;YACtE,uFAAuF,CAC1F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,CAAC,EAAE,YAAY;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,OAAO,eAAe,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"deeplinks.js","sourceRoot":"","sources":["../../src/lib/deeplinks.ts"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,qCAAqC,CAAC;AAEpE,qFAAqF;AACrF,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,GAAQ;IAClC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC1B,OAAO,CACL,IAAI,KAAK,WAAW;QACpB,IAAI,KAAK,WAAW;QACpB,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;QAChC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;QACjC,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC;QAChD,mDAAmD,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,0BAA0B;QAC5F,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa;KAChD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAAC,IAAuB;IACrD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,iEAAiE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1G,CAAC;IACD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,sDAAsD,IAAI,CAAC,MAAM,OAAO;YACtE,uFAAuF,CAC1F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,CAAC,EAAE,YAAY;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,GAAG,cAAc,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC3E,OAAO,eAAe,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC5C,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { PulseVaultRequest } from './request.js';
1
+ import { type PulseVaultLogger, type PulseVaultRequest } from './request.js';
2
2
  import type { LocalStorage } from '../storage/local.js';
3
3
  import type { S3Storage } from '../storage/s3.js';
4
4
  import type { UploadKind } from '../storage/types.js';
@@ -72,4 +72,44 @@ export declare function createMp4Sniffer(storage: LocalStorage): PulseVaultValid
72
72
  * ```
73
73
  */
74
74
  export declare function createS3Mp4Sniffer(storage: S3Storage): PulseVaultValidatePayload;
75
+ /**
76
+ * Whether a file's first bytes open one of the video containers PulseVault accepts: ISO base
77
+ * media (`ftyp`: MP4, MOV, M4V, 3GP), EBML (WebM, MKV) or RIFF `AVI `. A ~12-byte sniff, for
78
+ * when ffprobe isn't installed: it tells a video container from a renamed document, not a
79
+ * playable video from a broken one.
80
+ */
81
+ export declare function sniffVideo(filePath: string): Promise<boolean>;
82
+ export type VideoValidatorOptions = {
83
+ /** Refuse a video longer than this many seconds. Default: no limit. */
84
+ maxDurationSeconds?: number;
85
+ /** Path to the ffprobe binary. Default `"ffprobe"` (resolved via PATH). */
86
+ ffprobePath?: string;
87
+ /**
88
+ * Wall-clock limit for each ffprobe run, in seconds, so a malformed file can't hold the
89
+ * final `PATCH` open. Default `60`.
90
+ */
91
+ probeTimeoutSeconds?: number;
92
+ /** Where the one-time "ffprobe not found" warning goes. Defaults to `console`. */
93
+ logger?: PulseVaultLogger;
94
+ };
95
+ /**
96
+ * Build a `validatePayload` hook that checks a video by what it is, not its file name: ffprobe
97
+ * must find a video stream with a duration above zero (and, with `maxDurationSeconds`, not
98
+ * longer than that). Without ffprobe on the host it falls back to `sniffVideo` and logs once.
99
+ * Other kinds pass untouched. Needs the bytes on local disk (the local adapter).
100
+ *
101
+ * A refusal is a `422` whose message a host can show as it is: "That file isn't a video.",
102
+ * "That video is longer than the limit of 10 minutes." or, when ffprobe runs past
103
+ * `probeTimeoutSeconds` (a malformed file), "That video couldn't be checked in time."
104
+ *
105
+ * Usage:
106
+ * ```ts
107
+ * await app.register(pulseVault, {
108
+ * storage: createLocalStorage({ workspaceDir: "./data" }),
109
+ * validatePayload: createVideoValidator({ maxDurationSeconds: 600 }),
110
+ * // ...
111
+ * });
112
+ * ```
113
+ */
114
+ export declare function createVideoValidator(options?: VideoValidatorOptions): PulseVaultValidatePayload;
75
115
  //# sourceMappingURL=magic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"magic.d.ts","sourceRoot":"","sources":["../../src/lib/magic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,wHAAwH;IACxH,IAAI,EAAE,UAAU,CAAC;IACjB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KACE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAejE;AAaD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,yBAAyB,CAgBjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,yBAAyB,CAehF"}
1
+ {"version":3,"file":"magic.d.ts","sourceRoot":"","sources":["../../src/lib/magic.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,wHAAwH;IACxH,IAAI,EAAE,UAAU,CAAC;IACjB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KACE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAejE;AAaD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,yBAAyB,CAgBjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,yBAAyB,CAehF;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBnE;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kFAAkF;IAClF,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,CAAC;AAcF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,yBAAyB,CA6CnG"}