@goodandready/dsh-subscriptions 0.2.3 → 0.2.5
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/lib/client.js +13 -1
- package/lib/index.js +71 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -300,7 +300,19 @@ window.__ModuleLoader__.load({
|
|
|
300
300
|
React.createElement('a', { href: account.validationUrl, target: '_blank', rel: 'noopener noreferrer' }, t('verifyLink')),
|
|
301
301
|
t('verifySuffix'),
|
|
302
302
|
) : null,
|
|
303
|
-
(function(){
|
|
303
|
+
(function(){
|
|
304
|
+
var q=account.quota, up=account.usagePercent, a=[];
|
|
305
|
+
if(q){
|
|
306
|
+
if(q.remaining!=null&&q.limit!=null)a.push(q.remaining+'/'+q.limit);
|
|
307
|
+
else if(q.remaining!=null)a.push(String(q.remaining));
|
|
308
|
+
if(q.usedPercent!=null)a.push(Math.round(q.usedPercent)+'%');
|
|
309
|
+
if(q.resetAt){var d=new Date(q.resetAt);a.push(d.toLocaleTimeString())}
|
|
310
|
+
if(q.measuredAt){var m=Math.round((Date.now()-q.measuredAt)/60000);a.push(m<1?'<1m':m+'m')}
|
|
311
|
+
}
|
|
312
|
+
if(up!=null&&!q)a.push(Math.round(up)+'%');
|
|
313
|
+
if(!a.length)return null;
|
|
314
|
+
return React.createElement('span',{className:'dsub-sub'},t('quota')+' '+a.join(' \u00b7 '));
|
|
315
|
+
})(),
|
|
304
316
|
|
|
305
317
|
account.paidTierName ? React.createElement('span', { className: 'dsub-sub' }, t('plan') + ': ' + account.paidTierName) : null,
|
|
306
318
|
account.ref ? React.createElement('span', { className: 'dsub-sub' }, t('storedAs') + ' ' + account.ref) : null,
|
package/lib/index.js
CHANGED
|
@@ -487,6 +487,77 @@ export function apply(ctx, config) {
|
|
|
487
487
|
},
|
|
488
488
|
}), 'dsh-subscriptions: /oauth/complete')
|
|
489
489
|
|
|
490
|
+
// ponytail: cheap per-vendor probe; never sets cooldown, never returns tokens
|
|
491
|
+
ctx.effect(() => ctx.webServer.register({
|
|
492
|
+
kind: 'exact',
|
|
493
|
+
path: '/dsh-subscriptions/check',
|
|
494
|
+
handler: async (req, res) => {
|
|
495
|
+
if (req.method !== 'POST') {
|
|
496
|
+
writeJson(res, 405, { ok: false, error: { code: 'method', message: 'POST only' } })
|
|
497
|
+
return
|
|
498
|
+
}
|
|
499
|
+
if (!isTrustedSettingsRequest(req)) {
|
|
500
|
+
writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } })
|
|
501
|
+
return
|
|
502
|
+
}
|
|
503
|
+
let payload
|
|
504
|
+
try { payload = JSON.parse((await readBody(req, 8 * 1024)).toString('utf8') || '{}') } catch {
|
|
505
|
+
writeJson(res, 400, { ok: false, error: { code: 'json', message: 'invalid json' } })
|
|
506
|
+
return
|
|
507
|
+
}
|
|
508
|
+
const provider = payload.provider
|
|
509
|
+
if (!isProvider(provider)) {
|
|
510
|
+
writeJson(res, 200, { ok: false, provider, error: { code: 'provider', message: 'unknown provider' } })
|
|
511
|
+
return
|
|
512
|
+
}
|
|
513
|
+
const ref = oauthRef(provider, payload.index)
|
|
514
|
+
const info = await store.describeRef(ref)
|
|
515
|
+
if (!info.configured) {
|
|
516
|
+
writeJson(res, 200, { ok: false, provider, index: payload.index, ref, error: { code: 'not_connected', message: 'not connected' } })
|
|
517
|
+
return
|
|
518
|
+
}
|
|
519
|
+
let blob
|
|
520
|
+
try { blob = await store.loadBlob(ref) } catch (e) {
|
|
521
|
+
writeJson(res, 200, { ok: false, provider, index: payload.index, ref, error: { code: 'auth', message: String(e && e.message || e) } })
|
|
522
|
+
return
|
|
523
|
+
}
|
|
524
|
+
try { blob = await store.ensureFresh(provider, blob, ref) } catch (e) {
|
|
525
|
+
writeJson(res, 200, {
|
|
526
|
+
ok: false, provider, index: payload.index, ref,
|
|
527
|
+
email: blob.email || '', label: blob.label || '', expiresAt: blob.expiresAt || null,
|
|
528
|
+
quota: info.quota || null,
|
|
529
|
+
error: { code: 'refresh', message: String(e && e.message || e) },
|
|
530
|
+
})
|
|
531
|
+
return
|
|
532
|
+
}
|
|
533
|
+
const vendor = getVendor(provider)
|
|
534
|
+
if (typeof vendor.check !== 'function') {
|
|
535
|
+
writeJson(res, 200, { ok: true, provider, index: payload.index, ref, email: blob.email || '', label: blob.label || '', expiresAt: blob.expiresAt || null, quota: info.quota || null })
|
|
536
|
+
return
|
|
537
|
+
}
|
|
538
|
+
let capturedQuota = null
|
|
539
|
+
const probeFetch = async (url, init) => {
|
|
540
|
+
const res2 = await fetch(url, init)
|
|
541
|
+
try {
|
|
542
|
+
const snap = quotaSnapshot(provider, res2.headers, null, Date.now())
|
|
543
|
+
if (snap) { capturedQuota = snap; store.rememberQuota(ref, snap) }
|
|
544
|
+
} catch {}
|
|
545
|
+
return res2
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
await vendor.check(blob, vendorConfig(provider, live()), probeFetch)
|
|
549
|
+
writeJson(res, 200, { ok: true, provider, index: payload.index, ref, email: blob.email || '', label: blob.label || '', expiresAt: blob.expiresAt || null, quota: capturedQuota || info.quota || null, usagePercent: info.usagePercent ?? null })
|
|
550
|
+
} catch (e) {
|
|
551
|
+
writeJson(res, 200, {
|
|
552
|
+
ok: false, provider, index: payload.index, ref,
|
|
553
|
+
email: blob.email || '', label: blob.label || '', expiresAt: blob.expiresAt || null,
|
|
554
|
+
quota: capturedQuota || info.quota || null,
|
|
555
|
+
error: { code: e && e.code ? e.code : 'VENDOR', message: String(e && e.message || e).slice(0, 300) },
|
|
556
|
+
})
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
}), 'dsh-subscriptions: /check')
|
|
560
|
+
|
|
490
561
|
ctx.effect(() => ctx.webServer.register({
|
|
491
562
|
kind: 'exact',
|
|
492
563
|
path: '/dsh-subscriptions/logout',
|
package/package.json
CHANGED