@goodandready/dsh-subscriptions 0.5.1 → 0.5.3
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 +60 -14
- package/lib/mask.js +19 -0
- package/lib/plan.js +42 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -32,7 +32,8 @@ window.__ModuleLoader__.load({
|
|
|
32
32
|
'.dsub-mini{appearance:none;font:inherit;font-size:12px;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:3px 8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}' +
|
|
33
33
|
'.dsub-mini:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}' +
|
|
34
34
|
'.dsub-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
|
|
35
|
-
'.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}' +
|
|
35
|
+
'.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;word-break:break-word;max-width:100%}' +
|
|
36
|
+
'.dsub-hint{overflow-wrap:anywhere;word-break:break-word;max-width:100%}' +
|
|
36
37
|
'.dsub-btn{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:5px 12px;font-size:12.5px;font-weight:500;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}' +
|
|
37
38
|
'.dsub-btn:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}' +
|
|
38
39
|
'.dsub-inp{height:30px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 8px;font-size:12px;min-width:180px}' +
|
|
@@ -83,6 +84,8 @@ window.__ModuleLoader__.load({
|
|
|
83
84
|
'.dsub-brandOllama{background:rgba(107,114,128,.15);color:#9ca3af;border:1px solid rgba(107,114,128,.3)}' +
|
|
84
85
|
'.dsub-brandKimi{background:rgba(236,72,153,.15);color:#f472b6;border:1px solid rgba(236,72,153,.3)}' +
|
|
85
86
|
'.dsub-brandGlm{background:rgba(20,184,166,.15);color:#2dd4bf;border:1px solid rgba(20,184,166,.3)}' +
|
|
87
|
+
'.dsub-planBadge{display:inline-flex;align-items:center;padding:1px 6px;border-radius:4px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;background:rgba(99,102,241,.15);color:#818cf8;border:1px solid rgba(99,102,241,.3);margin-left:6px}' +
|
|
88
|
+
|
|
86
89
|
'.dsub-accInfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}' +
|
|
87
90
|
'.dsub-accNameRow{display:flex;align-items:center;justify-content:space-between;gap:8px}' +
|
|
88
91
|
'.dsub-accName{font-size:13px;font-weight:600}' +
|
|
@@ -322,7 +325,49 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
322
325
|
}
|
|
323
326
|
|
|
324
327
|
// #51: live countdown to the quota window reset (account.quota.resetAt).
|
|
325
|
-
|
|
328
|
+
function cleanErrorMessage(raw) {
|
|
329
|
+
if (!raw) return ''
|
|
330
|
+
var text = typeof raw === 'string' ? raw : (raw.message || String(raw))
|
|
331
|
+
text = text.trim()
|
|
332
|
+
if (text.charAt(0) === '{' && text.charAt(text.length - 1) === '}') {
|
|
333
|
+
try {
|
|
334
|
+
var parsed = JSON.parse(text)
|
|
335
|
+
if (parsed.error && parsed.error.message) text = parsed.error.message
|
|
336
|
+
else if (parsed.message) text = parsed.message
|
|
337
|
+
else if (parsed.code) text = parsed.code
|
|
338
|
+
} catch (e) {}
|
|
339
|
+
}
|
|
340
|
+
var firstLine = text.split('\n')[0].trim()
|
|
341
|
+
if (firstLine.length > 160) return firstLine.slice(0, 157) + '...'
|
|
342
|
+
return firstLine
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function normalizePlanBadge(provider, plan) {
|
|
346
|
+
if (!plan && provider !== 'kimi' && provider !== 'glm') return null
|
|
347
|
+
var p = String(plan || '').toLowerCase().replace(/[^a-z0-9]/g, '')
|
|
348
|
+
var label = plan
|
|
349
|
+
if (provider === 'codex') {
|
|
350
|
+
if (p.indexOf('pro20') >= 0 || p === 'pro') label = 'Pro 20x'
|
|
351
|
+
else if (p.indexOf('pro5') >= 0 || p.indexOf('prolite') >= 0) label = 'Pro 5x'
|
|
352
|
+
else if (p.indexOf('team') >= 0) label = 'Team'
|
|
353
|
+
else if (p.indexOf('plus') >= 0) label = 'Plus'
|
|
354
|
+
else if (p.indexOf('enterp') >= 0) label = 'Enterprise'
|
|
355
|
+
} else if (provider === 'grok') {
|
|
356
|
+
if (p.indexOf('super') >= 0) label = 'SuperGrok'
|
|
357
|
+
else if (p.indexOf('plus') >= 0) label = 'X Premium+'
|
|
358
|
+
else if (p.indexOf('premium') >= 0) label = 'X Premium'
|
|
359
|
+
} else if (provider === 'antigravity') {
|
|
360
|
+
if (p.indexOf('ultra') >= 0) label = 'Ultra'
|
|
361
|
+
else if (p.indexOf('pro') >= 0) label = 'Pro'
|
|
362
|
+
} else if (provider === 'kimi') {
|
|
363
|
+
label = 'Coding Plan'
|
|
364
|
+
} else if (provider === 'glm') {
|
|
365
|
+
label = '150% Boost'
|
|
366
|
+
}
|
|
367
|
+
return label ? React.createElement('span', { className: 'dsub-planBadge' }, label) : null
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function formatRelativeReset(resetAt, lang, now) {
|
|
326
371
|
if (!resetAt || !Number.isFinite(resetAt) || resetAt <= 0) return ''
|
|
327
372
|
var delta = resetAt - (now || Date.now())
|
|
328
373
|
var isRu = lang !== 'en'
|
|
@@ -596,7 +641,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
596
641
|
})
|
|
597
642
|
const data = await res.json().catch(() => ({}))
|
|
598
643
|
setProxyRes((m) => Object.assign({}, m, { [key]: data }))
|
|
599
|
-
} catch (e) { setErr(
|
|
644
|
+
} catch (e) { setErr(cleanErrorMessage(e.message || e)) }
|
|
600
645
|
setChecking((c) => Object.assign({}, c, { ['proxy:' + key]: false }))
|
|
601
646
|
}
|
|
602
647
|
|
|
@@ -616,7 +661,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
616
661
|
if (data && data.quota) {
|
|
617
662
|
setAccounts((prev) => prev.map((a) => a.provider===provider && a.index===index ? Object.assign({}, a, { quota: data.quota }) : a))
|
|
618
663
|
}
|
|
619
|
-
} catch (e) { setErr(
|
|
664
|
+
} catch (e) { setErr(cleanErrorMessage(e.message || e)) }
|
|
620
665
|
setChecking((c) => Object.assign({}, c, { [key]: false }))
|
|
621
666
|
}
|
|
622
667
|
|
|
@@ -737,23 +782,24 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
737
782
|
},
|
|
738
783
|
}),
|
|
739
784
|
React.createElement('span', { className: 'dsub-badge' + (account.validationUrl ? ' dsub-badge-warn' : (on ? ' dsub-badge-on' : '')) }, badgeFor(account, t)),
|
|
785
|
+
normalizePlanBadge(row.slot.provider, account.plan || (account.quota && account.quota.plan)),
|
|
740
786
|
React.createElement('button', {
|
|
741
787
|
type: 'button', className: 'dsub-mini',
|
|
742
|
-
onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
788
|
+
onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
743
789
|
}, on ? t('reconnect') : t('connect')),
|
|
744
790
|
(row.slot.provider === 'codex' ? React.createElement('button', {
|
|
745
791
|
type: 'button', className: 'dsub-mini',
|
|
746
|
-
onClick: () => deviceStartLogin(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
792
|
+
onClick: () => deviceStartLogin(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
747
793
|
}, t('deviceLogin')) : null),
|
|
748
794
|
React.createElement('button', {
|
|
749
795
|
type: 'button', className: 'dsub-mini',
|
|
750
796
|
disabled: !on,
|
|
751
|
-
onClick: () => logout(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
797
|
+
onClick: () => logout(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
752
798
|
}, t('disconnect')),
|
|
753
799
|
React.createElement('button', {
|
|
754
800
|
type: 'button', className: 'dsub-mini',
|
|
755
801
|
disabled: checking[key],
|
|
756
|
-
onClick: () => doCheck(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
802
|
+
onClick: () => doCheck(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
757
803
|
}, checking[key] ? t('checking') : t('check')),
|
|
758
804
|
React.createElement('button', {
|
|
759
805
|
type: 'button', className: 'dsub-mini', title: t('removeSlot'),
|
|
@@ -761,7 +807,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
761
807
|
const slot = row.slot
|
|
762
808
|
Promise.resolve(on ? logout(slot.provider, slot.index) : null)
|
|
763
809
|
.then(() => setSlots(slots.filter((_, k) => k !== row.i)))
|
|
764
|
-
.catch((e) => setErr(
|
|
810
|
+
.catch((e) => setErr(cleanErrorMessage(e.message || e)))
|
|
765
811
|
},
|
|
766
812
|
}, '\u00d7'),
|
|
767
813
|
),
|
|
@@ -776,7 +822,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
776
822
|
}),
|
|
777
823
|
React.createElement('button', {
|
|
778
824
|
type: 'button', className: 'dsub-mini',
|
|
779
|
-
onClick: () => complete(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
825
|
+
onClick: () => complete(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
780
826
|
}, t('submitCode')),
|
|
781
827
|
),
|
|
782
828
|
React.createElement('div', { className: 'dsub-row' },
|
|
@@ -788,12 +834,12 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
788
834
|
}),
|
|
789
835
|
React.createElement('button', {
|
|
790
836
|
type: 'button', className: 'dsub-mini',
|
|
791
|
-
onClick: () => importToken(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
837
|
+
onClick: () => importToken(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
792
838
|
}, t('importToken')),
|
|
793
839
|
React.createElement('button', {
|
|
794
840
|
type: 'button', className: 'dsub-mini',
|
|
795
841
|
title: t('importLocalCli'),
|
|
796
|
-
onClick: () => importLocalCli(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
842
|
+
onClick: () => importLocalCli(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
797
843
|
}, '📥 CLI'),
|
|
798
844
|
),
|
|
799
845
|
React.createElement('div', { className: 'dsub-row' },
|
|
@@ -810,7 +856,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
810
856
|
React.createElement('button', {
|
|
811
857
|
type: 'button', className: 'dsub-mini',
|
|
812
858
|
disabled: checking['proxy:' + key],
|
|
813
|
-
onClick: () => doProxyCheck(row.slot.provider, row.slot.index).catch((e) => setErr(
|
|
859
|
+
onClick: () => doProxyCheck(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
814
860
|
}, checking['proxy:' + key] ? '\u2026' : t('proxyCheck')),
|
|
815
861
|
),
|
|
816
862
|
(function(){
|
|
@@ -956,7 +1002,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
956
1002
|
React.createElement('div', { className: 'dsub-foot' },
|
|
957
1003
|
React.createElement('button', {
|
|
958
1004
|
type: 'button', className: 'dsub-save',
|
|
959
|
-
onClick: () => save().catch((e) => setErr(
|
|
1005
|
+
onClick: () => save().catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
960
1006
|
}, t('save')),
|
|
961
1007
|
saved ? React.createElement('span', { className: 'dsub-ok' }, t('saved')) : null,
|
|
962
1008
|
err ? React.createElement('span', { className: 'dsub-bad' }, err) : null,
|
package/lib/mask.js
CHANGED
|
@@ -19,3 +19,22 @@ const EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g
|
|
|
19
19
|
export function maskText(value) {
|
|
20
20
|
return String(value || '').replace(EMAIL_RE, (m) => maskEmail(m))
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export function cleanErrorMessage(raw) {
|
|
24
|
+
if (!raw) return ''
|
|
25
|
+
let text = typeof raw === 'string' ? raw : (raw.message || String(raw))
|
|
26
|
+
text = text.trim()
|
|
27
|
+
if (text.startsWith('{') && text.endsWith('}')) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(text)
|
|
30
|
+
if (parsed.error && parsed.error.message) text = parsed.error.message
|
|
31
|
+
else if (parsed.message) text = parsed.message
|
|
32
|
+
else if (parsed.code) text = parsed.code
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
35
|
+
const firstLine = text.split('\n')[0].trim()
|
|
36
|
+
if (firstLine.length > 160) {
|
|
37
|
+
return firstLine.slice(0, 157) + '...'
|
|
38
|
+
}
|
|
39
|
+
return firstLine
|
|
40
|
+
}
|
package/lib/plan.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize and pretty-print subscription plans.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export function normalizePlanName(provider, rawPlan) {
|
|
6
|
+
if (!rawPlan || typeof rawPlan !== 'string') {
|
|
7
|
+
if (provider === 'kimi') return 'Coding Plan'
|
|
8
|
+
if (provider === 'glm') return 'Coding Plan 150%'
|
|
9
|
+
return ''
|
|
10
|
+
}
|
|
11
|
+
const key = rawPlan.trim().toLowerCase().replace(/[^a-z0-9]/g, '')
|
|
12
|
+
if (provider === 'codex') {
|
|
13
|
+
if (key.includes('pro20') || key === 'pro') return 'Pro 20x'
|
|
14
|
+
if (key.includes('pro5') || key.includes('prolite')) return 'Pro 5x'
|
|
15
|
+
if (key.includes('team')) return 'Team'
|
|
16
|
+
if (key.includes('plus')) return 'Plus'
|
|
17
|
+
if (key.includes('enterp')) return 'Enterprise'
|
|
18
|
+
if (key.includes('edu')) return 'Edu'
|
|
19
|
+
if (key.includes('free')) return 'Free'
|
|
20
|
+
}
|
|
21
|
+
if (provider === 'grok') {
|
|
22
|
+
if (key.includes('super')) return 'SuperGrok'
|
|
23
|
+
if (key.includes('plus') || key.includes('premiumplus')) return 'X Premium+'
|
|
24
|
+
if (key.includes('premium')) return 'X Premium'
|
|
25
|
+
if (key.includes('basic')) return 'X Basic'
|
|
26
|
+
if (key.includes('free')) return 'Free'
|
|
27
|
+
}
|
|
28
|
+
if (provider === 'claude') {
|
|
29
|
+
if (key.includes('team')) return 'Team'
|
|
30
|
+
if (key.includes('enterp')) return 'Enterprise'
|
|
31
|
+
if (key.includes('pro')) return 'Pro'
|
|
32
|
+
if (key.includes('free')) return 'Free'
|
|
33
|
+
}
|
|
34
|
+
if (provider === 'antigravity') {
|
|
35
|
+
if (key.includes('ultra')) return 'Ultra'
|
|
36
|
+
if (key.includes('pro')) return 'Pro'
|
|
37
|
+
if (key.includes('free')) return 'Free'
|
|
38
|
+
}
|
|
39
|
+
if (provider === 'kimi') return 'Coding Plan'
|
|
40
|
+
if (provider === 'glm') return 'Coding Plan 150%'
|
|
41
|
+
return rawPlan
|
|
42
|
+
}
|
package/package.json
CHANGED