Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 008cdf8d27 | |||
| f6e8b2f2f0 | |||
| 3713ad399f | |||
| 987b073b79 | |||
| 815709ceab | |||
| 4b36e625bb | |||
| 1d8fed03bc | |||
| 05284a6584 | |||
| 3a8d1e229d | |||
| 8743a49c51 | |||
| e76fd17e34 | |||
| a62962ea5e | |||
| e9c6a8461c | |||
| 6d0c5078e9 | |||
| 51c29ba36a | |||
| dcf1e774d2 | |||
| 898503a554 | |||
| 67eaf1baa7 | |||
| 009e238c30 | |||
| 5ac8c3d653 | |||
| 89978efda3 | |||
| ce76e81b84 | |||
| 1c913cad2d | |||
| 4cfdd287e2 | |||
| 71524bb17b | |||
| bf7dbc342d | |||
| f4beacb744 | |||
| a6985a28ea | |||
| cc1cda8bf6 | |||
| d9ad3c2956 |
@@ -64,6 +64,9 @@ jobs:
|
||||
echo "${{ secrets.ENV_TOKEN }}" > .env
|
||||
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
|
||||
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
|
||||
echo "EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY=${{ secrets.EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY }}" >> .env
|
||||
echo "EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY=${{ secrets.EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY }}" >> .env
|
||||
echo "EXPO_PUBLIC_BSKY_PURCHASES_API=${{ secrets.EXPO_PUBLIC_BSKY_PURCHASES_API }}" >> .env
|
||||
echo "$json" > google-services.json
|
||||
|
||||
- name: 🏗️ EAS Build
|
||||
|
||||
@@ -76,6 +76,9 @@ jobs:
|
||||
echo "${{ secrets.ENV_TOKEN }}" > .env
|
||||
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
|
||||
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
|
||||
echo "EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY=${{ secrets.EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY }}" >> .env
|
||||
echo "EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY=${{ secrets.EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY }}" >> .env
|
||||
echo "EXPO_PUBLIC_BSKY_PURCHASES_API=${{ secrets.EXPO_PUBLIC_BSKY_PURCHASES_API }}" >> .env
|
||||
echo "${{ secrets.GOOGLE_SERVICES_TOKEN }}" > google-services.json
|
||||
|
||||
- name: 🏗️ EAS Build
|
||||
|
||||
@@ -101,6 +101,9 @@ jobs:
|
||||
echo "${{ secrets.ENV_TOKEN }}" > .env
|
||||
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
|
||||
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
|
||||
echo "EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY=${{ secrets.EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY }}" >> .env
|
||||
echo "EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY=${{ secrets.EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY }}" >> .env
|
||||
echo "EXPO_PUBLIC_BSKY_PURCHASES_API=${{ secrets.EXPO_PUBLIC_BSKY_PURCHASES_API }}" >> .env
|
||||
echo "$json" > google-services.json
|
||||
|
||||
- name: 🏗️ Create Bundle
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M6 4.667A2.667 2.667 0 0 1 8.667 2c1.34 0 2.538.608 3.333 1.564A4.32 4.32 0 0 1 15.333 2 2.667 2.667 0 0 1 18 4.667c0 .859-.25 1.66-.681 2.333H20a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-7V7h.667A2.333 2.333 0 0 0 16 4.667.667.667 0 0 0 15.333 4 2.333 2.333 0 0 0 13 6.333V7h-2v-.667A2.333 2.333 0 0 0 8.667 4 .667.667 0 0 0 8 4.667 2.333 2.333 0 0 0 10.333 7H11v4H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h2.681A4.3 4.3 0 0 1 6 4.667ZM11 13H4v7a1 1 0 0 0 1 1h6v-8Zm9 0h-7v8h6a1 1 0 0 0 1-1v-7Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 617 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M6 4.667A2.667 2.667 0 0 1 8.667 2c1.34 0 2.538.608 3.333 1.564A4.32 4.32 0 0 1 15.333 2 2.667 2.667 0 0 1 18 4.667c0 .859-.25 1.66-.681 2.333H20a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1v7a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-7a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h2.681A4.3 4.3 0 0 1 6 4.667ZM10.333 7H11v-.667A2.333 2.333 0 0 0 8.667 4 .667.667 0 0 0 8 4.667 2.333 2.333 0 0 0 10.333 7ZM13 6.333V7h.667A2.333 2.333 0 0 0 16 4.667.667.667 0 0 0 15.333 4 2.333 2.333 0 0 0 13 6.333ZM11 9H5v2h6V9Zm2 2V9h6v2h-6Zm-2 2H6v6h5v-6Zm2 6v-6h5v6h-5Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 659 B |
@@ -294,6 +294,9 @@ func serve(cctx *cli.Context) error {
|
||||
e.GET("/starter-pack-short/:code", server.WebGeneric)
|
||||
e.GET("/start/:handleOrDID/:rkey", server.WebStarterPack)
|
||||
|
||||
// subscription
|
||||
e.GET("/subscriptions", server.WebGeneric)
|
||||
|
||||
// ipcc
|
||||
e.GET("/ipcc", server.WebIpCC)
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
"react-native-pager-view": "6.2.3",
|
||||
"react-native-picker-select": "^9.1.3",
|
||||
"react-native-progress": "bluesky-social/react-native-progress",
|
||||
"react-native-purchases": "^8.2.3",
|
||||
"react-native-qrcode-styled": "^0.3.1",
|
||||
"react-native-reanimated": "^3.11.0",
|
||||
"react-native-root-siblings": "^4.1.1",
|
||||
|
||||
@@ -6,6 +6,16 @@ module.exports = function withAndroidManifestPlugin(appConfig) {
|
||||
decoratedAppConfig.modResults.manifest.application[0].$[
|
||||
'android:largeHeap'
|
||||
] = 'true'
|
||||
decoratedAppConfig.modResults.manifest['uses-permission'] =
|
||||
decoratedAppConfig.modResults.manifest['uses-permission'] || []
|
||||
/**
|
||||
* @see https://www.revenuecat.com/docs/getting-started/installation/reactnative#import-purchases
|
||||
*/
|
||||
decoratedAppConfig.modResults.manifest['uses-permission'].push({
|
||||
$: {
|
||||
'android:name': 'com.android.vending.BILLING',
|
||||
},
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(`withAndroidManifestPlugin failed`, e)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import '#/view/icons'
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
||||
import {KeyboardProvider} from 'react-native-keyboard-controller'
|
||||
import Purchases from 'react-native-purchases'
|
||||
import {RootSiblingParent} from 'react-native-root-siblings'
|
||||
import {
|
||||
initialWindowMetrics,
|
||||
@@ -24,6 +25,7 @@ import {s} from '#/lib/styles'
|
||||
import {ThemeProvider} from '#/lib/ThemeContext'
|
||||
import I18nProvider from '#/locale/i18nProvider'
|
||||
import {logger} from '#/logger'
|
||||
import {isAndroid, isIOS} from '#/platform/detection'
|
||||
import {Provider as A11yProvider} from '#/state/a11y'
|
||||
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
||||
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
||||
@@ -66,6 +68,7 @@ import {NuxDialogs} from '#/components/dialogs/nuxs'
|
||||
import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
|
||||
import {Provider as IntentDialogProvider} from '#/components/intents/IntentDialogs'
|
||||
import {Provider as PortalProvider} from '#/components/Portal'
|
||||
import {RC_APPLE_PUBLIC_KEY,RC_GOOGLE_PUBLIC_KEY} from '#/env'
|
||||
import {Splash} from '#/Splash'
|
||||
import {BottomSheetProvider} from '../modules/bottom-sheet'
|
||||
import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
||||
@@ -173,6 +176,14 @@ function App() {
|
||||
Promise.all([initPersistedState(), ensureGeolocationResolved()]).then(() =>
|
||||
setReady(true),
|
||||
)
|
||||
|
||||
Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG)
|
||||
|
||||
if (isIOS) {
|
||||
Purchases.configure({apiKey: RC_APPLE_PUBLIC_KEY})
|
||||
} else if (isAndroid) {
|
||||
Purchases.configure({apiKey: RC_GOOGLE_PUBLIC_KEY})
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (!isReady) {
|
||||
|
||||
@@ -92,6 +92,7 @@ import {
|
||||
StarterPackScreenShort,
|
||||
} from '#/screens/StarterPack/StarterPackScreen'
|
||||
import {Wizard} from '#/screens/StarterPack/Wizard'
|
||||
import {Subscriptions} from '#/screens/Subscriptions'
|
||||
import {useTheme} from '#/alf'
|
||||
import {router} from '#/routes'
|
||||
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
||||
@@ -407,6 +408,11 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
|
||||
getComponent={() => Wizard}
|
||||
options={{title: title(msg`Edit your starter pack`), requireAuth: true}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="Subscriptions"
|
||||
getComponent={() => Subscriptions}
|
||||
options={{title: title(msg`Subscriptions`), requireAuth: true}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ const GroupContext = React.createContext<{
|
||||
disabled: boolean
|
||||
type: 'radio' | 'checkbox'
|
||||
maxSelectionsReached: boolean
|
||||
setFieldValue: (props: {name: string; value: boolean}) => void
|
||||
setFieldValue: (props: {name: any; value: boolean}) => void
|
||||
}>({
|
||||
type: 'checkbox',
|
||||
values: [],
|
||||
@@ -50,12 +50,12 @@ const GroupContext = React.createContext<{
|
||||
setFieldValue: () => {},
|
||||
})
|
||||
|
||||
export type GroupProps = React.PropsWithChildren<{
|
||||
export type GroupProps<V> = React.PropsWithChildren<{
|
||||
type?: 'radio' | 'checkbox'
|
||||
values: string[]
|
||||
values: V[]
|
||||
maxSelections?: number
|
||||
disabled?: boolean
|
||||
onChange: (value: string[]) => void
|
||||
onChange: (value: V[]) => void
|
||||
label: string
|
||||
}>
|
||||
|
||||
@@ -74,7 +74,7 @@ export function useItemContext() {
|
||||
return React.useContext(ItemContext)
|
||||
}
|
||||
|
||||
export function Group({
|
||||
export function Group<V extends string>({
|
||||
children,
|
||||
values: providedValues,
|
||||
onChange,
|
||||
@@ -82,13 +82,13 @@ export function Group({
|
||||
type = 'checkbox',
|
||||
maxSelections,
|
||||
label,
|
||||
}: GroupProps) {
|
||||
}: GroupProps<V>) {
|
||||
const groupRole = type === 'radio' ? 'radiogroup' : undefined
|
||||
const values = type === 'radio' ? providedValues.slice(0, 1) : providedValues
|
||||
const [maxReached, setMaxReached] = React.useState(false)
|
||||
|
||||
const setFieldValue = React.useCallback<
|
||||
(props: {name: string; value: boolean}) => void
|
||||
(props: {name: V; value: boolean}) => void
|
||||
>(
|
||||
({name, value}) => {
|
||||
if (type === 'checkbox') {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import {createSinglePathSVG} from './TEMPLATE'
|
||||
|
||||
export const Gift1_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M6 4.667A2.667 2.667 0 0 1 8.667 2c1.34 0 2.538.608 3.333 1.564A4.324 4.324 0 0 1 15.333 2 2.667 2.667 0 0 1 18 4.667c0 .859-.25 1.66-.681 2.333H20a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1v7a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-7a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h2.681A4.313 4.313 0 0 1 6 4.667ZM10.333 7H11v-.667A2.333 2.333 0 0 0 8.667 4 .667.667 0 0 0 8 4.667 2.333 2.333 0 0 0 10.333 7ZM13 6.333V7h.667A2.333 2.333 0 0 0 16 4.667.667.667 0 0 0 15.333 4 2.333 2.333 0 0 0 13 6.333ZM11 9H5v2h6V9Zm2 2V9h6v2h-6Zm-2 2H6v6h5v-6Zm2 6v-6h5v6h-5Z',
|
||||
})
|
||||
|
||||
export const Gift1_Filled_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M6 4.667A2.667 2.667 0 0 1 8.667 2c1.34 0 2.538.608 3.333 1.564A4.324 4.324 0 0 1 15.333 2 2.667 2.667 0 0 1 18 4.667c0 .859-.25 1.66-.681 2.333H20a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-7V7h.667A2.333 2.333 0 0 0 16 4.667.667.667 0 0 0 15.333 4 2.333 2.333 0 0 0 13 6.333V7h-2v-.667A2.333 2.333 0 0 0 8.667 4 .667.667 0 0 0 8 4.667 2.333 2.333 0 0 0 10.333 7H11v4H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h2.681A4.313 4.313 0 0 1 6 4.667ZM11 13H4v7a1 1 0 0 0 1 1h6v-8Zm9 0h-7v8h6a1 1 0 0 0 1-1v-7Z',
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {msg} from '@lingui/macro'
|
||||
|
||||
import {TierId} from '#/state/purchases/subscriptions/types'
|
||||
|
||||
export function useMainSubscriptionTiersCopy() {
|
||||
const {_} = useLingui()
|
||||
|
||||
return {
|
||||
[TierId.Main0]: {
|
||||
title: _(msg`Bluesky Supporter`),
|
||||
},
|
||||
[TierId.Main1]: {
|
||||
title: _(msg`Bluesky Friend`),
|
||||
},
|
||||
[TierId.Main2]: {
|
||||
title: _(msg`Bluesky Besty`),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -7,3 +7,10 @@ export const LOG_LEVEL = (process.env.EXPO_PUBLIC_LOG_LEVEL || 'info') as
|
||||
| 'info'
|
||||
| 'warn'
|
||||
| 'error'
|
||||
|
||||
export const RC_GOOGLE_PUBLIC_KEY =
|
||||
process.env.EXPO_PUBLIC_RC_GOOGLE_PUBLIC_KEY || ''
|
||||
export const RC_APPLE_PUBLIC_KEY =
|
||||
process.env.EXPO_PUBLIC_RC_APPLE_PUBLIC_KEY || ''
|
||||
export const BSKY_PURCHASES_API =
|
||||
process.env.EXPO_PUBLIC_BSKY_PURCHASES_API || ''
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
import React from 'react'
|
||||
|
||||
import {deviceLocales} from '#/locale/deviceLocales'
|
||||
import {useGeolocation} from '#/state/geolocation'
|
||||
import {useLanguagePrefs} from '#/state/preferences'
|
||||
|
||||
/**
|
||||
* From react-native-localize
|
||||
*
|
||||
* MIT License
|
||||
* Copyright (c) 2017-present, Mathieu Acthernoene
|
||||
*
|
||||
* @see https://github.com/zoontek/react-native-localize/blob/master/LICENSE
|
||||
* @see https://github.com/zoontek/react-native-localize/blob/ee5bf25e0bb8f3b8e4f3fd055f67ad46269c81ea/src/constants.ts
|
||||
*/
|
||||
export const countryCodeToCurrency: Record<string, string> = {
|
||||
ad: 'eur',
|
||||
ae: 'aed',
|
||||
af: 'afn',
|
||||
ag: 'xcd',
|
||||
ai: 'xcd',
|
||||
al: 'all',
|
||||
am: 'amd',
|
||||
an: 'ang',
|
||||
ao: 'aoa',
|
||||
ar: 'ars',
|
||||
as: 'usd',
|
||||
at: 'eur',
|
||||
au: 'aud',
|
||||
aw: 'awg',
|
||||
ax: 'eur',
|
||||
az: 'azn',
|
||||
ba: 'bam',
|
||||
bb: 'bbd',
|
||||
bd: 'bdt',
|
||||
be: 'eur',
|
||||
bf: 'xof',
|
||||
bg: 'bgn',
|
||||
bh: 'bhd',
|
||||
bi: 'bif',
|
||||
bj: 'xof',
|
||||
bl: 'eur',
|
||||
bm: 'bmd',
|
||||
bn: 'bnd',
|
||||
bo: 'bob',
|
||||
bq: 'usd',
|
||||
br: 'brl',
|
||||
bs: 'bsd',
|
||||
bt: 'btn',
|
||||
bv: 'nok',
|
||||
bw: 'bwp',
|
||||
by: 'byn',
|
||||
bz: 'bzd',
|
||||
ca: 'cad',
|
||||
cc: 'aud',
|
||||
cd: 'cdf',
|
||||
cf: 'xaf',
|
||||
cg: 'xaf',
|
||||
ch: 'chf',
|
||||
ci: 'xof',
|
||||
ck: 'nzd',
|
||||
cl: 'clp',
|
||||
cm: 'xaf',
|
||||
cn: 'cny',
|
||||
co: 'cop',
|
||||
cr: 'crc',
|
||||
cu: 'cup',
|
||||
cv: 'cve',
|
||||
cw: 'ang',
|
||||
cx: 'aud',
|
||||
cy: 'eur',
|
||||
cz: 'czk',
|
||||
de: 'eur',
|
||||
dj: 'djf',
|
||||
dk: 'dkk',
|
||||
dm: 'xcd',
|
||||
do: 'dop',
|
||||
dz: 'dzd',
|
||||
ec: 'usd',
|
||||
ee: 'eur',
|
||||
eg: 'egp',
|
||||
eh: 'mad',
|
||||
er: 'ern',
|
||||
es: 'eur',
|
||||
et: 'etb',
|
||||
fi: 'eur',
|
||||
fj: 'fjd',
|
||||
fk: 'fkp',
|
||||
fm: 'usd',
|
||||
fo: 'dkk',
|
||||
fr: 'eur',
|
||||
ga: 'xaf',
|
||||
gb: 'gbp',
|
||||
gd: 'xcd',
|
||||
ge: 'gel',
|
||||
gf: 'eur',
|
||||
gg: 'gbp',
|
||||
gh: 'ghs',
|
||||
gi: 'gip',
|
||||
gl: 'dkk',
|
||||
gm: 'gmd',
|
||||
gn: 'gnf',
|
||||
gp: 'eur',
|
||||
gq: 'xaf',
|
||||
gr: 'eur',
|
||||
gs: 'gbp',
|
||||
gt: 'gtq',
|
||||
gu: 'usd',
|
||||
gw: 'xof',
|
||||
gy: 'gyd',
|
||||
hk: 'hkd',
|
||||
hm: 'aud',
|
||||
hn: 'hnl',
|
||||
hr: 'hrk',
|
||||
ht: 'htg',
|
||||
hu: 'huf',
|
||||
id: 'idr',
|
||||
ie: 'eur',
|
||||
il: 'ils',
|
||||
im: 'gbp',
|
||||
in: 'inr',
|
||||
io: 'usd',
|
||||
iq: 'iqd',
|
||||
ir: 'irr',
|
||||
is: 'isk',
|
||||
it: 'eur',
|
||||
je: 'gbp',
|
||||
jm: 'jmd',
|
||||
jo: 'jod',
|
||||
jp: 'jpy',
|
||||
ke: 'kes',
|
||||
kg: 'kgs',
|
||||
kh: 'khr',
|
||||
ki: 'aud',
|
||||
km: 'kmf',
|
||||
kn: 'xcd',
|
||||
kp: 'kpw',
|
||||
kr: 'krw',
|
||||
kw: 'kwd',
|
||||
ky: 'kyd',
|
||||
kz: 'kzt',
|
||||
la: 'lak',
|
||||
lb: 'lbp',
|
||||
lc: 'xcd',
|
||||
li: 'chf',
|
||||
lk: 'lkr',
|
||||
lr: 'lrd',
|
||||
ls: 'lsl',
|
||||
lt: 'eur',
|
||||
lu: 'eur',
|
||||
lv: 'eur',
|
||||
ly: 'lyd',
|
||||
ma: 'mad',
|
||||
mc: 'eur',
|
||||
md: 'mdl',
|
||||
me: 'eur',
|
||||
mf: 'eur',
|
||||
mg: 'mga',
|
||||
mh: 'usd',
|
||||
mk: 'mkd',
|
||||
ml: 'xof',
|
||||
mm: 'mmk',
|
||||
mn: 'mnt',
|
||||
mo: 'mop',
|
||||
mp: 'usd',
|
||||
mq: 'eur',
|
||||
mr: 'mro',
|
||||
ms: 'xcd',
|
||||
mt: 'eur',
|
||||
mu: 'mur',
|
||||
mv: 'mvr',
|
||||
mw: 'mwk',
|
||||
mx: 'mxn',
|
||||
my: 'myr',
|
||||
mz: 'mzn',
|
||||
na: 'nad',
|
||||
nc: 'xpf',
|
||||
ne: 'xof',
|
||||
nf: 'aud',
|
||||
ng: 'ngn',
|
||||
ni: 'nio',
|
||||
nl: 'eur',
|
||||
no: 'nok',
|
||||
np: 'npr',
|
||||
nr: 'aud',
|
||||
nu: 'nzd',
|
||||
nz: 'nzd',
|
||||
om: 'omr',
|
||||
pa: 'pab',
|
||||
pe: 'pen',
|
||||
pf: 'xpf',
|
||||
pg: 'pgk',
|
||||
ph: 'php',
|
||||
pk: 'pkr',
|
||||
pl: 'pln',
|
||||
pm: 'eur',
|
||||
pn: 'nzd',
|
||||
pr: 'usd',
|
||||
ps: 'ils',
|
||||
pt: 'eur',
|
||||
pw: 'usd',
|
||||
py: 'pyg',
|
||||
qa: 'qar',
|
||||
re: 'eur',
|
||||
ro: 'ron',
|
||||
rs: 'rsd',
|
||||
ru: 'rub',
|
||||
rw: 'rwf',
|
||||
sa: 'sar',
|
||||
sb: 'sbd',
|
||||
sc: 'scr',
|
||||
sd: 'sdg',
|
||||
se: 'sek',
|
||||
sg: 'sgd',
|
||||
sh: 'shp',
|
||||
si: 'eur',
|
||||
sj: 'nok',
|
||||
sk: 'eur',
|
||||
sl: 'sll',
|
||||
sm: 'eur',
|
||||
sn: 'xof',
|
||||
so: 'sos',
|
||||
sr: 'srd',
|
||||
ss: 'ssp',
|
||||
st: 'std',
|
||||
sv: 'svc',
|
||||
sx: 'ang',
|
||||
sy: 'syp',
|
||||
sz: 'szl',
|
||||
tc: 'usd',
|
||||
td: 'xaf',
|
||||
tf: 'eur',
|
||||
tg: 'xof',
|
||||
th: 'thb',
|
||||
tj: 'tjs',
|
||||
tk: 'nzd',
|
||||
tl: 'usd',
|
||||
tm: 'tmt',
|
||||
tn: 'tnd',
|
||||
to: 'top',
|
||||
tr: 'try',
|
||||
tt: 'ttd',
|
||||
tv: 'aud',
|
||||
tw: 'twd',
|
||||
tz: 'tzs',
|
||||
ua: 'uah',
|
||||
ug: 'ugx',
|
||||
um: 'usd',
|
||||
us: 'usd',
|
||||
uy: 'uyu',
|
||||
uz: 'uzs',
|
||||
va: 'eur',
|
||||
vc: 'xcd',
|
||||
ve: 'vef',
|
||||
vg: 'usd',
|
||||
vi: 'usd',
|
||||
vn: 'vnd',
|
||||
vu: 'vuv',
|
||||
wf: 'xpf',
|
||||
ws: 'wst',
|
||||
ye: 'yer',
|
||||
yt: 'eur',
|
||||
za: 'zar',
|
||||
zm: 'zmw',
|
||||
zw: 'zwl',
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-guess currency formatting.
|
||||
*
|
||||
* Attempts to use `getLocales` from `expo-localization` if available,
|
||||
* otherwise falls back to the `persisted.appLanguage` setting, and geolocation
|
||||
* API for region.
|
||||
*/
|
||||
export function useCurrencyFormatter(
|
||||
options?: Parameters<typeof Intl.NumberFormat>[1],
|
||||
) {
|
||||
const {geolocation} = useGeolocation()
|
||||
const {appLanguage} = useLanguagePrefs()
|
||||
return React.useMemo(() => {
|
||||
const locale = deviceLocales.at(0)
|
||||
const languageTag = locale?.languageTag || appLanguage || 'en-US'
|
||||
const countryCode = (
|
||||
locale?.regionCode ||
|
||||
geolocation?.countryCode ||
|
||||
'us'
|
||||
).toLowerCase()
|
||||
const currency = countryCodeToCurrency[countryCode]
|
||||
const format = new Intl.NumberFormat(languageTag, {
|
||||
...(options || {}),
|
||||
style: 'currency',
|
||||
currency: currency,
|
||||
}).format
|
||||
|
||||
return {
|
||||
format,
|
||||
currency,
|
||||
countryCode,
|
||||
languageTag,
|
||||
}
|
||||
}, [geolocation, appLanguage, options])
|
||||
}
|
||||
@@ -55,6 +55,7 @@ export type CommonNavigatorParams = {
|
||||
StarterPackShort: {code: string}
|
||||
StarterPackWizard: undefined
|
||||
StarterPackEdit: {rkey?: string}
|
||||
Subscriptions: undefined
|
||||
}
|
||||
|
||||
export type BottomTabNavigatorParams = CommonNavigatorParams & {
|
||||
|
||||
@@ -62,4 +62,5 @@ export const router = new Router({
|
||||
StarterPack: '/starter-pack/:name/:rkey',
|
||||
StarterPackShort: '/starter-pack-short/:code',
|
||||
StarterPackWizard: '/starter-pack/create',
|
||||
Subscriptions: '/subscriptions',
|
||||
})
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||
|
||||
import {isAndroid, isIOS} from '#/platform/detection'
|
||||
import {CommonNavigatorParams} from '#/lib/routes/types'
|
||||
import {
|
||||
useMainSubscriptions,
|
||||
usePurchaseSubscription,
|
||||
useChangeSubscription,
|
||||
useCancelSubscription,
|
||||
} from '#/state/purchases/subscriptions'
|
||||
// import {useEntitlements} from '#/state/purchases/subscriptions/useEntitlements'
|
||||
import {
|
||||
SubscriptionTier,
|
||||
Subscription,
|
||||
SubscriptionId,
|
||||
TierId,
|
||||
} from '#/state/purchases/subscriptions/types'
|
||||
import {ViewHeader} from '#/view/com/util/ViewHeader'
|
||||
import {CenteredView} from '#/view/com/util/Views'
|
||||
import {atoms as a, useTheme, useBreakpoints, tokens} from '#/alf'
|
||||
import {Button, ButtonText, ButtonIcon} from '#/components/Button'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useMainSubscriptionTiersCopy} from '#/components/subscriptions/localization'
|
||||
import {GradientFill} from '#/components/GradientFill'
|
||||
import {Divider} from '#/components/Divider'
|
||||
import {CheckThick_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import * as Toggle from '#/components/forms/Toggle'
|
||||
import {Admonition} from '#/components/Admonition'
|
||||
|
||||
export type ScreenProps = NativeStackScreenProps<
|
||||
CommonNavigatorParams,
|
||||
'Subscriptions'
|
||||
>
|
||||
|
||||
export function Subscriptions(_props: ScreenProps) {
|
||||
const {_} = useLingui()
|
||||
|
||||
// const {data: entitlements} = useEntitlements()
|
||||
const {data: subscriptions, isError} = useMainSubscriptions()
|
||||
const activeSubscription = React.useMemo(() => {
|
||||
if (!subscriptions) return
|
||||
for (const sub of subscriptions) {
|
||||
if (sub.monthly.subscription.state?.active) {
|
||||
return sub.monthly
|
||||
} else if (sub.annual.subscription.state?.active) {
|
||||
return sub.annual
|
||||
}
|
||||
}
|
||||
}, [subscriptions])
|
||||
const currentPlatform = isAndroid ? 'android' : isIOS ? 'ios' : 'web'
|
||||
const activeSubscriptionPlatform =
|
||||
activeSubscription?.subscription?.state?.platform
|
||||
const isManageable =
|
||||
!activeSubscriptionPlatform ||
|
||||
activeSubscriptionPlatform === currentPlatform
|
||||
|
||||
return (
|
||||
<Layout.Screen>
|
||||
<CenteredView sideBorders={true}>
|
||||
<ViewHeader title={_(msg`Subscriptions`)} />
|
||||
|
||||
<View style={[a.px_xl, a.py_xl, a.gap_lg]}>
|
||||
<Text style={[a.text_2xl]}>Subs</Text>
|
||||
|
||||
{isError ? (
|
||||
<Text>Error</Text>
|
||||
) : !subscriptions ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<>
|
||||
{subscriptions.map(s => (
|
||||
<SubscriptionCard
|
||||
key={s.id}
|
||||
subscription={s}
|
||||
activeSubscription={activeSubscription}
|
||||
isManageable={isManageable}
|
||||
/>
|
||||
))}
|
||||
|
||||
{!isManageable ? (
|
||||
<Admonition type="info">
|
||||
<Trans>
|
||||
You purchased this subscription on{' '}
|
||||
{activeSubscriptionPlatform}. Please access this screen on{' '}
|
||||
{activeSubscriptionPlatform} to manage your plan.
|
||||
</Trans>
|
||||
</Admonition>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</CenteredView>
|
||||
</Layout.Screen>
|
||||
)
|
||||
}
|
||||
|
||||
export function SubscriptionCard({
|
||||
subscription: s,
|
||||
activeSubscription,
|
||||
isManageable,
|
||||
}: {
|
||||
subscription: SubscriptionTier
|
||||
activeSubscription?: Subscription
|
||||
isManageable: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {i18n} = useLingui()
|
||||
const copy = useMainSubscriptionTiersCopy()
|
||||
|
||||
const activePlan = React.useMemo(() => {
|
||||
if (s.monthly.subscription.state?.active) {
|
||||
return s.monthly
|
||||
} else if (s.annual.subscription.state?.active) {
|
||||
return s.annual
|
||||
}
|
||||
}, [s])
|
||||
const isMonthly = s.monthly.subscription.state?.active
|
||||
const isAnnual = s.annual.subscription.state?.active
|
||||
const isActive = isMonthly || isAnnual
|
||||
|
||||
const gradient = React.useMemo(() => {
|
||||
return {
|
||||
[TierId.Main0]: tokens.gradients.sky,
|
||||
[TierId.Main1]: tokens.gradients.sunrise,
|
||||
[TierId.Main2]: tokens.gradients.bonfire,
|
||||
}[s.id]
|
||||
}, [s.id])
|
||||
|
||||
const control = Dialog.useDialogControl()
|
||||
|
||||
return (
|
||||
<View style={[a.w_full]}>
|
||||
<Button
|
||||
disabled={!isManageable}
|
||||
label={copy[s.id].title}
|
||||
style={[a.w_full]}
|
||||
onPress={() => control.open()}>
|
||||
{ctx => (
|
||||
<View
|
||||
style={[
|
||||
a.w_full,
|
||||
a.rounded_md,
|
||||
a.overflow_hidden,
|
||||
a.border,
|
||||
ctx.hovered
|
||||
? t.atoms.border_contrast_high
|
||||
: t.atoms.border_contrast_low,
|
||||
]}>
|
||||
<View
|
||||
style={[
|
||||
a.relative,
|
||||
a.w_full,
|
||||
{
|
||||
paddingTop: '10%',
|
||||
},
|
||||
]}>
|
||||
<GradientFill gradient={gradient} />
|
||||
{isActive && (
|
||||
<View
|
||||
style={[
|
||||
a.absolute,
|
||||
a.inset_0,
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
a.pr_lg,
|
||||
{
|
||||
left: 'auto',
|
||||
},
|
||||
]}>
|
||||
<Check fill="white" />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={[a.p_lg]}>
|
||||
<Text style={[a.text_2xl, a.font_heavy]}>{copy[s.id].title}</Text>
|
||||
|
||||
{activePlan && activePlan.subscription.state && (
|
||||
<View style={[a.gap_xs, a.pt_md]}>
|
||||
<Text style={[a.text_md, a.font_bold]}>Current</Text>
|
||||
<Text>• {activePlan.subscription.interval}</Text>
|
||||
<Text>
|
||||
• renews{' '}
|
||||
{i18n.date(
|
||||
new Date(activePlan.subscription.state?.periodEnd),
|
||||
{dateStyle: 'medium'},
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{isManageable && (
|
||||
<>
|
||||
<Divider style={[a.my_md]} />
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
{s.annual.price && s.monthly.price ? (
|
||||
<Text>
|
||||
<Trans>
|
||||
<Text style={[a.text_xl, a.font_heavy]}>
|
||||
{s.monthly.price.formatted}
|
||||
</Text>
|
||||
<Text style={[a.text_sm, a.font_bold]}>
|
||||
/month{' • '}
|
||||
<Text
|
||||
style={[
|
||||
a.text_sm,
|
||||
a.font_normal,
|
||||
t.atoms.text_contrast_medium,
|
||||
]}>
|
||||
<Trans>or {s.annual.price?.formatted}/year</Trans>
|
||||
</Text>
|
||||
</Text>
|
||||
</Trans>
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Dialog.Outer control={control}>
|
||||
<Dialog.Handle />
|
||||
<SubscriptionDialog
|
||||
subscription={s}
|
||||
activeSubscription={activeSubscription}
|
||||
/>
|
||||
</Dialog.Outer>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function SubscriptionDialog({
|
||||
subscription: s,
|
||||
activeSubscription,
|
||||
}: {
|
||||
subscription: SubscriptionTier
|
||||
activeSubscription?: Subscription
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {close} = Dialog.useDialogContext()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const copy = useMainSubscriptionTiersCopy()
|
||||
|
||||
const activeSubscriptionId = activeSubscription?.id
|
||||
const tierSubscriptions = [s.monthly, s.annual]
|
||||
console.log('tierSubscriptions', tierSubscriptions)
|
||||
const initiallySelectedSubscription = tierSubscriptions.find(
|
||||
s => s.id === activeSubscriptionId,
|
||||
)
|
||||
const isTierActive = !!initiallySelectedSubscription
|
||||
const [values, setValues] = React.useState<SubscriptionId[]>(
|
||||
initiallySelectedSubscription ? [initiallySelectedSubscription.id] : [],
|
||||
)
|
||||
const selectedSubscription = tierSubscriptions.find(s => s.id === values[0])
|
||||
|
||||
const isEditing =
|
||||
activeSubscription && selectedSubscription?.id !== activeSubscription.id
|
||||
const purchaseDisabled =
|
||||
!selectedSubscription ||
|
||||
(activeSubscription && selectedSubscription?.id === activeSubscription.id)
|
||||
|
||||
const {mutateAsync: purchaseSubscription, isPending: isPurchasePending} =
|
||||
usePurchaseSubscription()
|
||||
const {mutateAsync: changeSubscription, isPending: isChangePending} =
|
||||
useChangeSubscription()
|
||||
const {mutateAsync: cancelSubscription, isPending: isCancelPending} =
|
||||
useCancelSubscription()
|
||||
const purchase = React.useCallback(async () => {
|
||||
if (selectedSubscription) {
|
||||
console.log(selectedSubscription)
|
||||
await purchaseSubscription(selectedSubscription)
|
||||
}
|
||||
}, [selectedSubscription, purchaseSubscription])
|
||||
const change = React.useCallback(async () => {
|
||||
const prev = activeSubscription
|
||||
const next = selectedSubscription
|
||||
|
||||
if (!prev || !next) {
|
||||
throw new Error('Invalid subscription change')
|
||||
}
|
||||
|
||||
await changeSubscription({
|
||||
prev,
|
||||
next,
|
||||
})
|
||||
close()
|
||||
}, [activeSubscription, selectedSubscription, close])
|
||||
const cancel = React.useCallback(async () => {
|
||||
if (activeSubscription) {
|
||||
await cancelSubscription(activeSubscription)
|
||||
close()
|
||||
}
|
||||
}, [activeSubscription, cancelSubscription, close])
|
||||
const action = isEditing ? change : purchase
|
||||
const isPending = isPurchasePending || isChangePending
|
||||
const canCancel = isTierActive && activeSubscription?.platform === 'web'
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={copy[s.id].title}
|
||||
style={[
|
||||
gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full,
|
||||
]}>
|
||||
<Text style={[a.text_2xl, a.font_heavy, a.pb_md]}>
|
||||
{copy[s.id].title}
|
||||
</Text>
|
||||
|
||||
<Toggle.Group
|
||||
label={_(msg`Select plan`)}
|
||||
type="radio"
|
||||
values={values}
|
||||
onChange={setValues}>
|
||||
<View style={[a.flex_row, a.gap_md, a.pb_md]}>
|
||||
{tierSubscriptions.map(s => (
|
||||
<Toggle.Item
|
||||
key={s.id}
|
||||
label={_(msg`Billed annually`)}
|
||||
type="radio"
|
||||
name={s.id}
|
||||
style={[a.flex_1]}>
|
||||
{state => (
|
||||
<View
|
||||
style={[
|
||||
a.w_full,
|
||||
a.p_md,
|
||||
a.rounded_sm,
|
||||
a.border,
|
||||
t.atoms.border_contrast_low,
|
||||
{
|
||||
borderColor: state.selected
|
||||
? t.palette.primary_500
|
||||
: t.atoms.border_contrast_low.borderColor,
|
||||
},
|
||||
]}>
|
||||
<Text style={[a.text_2xl, a.font_heavy]}>
|
||||
{s.price?.formatted}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</Toggle.Item>
|
||||
))}
|
||||
</View>
|
||||
</Toggle.Group>
|
||||
|
||||
<View style={[a.gap_md]}>
|
||||
<Button
|
||||
label={_(msg`Purchase`)}
|
||||
disabled={purchaseDisabled}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
onPress={action}>
|
||||
<ButtonText>{isEditing ? 'Update' : 'Purchase'}</ButtonText>
|
||||
{isPending && <ButtonIcon icon={Loader} />}
|
||||
</Button>
|
||||
|
||||
{canCancel ? (
|
||||
<Button
|
||||
label={_(msg`Cancel subscription`)}
|
||||
size="large"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
onPress={cancel}>
|
||||
<ButtonText>Cancel</ButtonText>
|
||||
{isCancelPending && <ButtonIcon icon={Loader} />}
|
||||
</Button>
|
||||
) : null}
|
||||
</View>
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import Purchases from 'react-native-purchases'
|
||||
|
||||
import {SessionAccount} from '#/state/session/types'
|
||||
|
||||
export function identifyUser(account: SessionAccount) {
|
||||
Purchases.logIn(account.did)
|
||||
// TODO is this ever not defined?
|
||||
if (account.email) {
|
||||
Purchases.setEmail(account.email)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// no-op on web
|
||||
export function identifyUser() {}
|
||||
@@ -0,0 +1,80 @@
|
||||
import {Subscription} from '#/state/purchases/subscriptions/api/types'
|
||||
import {Entitlement} from '#/state/purchases/subscriptions/types'
|
||||
|
||||
export async function getMainSubscriptions({
|
||||
did,
|
||||
platform,
|
||||
currency,
|
||||
}: {
|
||||
did: string
|
||||
platform: 'web' | 'ios' | 'android'
|
||||
currency: string
|
||||
}) {
|
||||
const res = await fetch(
|
||||
`https://bsky-purchases.ngrok.io/subscriptions/main?user=${did}&platform=${platform}¤cy=${currency}`,
|
||||
)
|
||||
|
||||
if (!res.ok) {
|
||||
console.error('error fetching subscriptions', res.status, await res.text())
|
||||
return {
|
||||
subscriptions: [],
|
||||
}
|
||||
}
|
||||
|
||||
const json = await res.json()
|
||||
|
||||
return json as {
|
||||
subscriptions: Subscription[]
|
||||
}
|
||||
}
|
||||
|
||||
export async function getEntitlements({did}: {did: string}) {
|
||||
const res = await fetch(
|
||||
`https://bsky-purchases.ngrok.io/entitlements?user=${did}`,
|
||||
)
|
||||
|
||||
if (!res.ok) {
|
||||
console.error('error fetching entitlements', res.status, await res.text())
|
||||
return []
|
||||
}
|
||||
|
||||
const {entitlements} = await res.json()
|
||||
|
||||
return entitlements as Entitlement[]
|
||||
}
|
||||
|
||||
export async function updateSubscription({subscriptionId, newPriceId}: {subscriptionId: string, newPriceId: string}) {
|
||||
const res = await fetch(
|
||||
`https://bsky-purchases.ngrok.io/subscriptions/update`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({stripeSubscriptionId: subscriptionId, newPriceId}),
|
||||
}
|
||||
)
|
||||
|
||||
if (!res.ok) {
|
||||
console.error('error updating subscription', res.status, await res.text())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
export async function cancelSubscription({subscriptionId}: {subscriptionId: string}) {
|
||||
const res = await fetch(
|
||||
`https://bsky-purchases.ngrok.io/subscriptions/cancel`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({stripeSubscriptionId: subscriptionId}),
|
||||
}
|
||||
)
|
||||
|
||||
if (!res.ok) {
|
||||
console.error('error cancelling subscription', res.status, await res.text())
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import {
|
||||
TierId,
|
||||
SubscriptionId,
|
||||
} from '#/state/purchases/subscriptions/types'
|
||||
|
||||
export type SubscriptionState = {
|
||||
platform: 'android' | 'ios' | 'web'
|
||||
active: boolean
|
||||
entitlements: {id: TierId}[]
|
||||
status:
|
||||
| 'trialing'
|
||||
| 'active'
|
||||
| 'expired'
|
||||
| 'in_grace_period'
|
||||
| 'in_billing_retry'
|
||||
| 'paused'
|
||||
| 'unknown'
|
||||
| 'incomplete'
|
||||
renewalStatus:
|
||||
| 'will_renew'
|
||||
| 'will_not_renew'
|
||||
| 'will_change_product'
|
||||
| 'will_pause'
|
||||
| 'requires_price_increase_consent'
|
||||
| 'has_already_renewed'
|
||||
startedAt: number
|
||||
periodStart: number
|
||||
periodEnd: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Response from our API
|
||||
*/
|
||||
export type Subscription =
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'android' | 'ios'
|
||||
interval: 'monthly' | 'annual'
|
||||
state?: SubscriptionState
|
||||
store: {
|
||||
type: 'play_store' | 'app_store'
|
||||
productId: string
|
||||
productLookupKey: string
|
||||
}
|
||||
}
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'web'
|
||||
interval: 'monthly' | 'annual'
|
||||
state: undefined
|
||||
store: {
|
||||
type: 'stripe'
|
||||
productId: string
|
||||
price: number
|
||||
priceId: string
|
||||
subscriptionId: undefined
|
||||
}
|
||||
}
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'web'
|
||||
interval: 'monthly' | 'annual'
|
||||
state: SubscriptionState
|
||||
store: {
|
||||
type: 'stripe'
|
||||
productId: string
|
||||
price: number
|
||||
priceId: string
|
||||
subscriptionId: string
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import Purchases from 'react-native-purchases'
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {useCurrencyFormatter} from '#/lib/currency'
|
||||
import {isAndroid} from '#/platform/detection'
|
||||
import {getMainSubscriptions} from '#/state/purchases/subscriptions/api'
|
||||
import {Subscription as APISubscription} from '#/state/purchases/subscriptions/api/types'
|
||||
import {
|
||||
Subscription,
|
||||
SubscriptionTier,
|
||||
} from '#/state/purchases/subscriptions/types'
|
||||
import {organizeMainSubscriptionsByTier} from '#/state/purchases/subscriptions/util'
|
||||
import {useSession} from '#/state/session'
|
||||
|
||||
export function useMainSubscriptions() {
|
||||
const {currentAccount} = useSession()
|
||||
const did = currentAccount!.did
|
||||
const currencyFormatter = useCurrencyFormatter()
|
||||
|
||||
return useQuery<SubscriptionTier[]>({
|
||||
queryKey: ['availableSubscriptions', did],
|
||||
async queryFn() {
|
||||
const platform = isAndroid ? 'android' : 'ios'
|
||||
const rawSubscriptions = await getMainSubscriptions({
|
||||
did: currentAccount!.did,
|
||||
platform,
|
||||
})
|
||||
const platformSubscriptions = rawSubscriptions.subscriptions
|
||||
.filter(s => s.platform !== 'web')
|
||||
.filter(s => s.platform === platform)
|
||||
const lookupKeys = Array.from(
|
||||
new Set(platformSubscriptions.map(s => s.store.productLookupKey)),
|
||||
)
|
||||
const products = await Purchases.getProducts(lookupKeys)
|
||||
|
||||
function decorateSubscription(
|
||||
sub: APISubscription,
|
||||
): Subscription | undefined {
|
||||
if (sub.platform === 'web') {
|
||||
return {
|
||||
id: sub.id,
|
||||
platform: sub.platform,
|
||||
interval: sub.interval,
|
||||
subscription: sub,
|
||||
price: {
|
||||
value: sub.store.price, // convert to cents
|
||||
formatted: currencyFormatter.format(sub.store.price / 100),
|
||||
},
|
||||
product: sub.store.priceId,
|
||||
}
|
||||
}
|
||||
|
||||
const productData = products.find(
|
||||
p => p.identifier === sub.store.productId,
|
||||
)
|
||||
|
||||
if (!productData) return undefined
|
||||
|
||||
return {
|
||||
id: sub.id,
|
||||
platform: sub.platform,
|
||||
interval: sub.interval,
|
||||
subscription: sub,
|
||||
price: {
|
||||
value: productData.price * 100, // convert to cents
|
||||
formatted: productData.priceString,
|
||||
},
|
||||
product: productData,
|
||||
}
|
||||
}
|
||||
const subscriptions = rawSubscriptions.subscriptions
|
||||
.map(decorateSubscription)
|
||||
.filter(Boolean) as Subscription[]
|
||||
|
||||
return organizeMainSubscriptionsByTier(subscriptions)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function usePurchaseSubscription() {
|
||||
const {currentAccount} = useSession()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
async mutationFn(subscription: Subscription) {
|
||||
if (subscription.platform === 'web') {
|
||||
throw new Error('Cannot purchase web subscription on native')
|
||||
}
|
||||
|
||||
if (!subscription.product) {
|
||||
throw new Error('Subscription product not found')
|
||||
}
|
||||
|
||||
// TODO don't do this here
|
||||
Purchases.addCustomerInfoUpdateListener(_info => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['availableSubscriptions', currentAccount!.did],
|
||||
})
|
||||
})
|
||||
|
||||
return Purchases.purchaseStoreProduct(subscription.product)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useChangeSubscription() {
|
||||
return useMutation({
|
||||
async mutationFn({prev, next}: {prev: Subscription; next: Subscription}) {},
|
||||
})
|
||||
}
|
||||
|
||||
export function useCancelSubscription() {
|
||||
return useMutation({
|
||||
async mutationFn(subscription: Subscription) {},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
import {Linking} from 'react-native'
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {useCurrencyFormatter} from '#/lib/currency'
|
||||
import {
|
||||
getMainSubscriptions,
|
||||
updateSubscription,
|
||||
cancelSubscription,
|
||||
} from '#/state/purchases/subscriptions/api'
|
||||
import {
|
||||
Subscription,
|
||||
SubscriptionTier,
|
||||
} from '#/state/purchases/subscriptions/types'
|
||||
import {organizeMainSubscriptionsByTier} from '#/state/purchases/subscriptions/util'
|
||||
import {useSession} from '#/state/session'
|
||||
import {BSKY_PURCHASES_API} from '#/env'
|
||||
|
||||
const createMainSubscriptionsQueryKey = (did: string) => [
|
||||
'availableSubscriptions',
|
||||
did,
|
||||
]
|
||||
|
||||
export function useMainSubscriptions() {
|
||||
const {currentAccount} = useSession()
|
||||
const currencyFormatter = useCurrencyFormatter({
|
||||
trailingZeroDisplay: 'stripIfInteger',
|
||||
})
|
||||
|
||||
return useQuery<SubscriptionTier[]>({
|
||||
refetchOnWindowFocus: true,
|
||||
queryKey: createMainSubscriptionsQueryKey(currentAccount!.did),
|
||||
async queryFn() {
|
||||
const rawSubscriptions = await getMainSubscriptions({
|
||||
did: currentAccount!.did,
|
||||
platform: 'web',
|
||||
currency: currencyFormatter.currency,
|
||||
})
|
||||
const platformSubscriptions = rawSubscriptions.subscriptions.filter(
|
||||
s => s.platform === 'web',
|
||||
)
|
||||
const subscriptions: Subscription[] = platformSubscriptions.map(sub => {
|
||||
return {
|
||||
id: sub.id,
|
||||
platform: 'web',
|
||||
interval: sub.interval,
|
||||
subscription: sub,
|
||||
price: {
|
||||
value: sub.store.price,
|
||||
formatted: currencyFormatter.format(sub.store.price / 100),
|
||||
},
|
||||
// TODO may need to have si_id too
|
||||
product: sub.store.priceId,
|
||||
}
|
||||
})
|
||||
|
||||
return organizeMainSubscriptionsByTier(subscriptions)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function usePurchaseSubscription() {
|
||||
const {currentAccount} = useSession()
|
||||
return useMutation({
|
||||
async mutationFn(subscription: Subscription) {
|
||||
if (subscription.platform !== 'web') {
|
||||
throw new Error('Cannot purchase native subscription on web')
|
||||
}
|
||||
|
||||
if (!currentAccount || !currentAccount.email) {
|
||||
throw new Error('No account or email')
|
||||
}
|
||||
|
||||
const {checkoutUrl} = await fetch(
|
||||
`${BSKY_PURCHASES_API}/createCheckout`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
price: subscription.product,
|
||||
// TODO should NOT use query, use auth and our db state
|
||||
user: currentAccount.did,
|
||||
email: currentAccount.email,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
).then(res => res.json())
|
||||
Linking.openURL(checkoutUrl)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useChangeSubscription() {
|
||||
const {currentAccount} = useSession()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
async mutationFn({prev, next}: {prev: Subscription; next: Subscription}) {
|
||||
if (
|
||||
prev.subscription.platform !== 'web' ||
|
||||
next.subscription.platform !== 'web'
|
||||
) {
|
||||
throw new Error('Cannot purchase native subscription on web')
|
||||
}
|
||||
|
||||
if (!prev.subscription.store.subscriptionId) {
|
||||
throw new Error(`Cannot change a subscription that doesn't exist`)
|
||||
}
|
||||
|
||||
await updateSubscription({
|
||||
subscriptionId: prev.subscription.store.subscriptionId,
|
||||
newPriceId: next.subscription.store.priceId,
|
||||
})
|
||||
},
|
||||
onSuccess() {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: createMainSubscriptionsQueryKey(currentAccount!.did),
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useCancelSubscription() {
|
||||
const {currentAccount} = useSession()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
async mutationFn(subscription: Subscription) {
|
||||
if (subscription.subscription.platform !== 'web') {
|
||||
throw new Error('Cannot cancel native subscription on web')
|
||||
}
|
||||
|
||||
if (!subscription.subscription.store.subscriptionId) {
|
||||
throw new Error(`Cannot cancel a subscription that doesn't exist`)
|
||||
}
|
||||
|
||||
await cancelSubscription({
|
||||
subscriptionId: subscription.subscription.store.subscriptionId,
|
||||
})
|
||||
},
|
||||
onSuccess() {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: createMainSubscriptionsQueryKey(currentAccount!.did),
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import {PurchasesStoreProduct} from 'react-native-purchases'
|
||||
|
||||
import {Subscription as APISubscription} from '#/state/purchases/subscriptions/api/types'
|
||||
|
||||
export enum SubscriptionId {
|
||||
Main0MonthlyAuto = 'main:0:monthly:auto',
|
||||
Main0AnnualAuto = 'main:0:annual:auto',
|
||||
Main1MonthlyAuto = 'main:1:monthly:auto',
|
||||
Main1AnnualAuto = 'main:1:annual:auto',
|
||||
Main2MonthlyAuto = 'main:2:monthly:auto',
|
||||
Main2AnnualAuto = 'main:2:annual:auto',
|
||||
}
|
||||
|
||||
export enum TierId {
|
||||
Main0 = 'main:0',
|
||||
Main1 = 'main:1',
|
||||
Main2 = 'main:2',
|
||||
}
|
||||
|
||||
export enum PaymentInterval {
|
||||
Monthly = 'monthly',
|
||||
Annual = 'annual',
|
||||
}
|
||||
|
||||
export type Entitlement = {
|
||||
id: TierId
|
||||
}
|
||||
|
||||
export type Subscription =
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'android'
|
||||
interval: 'monthly' | 'annual'
|
||||
/**
|
||||
* Response from our API
|
||||
*/
|
||||
subscription: APISubscription
|
||||
price?: {
|
||||
value: number
|
||||
formatted: string
|
||||
}
|
||||
product?: PurchasesStoreProduct
|
||||
}
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'ios'
|
||||
interval: 'monthly' | 'annual'
|
||||
/**
|
||||
* Response from our API
|
||||
*/
|
||||
subscription: APISubscription
|
||||
price?: {
|
||||
value: number
|
||||
formatted: string
|
||||
}
|
||||
product?: PurchasesStoreProduct
|
||||
}
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'web'
|
||||
interval: 'monthly' | 'annual'
|
||||
/**
|
||||
* Response from our API
|
||||
*/
|
||||
subscription: APISubscription
|
||||
price: {
|
||||
value: number
|
||||
formatted: string
|
||||
}
|
||||
product: string
|
||||
}
|
||||
|
||||
export type SubscriptionTier = {
|
||||
id: TierId
|
||||
[PaymentInterval.Monthly]: Subscription
|
||||
[PaymentInterval.Annual]: Subscription
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import {useQuery} from '@tanstack/react-query'
|
||||
|
||||
import {getEntitlements} from '#/state/purchases/subscriptions/api'
|
||||
import {useSession} from '#/state/session'
|
||||
|
||||
export function useEntitlements() {
|
||||
const {currentAccount} = useSession()
|
||||
return useQuery({
|
||||
queryKey: ['entitlements', currentAccount!.did],
|
||||
async queryFn() {
|
||||
return getEntitlements({did: currentAccount!.did})
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import {Subscription, SubscriptionTier} from './types'
|
||||
|
||||
export function organizeMainSubscriptionsByTier(
|
||||
subscriptions: Subscription[],
|
||||
): SubscriptionTier[] {
|
||||
const interim: Record<string, SubscriptionTier> = {}
|
||||
|
||||
for (const sub of subscriptions) {
|
||||
const [_, tier, interval] = sub.id.split(':')
|
||||
|
||||
interim[tier] = interim[tier] || {
|
||||
id: `main:${tier}`,
|
||||
}
|
||||
interim[tier][interval as 'monthly' | 'annual'] = sub
|
||||
}
|
||||
|
||||
return Object.values(interim)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import {AtpSessionEvent} from '@atproto/api'
|
||||
|
||||
import {identifyUser as identifyPurchasesUser} from '#/state/purchases/identifyUser'
|
||||
import {createPublicAgent} from './agent'
|
||||
import {wrapSessionReducerForLogging} from './logging'
|
||||
import {SessionAccount} from './types'
|
||||
@@ -118,6 +119,7 @@ let reducer = (state: State, action: Action): State => {
|
||||
}
|
||||
case 'switched-to-account': {
|
||||
const {newAccount, newAgent} = action
|
||||
identifyPurchasesUser(newAccount)
|
||||
return {
|
||||
accounts: [
|
||||
newAccount,
|
||||
|
||||
@@ -16,6 +16,7 @@ import {atoms} from '#/alf'
|
||||
import {useTheme} from '#/alf'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {ColorPalette_Stroke2_Corner0_Rounded as ColorPalette} from '#/components/icons/ColorPalette'
|
||||
import {Gift1_Stroke2_Corner0_Rounded as Gift} from '#/components/icons/Gift1'
|
||||
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
||||
import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu'
|
||||
import {Link} from '#/components/Link'
|
||||
@@ -73,6 +74,9 @@ export function HomeHeaderLayoutMobile({
|
||||
]}>
|
||||
{IS_DEV && (
|
||||
<>
|
||||
<Link label="Jump to subscriptions" to="/subscriptions">
|
||||
<Gift size="md" />
|
||||
</Link>
|
||||
<Link
|
||||
label="View storybook"
|
||||
to="/sys/debug"
|
||||
|
||||
@@ -30,6 +30,10 @@ import {
|
||||
Bell_Stroke2_Corner0_Rounded as Bell,
|
||||
} from '#/components/icons/Bell'
|
||||
import {BulletList_Stroke2_Corner0_Rounded as List} from '#/components/icons/BulletList'
|
||||
import {
|
||||
Gift1_Filled_Corner0_Rounded as GiftFilled,
|
||||
Gift1_Stroke2_Corner0_Rounded as Gift,
|
||||
} from '#/components/icons/Gift1'
|
||||
import {
|
||||
Hashtag_Filled_Corner0_Rounded as HashtagFilled,
|
||||
Hashtag_Stroke2_Corner0_Rounded as Hashtag,
|
||||
@@ -205,6 +209,11 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
||||
setDrawerOpen(false)
|
||||
}, [navigation, setDrawerOpen])
|
||||
|
||||
const onPressSubscriptions = React.useCallback(() => {
|
||||
navigation.navigate('Subscriptions')
|
||||
setDrawerOpen(false)
|
||||
}, [navigation, setDrawerOpen])
|
||||
|
||||
const onPressFeedback = React.useCallback(() => {
|
||||
Linking.openURL(
|
||||
FEEDBACK_FORM_URL({
|
||||
@@ -266,6 +275,10 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
||||
onPress={onPressProfile}
|
||||
/>
|
||||
<SettingsMenuItem onPress={onPressSettings} />
|
||||
<SubscriptionsMenuItem
|
||||
isActive={false}
|
||||
onPress={onPressSubscriptions}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
@@ -562,6 +575,31 @@ let SettingsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
||||
}
|
||||
SettingsMenuItem = React.memo(SettingsMenuItem)
|
||||
|
||||
let SubscriptionsMenuItem = ({
|
||||
isActive,
|
||||
onPress,
|
||||
}: {
|
||||
isActive: boolean
|
||||
onPress: () => void
|
||||
}): React.ReactNode => {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MenuItem
|
||||
icon={
|
||||
isActive ? (
|
||||
<GiftFilled style={[t.atoms.text]} width={iconWidth} />
|
||||
) : (
|
||||
<Gift style={[t.atoms.text]} width={iconWidth} />
|
||||
)
|
||||
}
|
||||
label={_(msg`Support Bluesky`)}
|
||||
onPress={onPress}
|
||||
/>
|
||||
)
|
||||
}
|
||||
SubscriptionsMenuItem = React.memo(SubscriptionsMenuItem)
|
||||
|
||||
function MenuItem({icon, label, count, bold, onPress}: MenuItemProps) {
|
||||
const t = useTheme()
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.dev.vars
|
||||
.wrangler
|
||||
@@ -0,0 +1,9 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Front of House
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Cloudflare Workers Site
|
||||
|
||||
Minimalist approach to making a website on the Cloudflare Supercloud.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Clone this repo, then:
|
||||
|
||||
```
|
||||
pnpm i && pnpm client && pnpm push
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT License © [Front of House](https://github.com/front-of-house)
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
declare const ENV: 'development' | 'production'
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "workers-site",
|
||||
"scripts": {
|
||||
"start": "wrangler dev",
|
||||
"push": "wrangler publish",
|
||||
"dry": "wrangler deploy --dry-run --outdir dist",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20240903.0",
|
||||
"prettier": "^3.3.3",
|
||||
"typescript": "^5.5.4",
|
||||
"wrangler": "^3.75.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"hono": "^4.5.11",
|
||||
"ky": "^1.7.2",
|
||||
"stripe": "^17.2.1"
|
||||
}
|
||||
}
|
||||
Generated
+855
@@ -0,0 +1,855 @@
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
hono:
|
||||
specifier: ^4.5.11
|
||||
version: 4.5.11
|
||||
devDependencies:
|
||||
'@cloudflare/workers-types':
|
||||
specifier: ^4.20240903.0
|
||||
version: 4.20240903.0
|
||||
prettier:
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3
|
||||
typescript:
|
||||
specifier: ^5.5.4
|
||||
version: 5.5.4
|
||||
wrangler:
|
||||
specifier: ^3.75.0
|
||||
version: 3.75.0(@cloudflare/workers-types@4.20240903.0)
|
||||
|
||||
workers/site:
|
||||
dependencies:
|
||||
'@presta/html':
|
||||
specifier: ^0.2.5
|
||||
version: 0.2.5
|
||||
'@types/react':
|
||||
specifier: ^18.0.27
|
||||
version: 18.0.27
|
||||
hyposcript:
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
devDependencies:
|
||||
'@cloudflare/workers-types':
|
||||
specifier: ^4.20230115.0
|
||||
version: 4.20230115.0
|
||||
wrangler:
|
||||
specifier: ^2.9.0
|
||||
version: 2.9.1
|
||||
|
||||
packages:
|
||||
|
||||
/@cloudflare/kv-asset-handler@0.3.4:
|
||||
resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==}
|
||||
engines: {node: '>=16.13'}
|
||||
dependencies:
|
||||
mime: 3.0.0
|
||||
dev: true
|
||||
|
||||
/@cloudflare/workerd-darwin-64@1.20240821.1:
|
||||
resolution: {integrity: sha512-CDBpfZKrSy4YrIdqS84z67r3Tzal2pOhjCsIb63IuCnvVes59/ft1qhczBzk9EffeOE2iTCrA4YBT7Sbn7USew==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@cloudflare/workerd-darwin-arm64@1.20240821.1:
|
||||
resolution: {integrity: sha512-Q+9RedvNbPcEt/dKni1oN94OxbvuNAeJkgHmrLFTGF8zu21wzOhVkQeRNxcYxrMa9mfStc457NAg13OVCj2kHQ==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@cloudflare/workerd-linux-64@1.20240821.1:
|
||||
resolution: {integrity: sha512-j6z3KsPtawrscoLuP985LbqFrmsJL6q1mvSXOXTqXGODAHIzGBipHARdOjms3UQqovzvqB2lQaQsZtLBwCZxtA==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@cloudflare/workerd-linux-arm64@1.20240821.1:
|
||||
resolution: {integrity: sha512-I9bHgZOxJQW0CV5gTdilyxzTG7ILzbTirehQWgfPx9X77E/7eIbR9sboOMgyeC69W4he0SKtpx0sYZuTJu4ERw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@cloudflare/workerd-windows-64@1.20240821.1:
|
||||
resolution: {integrity: sha512-keC97QPArs6LWbPejQM7/Y8Jy8QqyaZow4/ZdsGo+QjlOLiZRDpAenfZx3CBUoWwEeFwQTl2FLO+8hV1SWFFYw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@cloudflare/workers-shared@0.4.1:
|
||||
resolution: {integrity: sha512-nYh4r8JwOOjYIdH2zub++CmIKlkYFlpxI1nBHimoiHcytJXD/b7ldJ21TtfzUZMCgI78mxVlymMHA/ReaOxKlA==}
|
||||
engines: {node: '>=16.7.0'}
|
||||
dev: true
|
||||
|
||||
/@cloudflare/workers-types@4.20240903.0:
|
||||
resolution: {integrity: sha512-a4mqgtVsPWg3JNNlQdLRE0Z6/mHr/uXa1ANDw6Zd7in438UCbeb+j7Z954Sf93G24jExpAn9VZ8kUUml0RwZbQ==}
|
||||
dev: true
|
||||
|
||||
/@cspotcode/source-map-support@0.8.1:
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
dev: true
|
||||
|
||||
/@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19):
|
||||
resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==}
|
||||
peerDependencies:
|
||||
esbuild: '*'
|
||||
dependencies:
|
||||
esbuild: 0.17.19
|
||||
dev: true
|
||||
|
||||
/@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19):
|
||||
resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==}
|
||||
peerDependencies:
|
||||
esbuild: '*'
|
||||
dependencies:
|
||||
esbuild: 0.17.19
|
||||
escape-string-regexp: 4.0.0
|
||||
rollup-plugin-node-polyfills: 0.2.1
|
||||
dev: true
|
||||
|
||||
/@esbuild/android-arm64@0.17.19:
|
||||
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/android-arm@0.17.19:
|
||||
resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/android-x64@0.17.19:
|
||||
resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/darwin-arm64@0.17.19:
|
||||
resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/darwin-x64@0.17.19:
|
||||
resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/freebsd-arm64@0.17.19:
|
||||
resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/freebsd-x64@0.17.19:
|
||||
resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-arm64@0.17.19:
|
||||
resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-arm@0.17.19:
|
||||
resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-ia32@0.17.19:
|
||||
resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-loong64@0.17.19:
|
||||
resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-mips64el@0.17.19:
|
||||
resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-ppc64@0.17.19:
|
||||
resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-riscv64@0.17.19:
|
||||
resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-s390x@0.17.19:
|
||||
resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-x64@0.17.19:
|
||||
resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/netbsd-x64@0.17.19:
|
||||
resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/openbsd-x64@0.17.19:
|
||||
resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/sunos-x64@0.17.19:
|
||||
resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/win32-arm64@0.17.19:
|
||||
resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/win32-ia32@0.17.19:
|
||||
resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/win32-x64@0.17.19:
|
||||
resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@fastify/busboy@2.1.1:
|
||||
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
|
||||
engines: {node: '>=14'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/resolve-uri@3.1.2:
|
||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/sourcemap-codec@1.5.0:
|
||||
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/trace-mapping@0.3.9:
|
||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
dev: true
|
||||
|
||||
/acorn-walk@8.3.3:
|
||||
resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dependencies:
|
||||
acorn: 8.12.1
|
||||
dev: true
|
||||
|
||||
/acorn@8.12.1:
|
||||
resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/anymatch@3.1.3:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
normalize-path: 3.0.0
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/as-table@1.0.55:
|
||||
resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
|
||||
dependencies:
|
||||
printable-characters: 1.0.42
|
||||
dev: true
|
||||
|
||||
/binary-extensions@2.2.0:
|
||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/blake3-wasm@2.1.5:
|
||||
resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
|
||||
dev: true
|
||||
|
||||
/braces@3.0.2:
|
||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
fill-range: 7.0.1
|
||||
dev: true
|
||||
|
||||
/capnp-ts@0.7.0:
|
||||
resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==}
|
||||
dependencies:
|
||||
debug: 4.3.7
|
||||
tslib: 2.7.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/chokidar@3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
dependencies:
|
||||
anymatch: 3.1.3
|
||||
braces: 3.0.2
|
||||
glob-parent: 5.1.2
|
||||
is-binary-path: 2.1.0
|
||||
is-glob: 4.0.3
|
||||
normalize-path: 3.0.0
|
||||
readdirp: 3.6.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/cookie@0.5.0:
|
||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: true
|
||||
|
||||
/data-uri-to-buffer@2.0.2:
|
||||
resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
|
||||
dev: true
|
||||
|
||||
/date-fns@3.6.0:
|
||||
resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
|
||||
dev: true
|
||||
|
||||
/debug@4.3.7:
|
||||
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
dev: true
|
||||
|
||||
/defu@6.1.4:
|
||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||
dev: true
|
||||
|
||||
/esbuild@0.17.19:
|
||||
resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@esbuild/android-arm': 0.17.19
|
||||
'@esbuild/android-arm64': 0.17.19
|
||||
'@esbuild/android-x64': 0.17.19
|
||||
'@esbuild/darwin-arm64': 0.17.19
|
||||
'@esbuild/darwin-x64': 0.17.19
|
||||
'@esbuild/freebsd-arm64': 0.17.19
|
||||
'@esbuild/freebsd-x64': 0.17.19
|
||||
'@esbuild/linux-arm': 0.17.19
|
||||
'@esbuild/linux-arm64': 0.17.19
|
||||
'@esbuild/linux-ia32': 0.17.19
|
||||
'@esbuild/linux-loong64': 0.17.19
|
||||
'@esbuild/linux-mips64el': 0.17.19
|
||||
'@esbuild/linux-ppc64': 0.17.19
|
||||
'@esbuild/linux-riscv64': 0.17.19
|
||||
'@esbuild/linux-s390x': 0.17.19
|
||||
'@esbuild/linux-x64': 0.17.19
|
||||
'@esbuild/netbsd-x64': 0.17.19
|
||||
'@esbuild/openbsd-x64': 0.17.19
|
||||
'@esbuild/sunos-x64': 0.17.19
|
||||
'@esbuild/win32-arm64': 0.17.19
|
||||
'@esbuild/win32-ia32': 0.17.19
|
||||
'@esbuild/win32-x64': 0.17.19
|
||||
dev: true
|
||||
|
||||
/escape-string-regexp@4.0.0:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/estree-walker@0.6.1:
|
||||
resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
|
||||
dev: true
|
||||
|
||||
/exit-hook@2.2.1:
|
||||
resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/fill-range@7.0.1:
|
||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
dev: true
|
||||
|
||||
/fsevents@2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
dev: true
|
||||
|
||||
/get-source@2.0.12:
|
||||
resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
|
||||
dependencies:
|
||||
data-uri-to-buffer: 2.0.2
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
dev: true
|
||||
|
||||
/glob-to-regexp@0.4.1:
|
||||
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
|
||||
dev: true
|
||||
|
||||
/hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
dev: true
|
||||
|
||||
/hono@4.5.11:
|
||||
resolution: {integrity: sha512-62FcjLPtjAFwISVBUshryl+vbHOjg8rE4uIK/dxyR8GpLztunZpwFmfEvmJCUI7xoGh/Sr3CGCDPCmYxVw7wUQ==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
dev: false
|
||||
|
||||
/is-binary-path@2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
binary-extensions: 2.2.0
|
||||
dev: true
|
||||
|
||||
/is-core-module@2.15.1:
|
||||
resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
dev: true
|
||||
|
||||
/is-extglob@2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/is-glob@4.0.3:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
is-extglob: 2.1.1
|
||||
dev: true
|
||||
|
||||
/is-number@7.0.0:
|
||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
dev: true
|
||||
|
||||
/magic-string@0.25.9:
|
||||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||
dependencies:
|
||||
sourcemap-codec: 1.4.8
|
||||
dev: true
|
||||
|
||||
/mime@3.0.0:
|
||||
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/miniflare@3.20240821.1:
|
||||
resolution: {integrity: sha512-81qdiryDG7VXzZuoa0EwhkaIYYrn7+StRIrd/2i7SPqPUNICUBjbhFFKqTnvE1+fqIPPB6l8ShKFaFvmnZOASg==}
|
||||
engines: {node: '>=16.13'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
acorn: 8.12.1
|
||||
acorn-walk: 8.3.3
|
||||
capnp-ts: 0.7.0
|
||||
exit-hook: 2.2.1
|
||||
glob-to-regexp: 0.4.1
|
||||
stoppable: 1.1.0
|
||||
undici: 5.28.4
|
||||
workerd: 1.20240821.1
|
||||
ws: 8.18.0
|
||||
youch: 3.3.3
|
||||
zod: 3.23.8
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
dev: true
|
||||
|
||||
/mustache@4.2.0:
|
||||
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/nanoid@3.3.4:
|
||||
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/node-forge@1.3.1:
|
||||
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
|
||||
engines: {node: '>= 6.13.0'}
|
||||
dev: true
|
||||
|
||||
/normalize-path@3.0.0:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/ohash@1.1.3:
|
||||
resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==}
|
||||
dev: true
|
||||
|
||||
/path-parse@1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
dev: true
|
||||
|
||||
/path-to-regexp@6.2.1:
|
||||
resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
|
||||
dev: true
|
||||
|
||||
/pathe@1.1.2:
|
||||
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
|
||||
dev: true
|
||||
|
||||
/picomatch@2.3.1:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
dev: true
|
||||
|
||||
/prettier@3.3.3:
|
||||
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/printable-characters@1.0.42:
|
||||
resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
|
||||
dev: true
|
||||
|
||||
/readdirp@3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/resolve.exports@2.0.2:
|
||||
resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/resolve@1.22.8:
|
||||
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
is-core-module: 2.15.1
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-inject@3.0.2:
|
||||
resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==}
|
||||
deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
|
||||
dependencies:
|
||||
estree-walker: 0.6.1
|
||||
magic-string: 0.25.9
|
||||
rollup-pluginutils: 2.8.2
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-node-polyfills@0.2.1:
|
||||
resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==}
|
||||
dependencies:
|
||||
rollup-plugin-inject: 3.0.2
|
||||
dev: true
|
||||
|
||||
/rollup-pluginutils@2.8.2:
|
||||
resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
|
||||
dependencies:
|
||||
estree-walker: 0.6.1
|
||||
dev: true
|
||||
|
||||
/selfsigned@2.1.1:
|
||||
resolution: {integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
node-forge: 1.3.1
|
||||
dev: true
|
||||
|
||||
/source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/sourcemap-codec@1.4.8:
|
||||
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
|
||||
deprecated: Please use @jridgewell/sourcemap-codec instead
|
||||
dev: true
|
||||
|
||||
/stacktracey@2.1.8:
|
||||
resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==}
|
||||
dependencies:
|
||||
as-table: 1.0.55
|
||||
get-source: 2.0.12
|
||||
dev: true
|
||||
|
||||
/stoppable@1.1.0:
|
||||
resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==}
|
||||
engines: {node: '>=4', npm: '>=6'}
|
||||
dev: true
|
||||
|
||||
/supports-preserve-symlinks-flag@1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
dev: true
|
||||
|
||||
/tslib@2.7.0:
|
||||
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
|
||||
dev: true
|
||||
|
||||
/typescript@5.5.4:
|
||||
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/ufo@1.5.4:
|
||||
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
|
||||
dev: true
|
||||
|
||||
/undici@5.28.4:
|
||||
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
|
||||
engines: {node: '>=14.0'}
|
||||
dependencies:
|
||||
'@fastify/busboy': 2.1.1
|
||||
dev: true
|
||||
|
||||
/unenv-nightly@2.0.0-1724863496.70db6f1:
|
||||
resolution: {integrity: sha512-r+VIl1gnsI4WQxluruSQhy8alpAf1AsLRLm4sEKp3otCyTIVD6I6wHEYzeQnwsyWgaD4+3BD4A/eqrgOpdTzhw==}
|
||||
dependencies:
|
||||
defu: 6.1.4
|
||||
ohash: 1.1.3
|
||||
pathe: 1.1.2
|
||||
ufo: 1.5.4
|
||||
dev: true
|
||||
|
||||
/workerd@1.20240821.1:
|
||||
resolution: {integrity: sha512-y4phjCnEG96u8ZkgkkHB+gSw0i6uMNo23rBmixylWpjxDklB+LWD8dztasvsu7xGaZbLoTxQESdEw956F7VJDA==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@cloudflare/workerd-darwin-64': 1.20240821.1
|
||||
'@cloudflare/workerd-darwin-arm64': 1.20240821.1
|
||||
'@cloudflare/workerd-linux-64': 1.20240821.1
|
||||
'@cloudflare/workerd-linux-arm64': 1.20240821.1
|
||||
'@cloudflare/workerd-windows-64': 1.20240821.1
|
||||
dev: true
|
||||
|
||||
/wrangler@3.75.0(@cloudflare/workers-types@4.20240903.0):
|
||||
resolution: {integrity: sha512-CitNuNj0O1z6qbonUXmpUbxeWpU3nx28Kc4ZT33tMdeooQssb063Ie7+ZCdfS3kPhRHSwGdtOV22xFYytHON8w==}
|
||||
engines: {node: '>=16.17.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@cloudflare/workers-types': ^4.20240821.1
|
||||
peerDependenciesMeta:
|
||||
'@cloudflare/workers-types':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@cloudflare/kv-asset-handler': 0.3.4
|
||||
'@cloudflare/workers-shared': 0.4.1
|
||||
'@cloudflare/workers-types': 4.20240903.0
|
||||
'@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
|
||||
'@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
|
||||
blake3-wasm: 2.1.5
|
||||
chokidar: 3.5.3
|
||||
date-fns: 3.6.0
|
||||
esbuild: 0.17.19
|
||||
miniflare: 3.20240821.1
|
||||
nanoid: 3.3.4
|
||||
path-to-regexp: 6.2.1
|
||||
resolve: 1.22.8
|
||||
resolve.exports: 2.0.2
|
||||
selfsigned: 2.1.1
|
||||
source-map: 0.6.1
|
||||
unenv: /unenv-nightly@2.0.0-1724863496.70db6f1
|
||||
workerd: 1.20240821.1
|
||||
xxhash-wasm: 1.0.2
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/ws@8.18.0:
|
||||
resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
dev: true
|
||||
|
||||
/xxhash-wasm@1.0.2:
|
||||
resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==}
|
||||
dev: true
|
||||
|
||||
/youch@3.3.3:
|
||||
resolution: {integrity: sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==}
|
||||
dependencies:
|
||||
cookie: 0.5.0
|
||||
mustache: 4.2.0
|
||||
stacktracey: 2.1.8
|
||||
dev: true
|
||||
|
||||
/zod@3.23.8:
|
||||
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
||||
dev: true
|
||||
@@ -0,0 +1,389 @@
|
||||
import {Hono} from 'hono'
|
||||
import {cors} from 'hono/cors'
|
||||
import {HTTPException} from 'hono/http-exception'
|
||||
import ky, {KyInstance} from 'ky'
|
||||
import Stripe from 'stripe'
|
||||
|
||||
import {
|
||||
mergeSubscriptions,
|
||||
normalizeEntitlements,
|
||||
normalizeSubscriptions,
|
||||
RevenueCatSubscription,
|
||||
Subscription,
|
||||
} from './util'
|
||||
|
||||
type Bindings = {
|
||||
STRIPE_API_KEY: string
|
||||
RC_API_KEY_V2: string
|
||||
RC_API_KEY_V1: string
|
||||
RC_PROJECT_ID: string
|
||||
}
|
||||
|
||||
type Variables = {
|
||||
rcv1: KyInstance
|
||||
rcv2: KyInstance
|
||||
stripe: Stripe
|
||||
}
|
||||
|
||||
export default new Hono<{Bindings: Bindings; Variables: Variables}>()
|
||||
.use(
|
||||
cors({
|
||||
origin: [
|
||||
'http://localhost:19006',
|
||||
'https://main.bsky.dev',
|
||||
'https://bsky.app',
|
||||
],
|
||||
allowMethods: ['GET'],
|
||||
exposeHeaders: ['Content-Length'],
|
||||
maxAge: 600,
|
||||
credentials: true,
|
||||
}),
|
||||
)
|
||||
.use(async (c, next) => {
|
||||
const rcv1 = ky.create({
|
||||
prefixUrl: 'https://api.revenuecat.com/v1',
|
||||
headers: {
|
||||
Authorization: `Bearer ${c.env.RC_API_KEY_V1}`,
|
||||
},
|
||||
})
|
||||
const rcv2 = ky.create({
|
||||
prefixUrl: `https://api.revenuecat.com/v2/projects/${c.env.RC_PROJECT_ID}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${c.env.RC_API_KEY_V2}`,
|
||||
},
|
||||
})
|
||||
const stripe = new Stripe(c.env.STRIPE_API_KEY)
|
||||
c.set('rcv1', rcv1)
|
||||
c.set('rcv2', rcv2)
|
||||
c.set('stripe', stripe)
|
||||
await next()
|
||||
})
|
||||
|
||||
/**
|
||||
* Update a subscription (web only)
|
||||
*/
|
||||
.post(`/subscriptions/update`, async c => {
|
||||
const stripe = c.get('stripe')
|
||||
const {stripeSubscriptionId, newPriceId} = await c.req.json()
|
||||
const subscriptionItem = await stripe.subscriptionItems.retrieve(
|
||||
stripeSubscriptionId,
|
||||
)
|
||||
const subscription = await stripe.subscriptions.retrieve(
|
||||
subscriptionItem.subscription,
|
||||
)
|
||||
const price = await stripe.prices.retrieve(newPriceId)
|
||||
|
||||
if (!subscription.schedule) {
|
||||
throw new HTTPException(400, {
|
||||
message: `Subscription does not have an associated schedule`,
|
||||
})
|
||||
}
|
||||
|
||||
const schedule = await stripe.subscriptionSchedules.retrieve(
|
||||
typeof subscription.schedule === 'string'
|
||||
? subscription.schedule
|
||||
: subscription.schedule.id,
|
||||
)
|
||||
const now = Date.now() / 1000
|
||||
const activeSubscriptionPhases = schedule.phases.filter(p => {
|
||||
return p.end_date > now && p.start_date < now
|
||||
})
|
||||
|
||||
const updatedSchedule = await stripe.subscriptionSchedules.update(
|
||||
schedule.id,
|
||||
{
|
||||
phases: [
|
||||
...activeSubscriptionPhases.map(p => ({
|
||||
items: [
|
||||
{
|
||||
price:
|
||||
typeof p.items[0].price === 'string'
|
||||
? p.items[0].price
|
||||
: p.items[0].price.id,
|
||||
quantity: p.items[0].quantity,
|
||||
},
|
||||
],
|
||||
start_date: p.start_date,
|
||||
end_date: p.end_date,
|
||||
})),
|
||||
{
|
||||
items: [
|
||||
{
|
||||
price: newPriceId,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
iterations: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
return c.json({subscription: s, price, schedule: updatedSchedule})
|
||||
|
||||
// TODO get customer and compare DID to auth state to ensure it's legit
|
||||
/*
|
||||
const subscription = await stripe.subscriptions.update(
|
||||
subscriptionItem.subscription,
|
||||
{
|
||||
items: [
|
||||
{
|
||||
id: stripeSubscriptionId,
|
||||
deleted: true,
|
||||
},
|
||||
{
|
||||
price: newPriceId,
|
||||
},
|
||||
],
|
||||
proration_behavior: 'always_invoice',
|
||||
},
|
||||
)
|
||||
|
||||
return c.json({
|
||||
oldItem: subscriptionItem,
|
||||
subscription,
|
||||
})
|
||||
*/
|
||||
})
|
||||
|
||||
/**
|
||||
* Cancel a subscription (web only)
|
||||
*/
|
||||
.post(`/subscriptions/cancel`, async c => {
|
||||
const stripe = c.get('stripe')
|
||||
const {stripeSubscriptionId} = await c.req.json()
|
||||
const subscriptionItem = await stripe.subscriptionItems.retrieve(
|
||||
stripeSubscriptionId,
|
||||
)
|
||||
// TODO get customer and compare DID to auth state to ensure it's legit
|
||||
const subscription = await stripe.subscriptions.update(
|
||||
subscriptionItem.subscription,
|
||||
{
|
||||
cancel_at_period_end: true,
|
||||
},
|
||||
)
|
||||
|
||||
return c.json({
|
||||
oldItem: subscriptionItem,
|
||||
subscription,
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Get subscription products for a given offering
|
||||
*/
|
||||
.get('/subscriptions/:offering_lookup_key', async c => {
|
||||
const rc = c.get('rcv2')
|
||||
const {user, platform, currency} = c.req.query()
|
||||
const {offering_lookup_key} = c.req.param()
|
||||
|
||||
const {items} = await rc
|
||||
.get<{items: any[]}>(`offerings?expand=items.package.product`)
|
||||
.json()
|
||||
const offering = items.find(i => i.lookup_key == offering_lookup_key)
|
||||
|
||||
if (!offering) {
|
||||
throw new HTTPException(404, {message: `Offering not found`})
|
||||
}
|
||||
|
||||
const offeringProducts = offering.packages.items
|
||||
.flatMap((i: any) => i.products.items)
|
||||
.map((i: any) => i.product)
|
||||
let userSubscriptions: any[] = []
|
||||
|
||||
try {
|
||||
const {items} = await rc
|
||||
.get<{
|
||||
items: RevenueCatSubscription[]
|
||||
}>(`customers/${user}/subscriptions`)
|
||||
.json()
|
||||
userSubscriptions = items
|
||||
} catch (e) {}
|
||||
|
||||
let normalizedSubscriptions = normalizeSubscriptions(
|
||||
offeringProducts,
|
||||
userSubscriptions,
|
||||
)
|
||||
let activeSubscriptions = normalizedSubscriptions.filter(
|
||||
p => p.state?.active,
|
||||
)
|
||||
let platformSubscriptions = normalizedSubscriptions.filter(
|
||||
p => p.platform === platform,
|
||||
)
|
||||
|
||||
async function decorateWebProducts(subscriptions: Subscription[]) {
|
||||
const stripe = c.get('stripe')
|
||||
|
||||
const ids = subscriptions
|
||||
.filter(p => p.platform === 'web')
|
||||
.map(p => p.store.productId)
|
||||
const {data} = await stripe.products.list({ids})
|
||||
const prices = await Promise.all(
|
||||
data.map(p => {
|
||||
if (typeof p.default_price === 'string') {
|
||||
return stripe.prices.retrieve(p.default_price, {
|
||||
expand: ['currency_options'],
|
||||
})
|
||||
} else {
|
||||
return p.default_price
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
for (const price of prices) {
|
||||
if (!price) continue
|
||||
|
||||
// mutates for now
|
||||
for (const sub of subscriptions) {
|
||||
if (sub.platform !== 'web') continue
|
||||
|
||||
if (price.product === sub.store.productId) {
|
||||
const localizedPrice =
|
||||
price?.currency_options?.[currency || 'usd']?.unit_amount ||
|
||||
price.unit_amount
|
||||
sub.store.price = localizedPrice ?? 0
|
||||
sub.store.priceId = price.id
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subscriptions
|
||||
}
|
||||
|
||||
if (platform === 'web') {
|
||||
activeSubscriptions = await decorateWebProducts(activeSubscriptions)
|
||||
platformSubscriptions = await decorateWebProducts(platformSubscriptions)
|
||||
} else if (platform === 'ios') {
|
||||
activeSubscriptions = await decorateWebProducts(activeSubscriptions)
|
||||
} else if (platform === 'android') {
|
||||
activeSubscriptions = await decorateWebProducts(activeSubscriptions)
|
||||
}
|
||||
|
||||
return c.json({
|
||||
subscriptions: mergeSubscriptions(
|
||||
platformSubscriptions,
|
||||
activeSubscriptions,
|
||||
),
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Get entitlements for a user
|
||||
*/
|
||||
.get('/entitlements', async c => {
|
||||
const rc = c.get('rcv2')
|
||||
const user = c.req.query('user')
|
||||
|
||||
const {items: activeEntitlements} = await rc
|
||||
.get<{
|
||||
items: {entitlement_id: string}[]
|
||||
}>(`customers/${user}/active_entitlements`)
|
||||
.json()
|
||||
const entitlements = await Promise.all(
|
||||
activeEntitlements.map(e => {
|
||||
return rc.get(`entitlements/${e.entitlement_id}?expand=product`).json()
|
||||
}),
|
||||
)
|
||||
const normalized = normalizeEntitlements(entitlements)
|
||||
|
||||
return c.json({entitlements: normalized})
|
||||
})
|
||||
|
||||
/**
|
||||
* Create a Stripe checkout session (web only)
|
||||
*/
|
||||
.post('/createCheckout', async c => {
|
||||
const DOMAIN = `http://localhost:19006`
|
||||
const stripe = c.get('stripe')
|
||||
|
||||
const {price, user, email} = await c.req.json()
|
||||
|
||||
// TODO should store this in a db
|
||||
const customers = await stripe.customers.search({
|
||||
query: `email:"${email}"`,
|
||||
})
|
||||
|
||||
let customer: Stripe.Customer | undefined =
|
||||
customers.data.at(0)?.email === email ? customers.data[0] : undefined
|
||||
|
||||
if (!customer) {
|
||||
customer = await stripe.customers.create({
|
||||
email,
|
||||
metadata: {
|
||||
did: user,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const session = await stripe.checkout.sessions.create({
|
||||
client_reference_id: user,
|
||||
customer: customer.id,
|
||||
customer_update: {
|
||||
address: 'auto',
|
||||
name: 'auto',
|
||||
shipping: 'auto',
|
||||
},
|
||||
saved_payment_method_options: {
|
||||
payment_method_save: 'enabled',
|
||||
},
|
||||
line_items: [
|
||||
{
|
||||
price: price,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
mode: 'subscription',
|
||||
success_url: `${DOMAIN}/subscriptions?success=true`,
|
||||
cancel_url: `${DOMAIN}/subscriptions?canceled=true`,
|
||||
automatic_tax: {enabled: true},
|
||||
})
|
||||
|
||||
if (!session.url) {
|
||||
throw new HTTPException(400, {message: `Failed to create checkout`})
|
||||
}
|
||||
|
||||
return c.json({checkoutUrl: session.url})
|
||||
})
|
||||
|
||||
/**
|
||||
* Listen for Stripe webhooks
|
||||
* @see https://docs.stripe.com/webhooks#local-listener
|
||||
*/
|
||||
.post('/webhooks/stripe', async c => {
|
||||
const stripe = c.get('stripe')
|
||||
const rc = c.get('rcv1')
|
||||
|
||||
const {type, data} = await c.req.json()
|
||||
|
||||
if (type === 'customer.subscription.created') {
|
||||
const {object: sub} = data
|
||||
const customer = await stripe.customers.retrieve(sub.customer)
|
||||
|
||||
// immediately attach a schedule for later manipulation
|
||||
await stripe.subscriptionSchedules.create({
|
||||
from_subscription: sub.id,
|
||||
})
|
||||
|
||||
if (!customer.deleted) {
|
||||
const payload = {
|
||||
fetch_token: sub.id,
|
||||
app_user_id: customer.metadata.did,
|
||||
}
|
||||
try {
|
||||
const res = await rc
|
||||
.post(`receipts`, {
|
||||
json: payload,
|
||||
headers: {
|
||||
'X-Platform': 'stripe',
|
||||
},
|
||||
})
|
||||
.json()
|
||||
console.log(`success`, res)
|
||||
} catch (e) {
|
||||
console.error(`failed to send receipt`, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.text('ok')
|
||||
})
|
||||
@@ -0,0 +1,400 @@
|
||||
/**
|
||||
* @see https://www.revenuecat.com/docs/api-v2#tag/Product/operation/list-products
|
||||
*/
|
||||
export type RevenueCatProduct = {
|
||||
id: string
|
||||
object: 'product'
|
||||
store_identifier: string
|
||||
type: 'subscription'
|
||||
app:
|
||||
| {
|
||||
type: 'stripe'
|
||||
id: string
|
||||
project_id: string
|
||||
stripe: {
|
||||
stripe_account_id: string
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: 'play_store'
|
||||
id: string
|
||||
project_id: string
|
||||
play_store: {
|
||||
package_name: string
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: 'app_store'
|
||||
id: string
|
||||
project_id: string
|
||||
app_store: {
|
||||
bundle_id: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.revenuecat.com/docs/api-v2#tag/Customer/operation/list-subscriptions
|
||||
*/
|
||||
export type RevenueCatSubscription = {
|
||||
id: string
|
||||
product_id: 'prodc783cb31d8'
|
||||
environment: 'sandbox'
|
||||
status:
|
||||
| 'trialing'
|
||||
| 'active'
|
||||
| 'expired'
|
||||
| 'in_grace_period'
|
||||
| 'in_billing_retry'
|
||||
| 'paused'
|
||||
| 'unknown'
|
||||
| 'incomplete'
|
||||
store: 'stripe' | 'play_store' | 'app_store'
|
||||
object: 'subscription'
|
||||
auto_renewal_status:
|
||||
| 'will_renew'
|
||||
| 'will_not_renew'
|
||||
| 'will_change_product'
|
||||
| 'will_pause'
|
||||
| 'requires_price_increase_consent'
|
||||
| 'has_already_renewed'
|
||||
starts_at: number
|
||||
current_period_ends_at: number
|
||||
current_period_starts_at: number
|
||||
customer_id: string // DID
|
||||
original_customer_id: string // should be DID, may be anon
|
||||
entitlements: {
|
||||
items: {
|
||||
created_at: number
|
||||
display_name: string
|
||||
id: string
|
||||
lookup_key: string
|
||||
object: 'entitlement'
|
||||
project_id: string
|
||||
}[]
|
||||
next_page: null
|
||||
object: 'list'
|
||||
url: string
|
||||
}
|
||||
management_url: unknown
|
||||
gives_access: boolean
|
||||
store_subscription_identifier: string
|
||||
}
|
||||
|
||||
export enum SubscriptionId {
|
||||
Main0MonthlyAuto = 'main:0:monthly:auto',
|
||||
Main0AnnualAuto = 'main:0:annual:auto',
|
||||
Main1MonthlyAuto = 'main:1:monthly:auto',
|
||||
Main1AnnualAuto = 'main:1:annual:auto',
|
||||
Main2MonthlyAuto = 'main:2:monthly:auto',
|
||||
Main2AnnualAuto = 'main:2:annual:auto',
|
||||
}
|
||||
|
||||
export enum EntitlementId {
|
||||
Main0 = 'main:0',
|
||||
Main1 = 'main:1',
|
||||
Main2 = 'main:2',
|
||||
}
|
||||
|
||||
export type Entitlement = {
|
||||
id: EntitlementId
|
||||
}
|
||||
|
||||
export type SubscriptionState = {
|
||||
platform: 'web' | 'android' | 'ios'
|
||||
active: boolean
|
||||
entitlements: {id: EntitlementId}[]
|
||||
status:
|
||||
| 'trialing'
|
||||
| 'active'
|
||||
| 'expired'
|
||||
| 'in_grace_period'
|
||||
| 'in_billing_retry'
|
||||
| 'paused'
|
||||
| 'unknown'
|
||||
| 'incomplete'
|
||||
renewalStatus:
|
||||
| 'will_renew'
|
||||
| 'will_not_renew'
|
||||
| 'will_change_product'
|
||||
| 'will_pause'
|
||||
| 'requires_price_increase_consent'
|
||||
| 'has_already_renewed'
|
||||
startedAt: number
|
||||
periodStart: number
|
||||
periodEnd: number
|
||||
}
|
||||
|
||||
export type Subscription =
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'android' | 'ios'
|
||||
interval: 'monthly' | 'annual'
|
||||
state?: SubscriptionState
|
||||
store: {
|
||||
type: 'play_store' | 'app_store'
|
||||
productId: string
|
||||
productLookupKey: string
|
||||
}
|
||||
}
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'web'
|
||||
interval: 'monthly' | 'annual'
|
||||
state: undefined
|
||||
store: {
|
||||
type: 'stripe'
|
||||
productId: string
|
||||
price: number
|
||||
priceId: string
|
||||
subscriptionId: undefined
|
||||
}
|
||||
}
|
||||
| {
|
||||
id: SubscriptionId
|
||||
platform: 'web'
|
||||
interval: 'monthly' | 'annual'
|
||||
state: SubscriptionState
|
||||
store: {
|
||||
type: 'stripe'
|
||||
productId: string
|
||||
price: number
|
||||
priceId: string
|
||||
subscriptionId: string
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeSubscriptions(
|
||||
products: RevenueCatProduct[],
|
||||
subscriptions: RevenueCatSubscription[],
|
||||
): Subscription[] {
|
||||
// should always be subscriptions, but guard here
|
||||
const subscriptionProducts = products.filter(
|
||||
product => product.type === 'subscription',
|
||||
)
|
||||
|
||||
const normalized: Subscription[] = []
|
||||
|
||||
for (const product of subscriptionProducts) {
|
||||
/**
|
||||
* Matches product ID and gives user access (is active)
|
||||
* @see https://www.revenuecat.com/docs/api-v2#tag/Customer/operation/list-subscriptions
|
||||
*/
|
||||
const subscription = subscriptions.find(
|
||||
s => s.product_id === product.id && s.gives_access,
|
||||
)
|
||||
|
||||
const id = normalizeSubscriptionId(product.store_identifier)
|
||||
if (!id) continue
|
||||
const platform = getSubscriptionPlatform(product.store_identifier)
|
||||
const state = subscription
|
||||
? getSubscriptionState(subscription, {platform})
|
||||
: undefined
|
||||
const interval = getSubscriptionInterval(id)
|
||||
|
||||
if (platform === 'web') {
|
||||
if (state) {
|
||||
normalized.push({
|
||||
id,
|
||||
platform,
|
||||
interval,
|
||||
state,
|
||||
store: {
|
||||
type: 'stripe',
|
||||
price: 0,
|
||||
productId: product.store_identifier,
|
||||
priceId: '',
|
||||
subscriptionId: subscription?.store_subscription_identifier!,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
normalized.push({
|
||||
id,
|
||||
platform,
|
||||
interval,
|
||||
state,
|
||||
store: {
|
||||
type: 'stripe',
|
||||
productId: product.store_identifier,
|
||||
price: 0,
|
||||
priceId: '',
|
||||
subscriptionId: undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
normalized.push({
|
||||
id,
|
||||
platform,
|
||||
interval,
|
||||
state,
|
||||
store: {
|
||||
type: platform === 'android' ? 'play_store' : 'app_store',
|
||||
productId: product.store_identifier,
|
||||
productLookupKey: getProductLookupKey(product.store_identifier),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
export function mergeSubscriptions(
|
||||
all: Subscription[],
|
||||
active: Subscription[],
|
||||
): Subscription[] {
|
||||
const merged: Subscription[] = []
|
||||
|
||||
for (const s of all) {
|
||||
const a = active.find(p => p.id === s.id)
|
||||
if (a) {
|
||||
// @ts-ignore
|
||||
merged.push({...s, state: a.state})
|
||||
} else {
|
||||
merged.push(s)
|
||||
}
|
||||
}
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
export function getSubscriptionInterval(
|
||||
id: SubscriptionId,
|
||||
): 'monthly' | 'annual' {
|
||||
switch (id) {
|
||||
case SubscriptionId.Main0MonthlyAuto:
|
||||
case SubscriptionId.Main1MonthlyAuto:
|
||||
case SubscriptionId.Main2MonthlyAuto:
|
||||
return 'monthly'
|
||||
case SubscriptionId.Main0AnnualAuto:
|
||||
case SubscriptionId.Main1AnnualAuto:
|
||||
case SubscriptionId.Main2AnnualAuto:
|
||||
return 'annual'
|
||||
}
|
||||
}
|
||||
|
||||
export function getSubscriptionState(
|
||||
subscription: RevenueCatSubscription,
|
||||
options: {
|
||||
platform: 'web' | 'android' | 'ios'
|
||||
},
|
||||
): SubscriptionState {
|
||||
return {
|
||||
platform: options.platform,
|
||||
active: subscription.gives_access,
|
||||
status: subscription.status,
|
||||
renewalStatus: subscription.auto_renewal_status,
|
||||
entitlements: normalizeEntitlements(subscription.entitlements.items),
|
||||
startedAt: subscription.starts_at,
|
||||
periodStart: subscription.current_period_starts_at,
|
||||
periodEnd: subscription.current_period_ends_at,
|
||||
}
|
||||
}
|
||||
|
||||
export function getSubscriptionPlatform(id: string): 'web' | 'android' | 'ios' {
|
||||
switch (id) {
|
||||
case 'prod_R2eNjNa6mB1Jlu':
|
||||
case 'prod_R37Zg28EeQ9XAz':
|
||||
case 'prod_R67eiEMuIf59w7':
|
||||
case 'prod_R67fjfexQ7THQ0':
|
||||
case 'prod_R67ftsSVu2U1D6':
|
||||
case 'prod_R67gClEZy1cry2': {
|
||||
return 'web'
|
||||
}
|
||||
case 'bsky_tier_0:monthly-auto':
|
||||
case 'bsky_tier_0:annual-auto':
|
||||
case 'bsky_tier_1:monthly-auto':
|
||||
case 'bsky_tier_1:annual-auto':
|
||||
case 'bsky_tier_2:monthly-auto':
|
||||
case 'bsky_tier_2:annual-auto': {
|
||||
return 'android'
|
||||
}
|
||||
case 'bsky_tier_0_monthly':
|
||||
case 'bsky_tier_0_annual':
|
||||
case 'bsky_tier_1_monthly':
|
||||
case 'bsky_tier_1_annual':
|
||||
case 'bsky_tier_2_monthly':
|
||||
case 'bsky_tier_2_annual': {
|
||||
return 'ios'
|
||||
}
|
||||
default: {
|
||||
throw new Error(`Unknown product ID: ${id}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getProductLookupKey(id: string): string {
|
||||
switch (id) {
|
||||
case 'bsky_tier_0:monthly-auto':
|
||||
case 'bsky_tier_0:annual-auto':
|
||||
return 'bsky_tier_0'
|
||||
case 'bsky_tier_1:monthly-auto':
|
||||
case 'bsky_tier_1:annual-auto':
|
||||
return 'bsky_tier_1'
|
||||
case 'bsky_tier_2:monthly-auto':
|
||||
case 'bsky_tier_2:annual-auto':
|
||||
return 'bsky_tier_2'
|
||||
default:
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeSubscriptionId(
|
||||
id: string,
|
||||
): SubscriptionId | undefined {
|
||||
switch (id) {
|
||||
case 'bsky_tier_0_monthly':
|
||||
case 'bsky_tier_0:monthly-auto':
|
||||
case 'prod_R2eNjNa6mB1Jlu':
|
||||
return SubscriptionId.Main0MonthlyAuto
|
||||
case 'bsky_tier_0_annual':
|
||||
case 'bsky_tier_0:annual-auto':
|
||||
case 'prod_R37Zg28EeQ9XAz':
|
||||
return SubscriptionId.Main0AnnualAuto
|
||||
case 'bsky_tier_1_monthly':
|
||||
case 'bsky_tier_1:monthly-auto':
|
||||
case 'prod_R67eiEMuIf59w7':
|
||||
return SubscriptionId.Main1MonthlyAuto
|
||||
case 'bsky_tier_1_annual':
|
||||
case 'bsky_tier_1:annual-auto':
|
||||
case 'prod_R67fjfexQ7THQ0':
|
||||
return SubscriptionId.Main1AnnualAuto
|
||||
case 'bsky_tier_2_monthly':
|
||||
case 'bsky_tier_2:monthly-auto':
|
||||
case 'prod_R67ftsSVu2U1D6':
|
||||
return SubscriptionId.Main2MonthlyAuto
|
||||
case 'bsky_tier_2_annual':
|
||||
case 'bsky_tier_2:annual-auto':
|
||||
case 'prod_R67gClEZy1cry2':
|
||||
return SubscriptionId.Main2AnnualAuto
|
||||
default: {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeEntitlements(entitlements: any[]) {
|
||||
return entitlements.map(entitlement => {
|
||||
let id = EntitlementId.Main0
|
||||
|
||||
switch (entitlement.lookup_key) {
|
||||
case 'main:0': {
|
||||
id = EntitlementId.Main0
|
||||
break
|
||||
}
|
||||
case 'main:1': {
|
||||
id = EntitlementId.Main1
|
||||
break
|
||||
}
|
||||
case 'main:2': {
|
||||
id = EntitlementId.Main2
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"include": ["src", "env.d.ts"],
|
||||
"compilerOptions": {
|
||||
"types": ["@cloudflare/workers-types"],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": ["src/*"]
|
||||
},
|
||||
"strict": true,
|
||||
"target": "es2021",
|
||||
"lib": ["es2021"],
|
||||
"module": "es2022",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitReturns": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
name = "purchases"
|
||||
main = "src/index.ts"
|
||||
|
||||
account_id = '8443bac20f1f475b04c034a0d98c7ed9'
|
||||
compatibility_date = "2024-09-06"
|
||||
# route = 'worker.com/*'
|
||||
@@ -0,0 +1,827 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@cloudflare/kv-asset-handler@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz#5cc152847c8ae4d280ec5d7f4f6ba8c976b585c3"
|
||||
integrity sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==
|
||||
dependencies:
|
||||
mime "^3.0.0"
|
||||
|
||||
"@cloudflare/workerd-darwin-64@1.20241022.0":
|
||||
version "1.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241022.0.tgz#1d22149152ad32672971e3be48ab1491ff236eb3"
|
||||
integrity sha512-1NNYun37myMTgCUiPQEJ0cMal4mKZVTpkD0b2tx9hV70xji+frVJcSK8YVLeUm1P+Rw1d/ct8DMgQuCpsz3Fsw==
|
||||
|
||||
"@cloudflare/workerd-darwin-arm64@1.20241022.0":
|
||||
version "1.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241022.0.tgz#6ec4e4fd1427ac09d9cfea38db849799755029e5"
|
||||
integrity sha512-FOO/0P0U82EsTLTdweNVgw+4VOk5nghExLPLSppdOziq6IR5HVgP44Kmq5LdsUeHUhwUmfOh9hzaTpkNzUqKvw==
|
||||
|
||||
"@cloudflare/workerd-linux-64@1.20241022.0":
|
||||
version "1.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241022.0.tgz#0297222e46ce8b2c55b591ae87ee2bbb85830e20"
|
||||
integrity sha512-RsNc19BQJG9yd+ngnjuDeG9ywZG+7t1L4JeglgceyY5ViMNMKVO7Zpbsu69kXslU9h6xyQG+lrmclg3cBpnhYA==
|
||||
|
||||
"@cloudflare/workerd-linux-arm64@1.20241022.0":
|
||||
version "1.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241022.0.tgz#7637092b14129c94ddb87990221d38623e4fd498"
|
||||
integrity sha512-x5mUXpKxfsosxcFmcq5DaqLs37PejHYVRsNz1cWI59ma7aC4y4Qn6Tf3i0r9MwQTF/MccP4SjVslMU6m4W7IaA==
|
||||
|
||||
"@cloudflare/workerd-windows-64@1.20241022.0":
|
||||
version "1.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241022.0.tgz#64f05a2bc475e1450154942c060555184e6350de"
|
||||
integrity sha512-eBCClx4szCOgKqOlxxbdNszMqQf3MRG1B9BRIqEM/diDfdR9IrZ8l3FaEm+l9gXgPmS6m1NBn40aWuGBl8UTSw==
|
||||
|
||||
"@cloudflare/workers-shared@0.7.0":
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.7.0.tgz#ecb6a3a1f483989c1ca10d5ed0592d01c7eff0c0"
|
||||
integrity sha512-LLQRTqx7lKC7o2eCYMpyc5FXV8d0pUX6r3A+agzhqS9aoR5A6zCPefwQGcvbKx83ozX22ATZcemwxQXn12UofQ==
|
||||
dependencies:
|
||||
mime "^3.0.0"
|
||||
zod "^3.22.3"
|
||||
|
||||
"@cloudflare/workers-types@^4.20240903.0":
|
||||
version "4.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20241022.0.tgz#4f751ec29b9a2a0cef83bdc797b02089462ee48d"
|
||||
integrity sha512-1zOAw5QIDKItzGatzCrEpfLOB1AuMTwVqKmbw9B9eBfCUGRFNfJYMrJxIwcse9EmKahsQt2GruqU00pY/GyXgg==
|
||||
|
||||
"@cspotcode/source-map-support@0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
|
||||
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@esbuild-plugins/node-globals-polyfill@^0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz#0e4497a2b53c9e9485e149bc92ddb228438d6bcf"
|
||||
integrity sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==
|
||||
|
||||
"@esbuild-plugins/node-modules-polyfill@^0.2.2":
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz#cefa3dc0bd1c16277a8338b52833420c94987327"
|
||||
integrity sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==
|
||||
dependencies:
|
||||
escape-string-regexp "^4.0.0"
|
||||
rollup-plugin-node-polyfills "^0.2.1"
|
||||
|
||||
"@esbuild/android-arm64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd"
|
||||
integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==
|
||||
|
||||
"@esbuild/android-arm@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d"
|
||||
integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==
|
||||
|
||||
"@esbuild/android-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1"
|
||||
integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==
|
||||
|
||||
"@esbuild/darwin-arm64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276"
|
||||
integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==
|
||||
|
||||
"@esbuild/darwin-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb"
|
||||
integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2"
|
||||
integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==
|
||||
|
||||
"@esbuild/freebsd-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4"
|
||||
integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==
|
||||
|
||||
"@esbuild/linux-arm64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb"
|
||||
integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==
|
||||
|
||||
"@esbuild/linux-arm@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a"
|
||||
integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==
|
||||
|
||||
"@esbuild/linux-ia32@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a"
|
||||
integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==
|
||||
|
||||
"@esbuild/linux-loong64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72"
|
||||
integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==
|
||||
|
||||
"@esbuild/linux-mips64el@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289"
|
||||
integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==
|
||||
|
||||
"@esbuild/linux-ppc64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7"
|
||||
integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==
|
||||
|
||||
"@esbuild/linux-riscv64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09"
|
||||
integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==
|
||||
|
||||
"@esbuild/linux-s390x@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829"
|
||||
integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==
|
||||
|
||||
"@esbuild/linux-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4"
|
||||
integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462"
|
||||
integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==
|
||||
|
||||
"@esbuild/openbsd-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691"
|
||||
integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==
|
||||
|
||||
"@esbuild/sunos-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273"
|
||||
integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==
|
||||
|
||||
"@esbuild/win32-arm64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f"
|
||||
integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==
|
||||
|
||||
"@esbuild/win32-ia32@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03"
|
||||
integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==
|
||||
|
||||
"@esbuild/win32-x64@0.17.19":
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061"
|
||||
integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==
|
||||
|
||||
"@fastify/busboy@^2.0.0":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d"
|
||||
integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==
|
||||
|
||||
"@jridgewell/resolve-uri@^3.0.3":
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
|
||||
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
|
||||
|
||||
"@jridgewell/trace-mapping@0.3.9":
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@types/node-forge@^1.3.0":
|
||||
version "1.3.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
|
||||
integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@>=8.1.0":
|
||||
version "22.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.8.1.tgz#b39d4b98165e2ae792ce213f610c7c6108ccfa16"
|
||||
integrity sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==
|
||||
dependencies:
|
||||
undici-types "~6.19.8"
|
||||
|
||||
acorn-walk@^8.2.0:
|
||||
version "8.3.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7"
|
||||
integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==
|
||||
dependencies:
|
||||
acorn "^8.11.0"
|
||||
|
||||
acorn@^8.11.0, acorn@^8.8.0:
|
||||
version "8.13.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.13.0.tgz#2a30d670818ad16ddd6a35d3842dacec9e5d7ca3"
|
||||
integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==
|
||||
|
||||
anymatch@~3.1.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
|
||||
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
|
||||
dependencies:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
as-table@^1.0.36:
|
||||
version "1.0.55"
|
||||
resolved "https://registry.yarnpkg.com/as-table/-/as-table-1.0.55.tgz#dc984da3937745de902cea1d45843c01bdbbec4f"
|
||||
integrity sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==
|
||||
dependencies:
|
||||
printable-characters "^1.0.42"
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
|
||||
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
|
||||
|
||||
blake3-wasm@^2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/blake3-wasm/-/blake3-wasm-2.1.5.tgz#b22dbb84bc9419ed0159caa76af4b1b132e6ba52"
|
||||
integrity sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==
|
||||
|
||||
braces@~3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
dependencies:
|
||||
fill-range "^7.1.1"
|
||||
|
||||
call-bind@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
|
||||
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
set-function-length "^1.2.1"
|
||||
|
||||
capnp-ts@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/capnp-ts/-/capnp-ts-0.7.0.tgz#16fd8e76b667d002af8fcf4bf92bf15d1a7b54a9"
|
||||
integrity sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==
|
||||
dependencies:
|
||||
debug "^4.3.1"
|
||||
tslib "^2.2.0"
|
||||
|
||||
chokidar@^3.5.3:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
cookie@^0.7.1:
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7"
|
||||
integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==
|
||||
|
||||
data-uri-to-buffer@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz#d296973d5a4897a5dbe31716d118211921f04770"
|
||||
integrity sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==
|
||||
|
||||
date-fns@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14"
|
||||
integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
|
||||
|
||||
debug@^4.3.1:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
|
||||
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
define-data-property@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
|
||||
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.0.1"
|
||||
|
||||
defu@^6.1.4:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
|
||||
integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
|
||||
dependencies:
|
||||
get-intrinsic "^1.2.4"
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
esbuild@0.17.19:
|
||||
version "0.17.19"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955"
|
||||
integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.17.19"
|
||||
"@esbuild/android-arm64" "0.17.19"
|
||||
"@esbuild/android-x64" "0.17.19"
|
||||
"@esbuild/darwin-arm64" "0.17.19"
|
||||
"@esbuild/darwin-x64" "0.17.19"
|
||||
"@esbuild/freebsd-arm64" "0.17.19"
|
||||
"@esbuild/freebsd-x64" "0.17.19"
|
||||
"@esbuild/linux-arm" "0.17.19"
|
||||
"@esbuild/linux-arm64" "0.17.19"
|
||||
"@esbuild/linux-ia32" "0.17.19"
|
||||
"@esbuild/linux-loong64" "0.17.19"
|
||||
"@esbuild/linux-mips64el" "0.17.19"
|
||||
"@esbuild/linux-ppc64" "0.17.19"
|
||||
"@esbuild/linux-riscv64" "0.17.19"
|
||||
"@esbuild/linux-s390x" "0.17.19"
|
||||
"@esbuild/linux-x64" "0.17.19"
|
||||
"@esbuild/netbsd-x64" "0.17.19"
|
||||
"@esbuild/openbsd-x64" "0.17.19"
|
||||
"@esbuild/sunos-x64" "0.17.19"
|
||||
"@esbuild/win32-arm64" "0.17.19"
|
||||
"@esbuild/win32-ia32" "0.17.19"
|
||||
"@esbuild/win32-x64" "0.17.19"
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
estree-walker@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
||||
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
||||
|
||||
exit-hook@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.1.tgz#007b2d92c6428eda2b76e7016a34351586934593"
|
||||
integrity sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==
|
||||
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
hasown "^2.0.0"
|
||||
|
||||
get-source@^2.0.12:
|
||||
version "2.0.12"
|
||||
resolved "https://registry.yarnpkg.com/get-source/-/get-source-2.0.12.tgz#0b47d57ea1e53ce0d3a69f4f3d277eb8047da944"
|
||||
integrity sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==
|
||||
dependencies:
|
||||
data-uri-to-buffer "^2.0.0"
|
||||
source-map "^0.6.1"
|
||||
|
||||
glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob-to-regexp@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
||||
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
|
||||
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
|
||||
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
|
||||
|
||||
has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
|
||||
hasown@^2.0.0, hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
hono@^4.5.11:
|
||||
version "4.6.7"
|
||||
resolved "https://registry.yarnpkg.com/hono/-/hono-4.6.7.tgz#5389be797be4e049991d29ad7aea499e70d28085"
|
||||
integrity sha512-wX4ZbOnzfNO61hUjuQbJ7OPGs1fWXXVVJ8VTPDb2Ls/x9HjCbVTm80Je6VTHMz5n5RGDtBgV9d9ZFZxBqx56ng==
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-core-module@^2.13.0:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37"
|
||||
integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==
|
||||
dependencies:
|
||||
hasown "^2.0.2"
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||
|
||||
is-glob@^4.0.1, is-glob@~4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
itty-time@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/itty-time/-/itty-time-1.0.6.tgz#a6eeda619f19d2f4c480ceddd013b93acb05714d"
|
||||
integrity sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==
|
||||
|
||||
ky@^1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/ky/-/ky-1.7.2.tgz#b97d9b997ba51ff1e152f0815d3d27b86513eb1c"
|
||||
integrity sha512-OzIvbHKKDpi60TnF9t7UUVAF1B4mcqc02z5PIvrm08Wyb+yOcz63GRvEuVxNT18a9E1SrNouhB4W2NNLeD7Ykg==
|
||||
|
||||
magic-string@^0.25.3:
|
||||
version "0.25.9"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
|
||||
dependencies:
|
||||
sourcemap-codec "^1.4.8"
|
||||
|
||||
mime@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
|
||||
integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
|
||||
|
||||
miniflare@3.20241022.0:
|
||||
version "3.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20241022.0.tgz#31b8a2bc53b411ac814b55db9c31aebfe475f344"
|
||||
integrity sha512-x9Fbq1Hmz1f0osIT9Qmj78iX4UpCP2EqlZnA/tzj/3+I49vc3Kq0fNqSSKplcdf6HlCHdL3fOBicmreQF4BUUQ==
|
||||
dependencies:
|
||||
"@cspotcode/source-map-support" "0.8.1"
|
||||
acorn "^8.8.0"
|
||||
acorn-walk "^8.2.0"
|
||||
capnp-ts "^0.7.0"
|
||||
exit-hook "^2.2.1"
|
||||
glob-to-regexp "^0.4.1"
|
||||
stoppable "^1.1.0"
|
||||
undici "^5.28.4"
|
||||
workerd "1.20241022.0"
|
||||
ws "^8.17.1"
|
||||
youch "^3.2.2"
|
||||
zod "^3.22.3"
|
||||
|
||||
ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
mustache@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64"
|
||||
integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==
|
||||
|
||||
nanoid@^3.3.3:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
node-forge@^1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
||||
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
object-inspect@^1.13.1:
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
|
||||
integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==
|
||||
|
||||
ohash@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.4.tgz#ae8d83014ab81157d2c285abf7792e2995fadd72"
|
||||
integrity sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==
|
||||
|
||||
path-parse@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
path-to-regexp@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4"
|
||||
integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==
|
||||
|
||||
pathe@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
|
||||
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
prettier@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105"
|
||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||
|
||||
printable-characters@^1.0.42:
|
||||
version "1.0.42"
|
||||
resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8"
|
||||
integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==
|
||||
|
||||
qs@^6.11.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
|
||||
dependencies:
|
||||
side-channel "^1.0.6"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
resolve.exports@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800"
|
||||
integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==
|
||||
|
||||
resolve@^1.22.8:
|
||||
version "1.22.8"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
|
||||
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
|
||||
dependencies:
|
||||
is-core-module "^2.13.0"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
rollup-plugin-inject@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz#e4233855bfba6c0c12a312fd6649dff9a13ee9f4"
|
||||
integrity sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==
|
||||
dependencies:
|
||||
estree-walker "^0.6.1"
|
||||
magic-string "^0.25.3"
|
||||
rollup-pluginutils "^2.8.1"
|
||||
|
||||
rollup-plugin-node-polyfills@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz#53092a2744837164d5b8a28812ba5f3ff61109fd"
|
||||
integrity sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==
|
||||
dependencies:
|
||||
rollup-plugin-inject "^3.0.0"
|
||||
|
||||
rollup-pluginutils@^2.8.1:
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
|
||||
integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
|
||||
dependencies:
|
||||
estree-walker "^0.6.1"
|
||||
|
||||
selfsigned@^2.0.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0"
|
||||
integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==
|
||||
dependencies:
|
||||
"@types/node-forge" "^1.3.0"
|
||||
node-forge "^1"
|
||||
|
||||
set-function-length@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
|
||||
dependencies:
|
||||
define-data-property "^1.1.4"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
gopd "^1.0.1"
|
||||
has-property-descriptors "^1.0.2"
|
||||
|
||||
side-channel@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
|
||||
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
|
||||
dependencies:
|
||||
call-bind "^1.0.7"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
object-inspect "^1.13.1"
|
||||
|
||||
source-map@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sourcemap-codec@^1.4.8:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||
|
||||
stacktracey@^2.1.8:
|
||||
version "2.1.8"
|
||||
resolved "https://registry.yarnpkg.com/stacktracey/-/stacktracey-2.1.8.tgz#bf9916020738ce3700d1323b32bd2c91ea71199d"
|
||||
integrity sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==
|
||||
dependencies:
|
||||
as-table "^1.0.36"
|
||||
get-source "^2.0.12"
|
||||
|
||||
stoppable@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b"
|
||||
integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==
|
||||
|
||||
stripe@^17.2.1:
|
||||
version "17.2.1"
|
||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-17.2.1.tgz#8f1ea25c31df92245e5747e121ca0fe1e90f1c2e"
|
||||
integrity sha512-Mwb0SitV/UjxTLSUiTlUQ0VDE/gfyQ7OHDGdvDdvKIH4CNNqobPKlzlWhoZHFFU0OA/YsZyBtPULK4JG86BAAg==
|
||||
dependencies:
|
||||
"@types/node" ">=8.1.0"
|
||||
qs "^6.11.0"
|
||||
|
||||
supports-preserve-symlinks-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tslib@^2.2.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b"
|
||||
integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==
|
||||
|
||||
typescript@^5.5.4:
|
||||
version "5.6.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b"
|
||||
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
|
||||
|
||||
ufo@^1.5.4:
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754"
|
||||
integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==
|
||||
|
||||
undici-types@~6.19.8:
|
||||
version "6.19.8"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
||||
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
||||
|
||||
undici@^5.28.4:
|
||||
version "5.28.4"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068"
|
||||
integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==
|
||||
dependencies:
|
||||
"@fastify/busboy" "^2.0.0"
|
||||
|
||||
"unenv@npm:unenv-nightly@2.0.0-20241018-011344-e666fcf":
|
||||
version "2.0.0-20241018-011344-e666fcf"
|
||||
resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-2.0.0-20241018-011344-e666fcf.tgz#75b6d1ab37e6b5edeec80fe8f403e3de8e9bc50e"
|
||||
integrity sha512-D00bYn8rzkCBOlLx+k1iHQlc69jvtJRT7Eek4yIGQ6461a2tUBjngGZdRpqsoXAJCz/qBW0NgPting7Zvg+ysg==
|
||||
dependencies:
|
||||
defu "^6.1.4"
|
||||
ohash "^1.1.4"
|
||||
pathe "^1.1.2"
|
||||
ufo "^1.5.4"
|
||||
|
||||
workerd@1.20241022.0:
|
||||
version "1.20241022.0"
|
||||
resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20241022.0.tgz#45ab10642009b4573ae78df784e0a8c5b338914e"
|
||||
integrity sha512-jyGXsgO9DRcJyx6Ovv7gUyDPc3UYC2i/E0p9GFUg6GUzpldw4Y93y9kOmdfsOnKZ3+lY53veSiUniiBPE6Q2NQ==
|
||||
optionalDependencies:
|
||||
"@cloudflare/workerd-darwin-64" "1.20241022.0"
|
||||
"@cloudflare/workerd-darwin-arm64" "1.20241022.0"
|
||||
"@cloudflare/workerd-linux-64" "1.20241022.0"
|
||||
"@cloudflare/workerd-linux-arm64" "1.20241022.0"
|
||||
"@cloudflare/workerd-windows-64" "1.20241022.0"
|
||||
|
||||
wrangler@^3.75.0:
|
||||
version "3.83.0"
|
||||
resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.83.0.tgz#bebe3d0067f3430cf6f0b2e8e4ab648c208e002b"
|
||||
integrity sha512-qDzdUuTngKqmm2OJUZm7Gk4+Hv37F2nNNAHuhIgItEIhxBdOVDsgKmvpd+f41MFxyuGg3fbGWYANHI+0V2Z5yw==
|
||||
dependencies:
|
||||
"@cloudflare/kv-asset-handler" "0.3.4"
|
||||
"@cloudflare/workers-shared" "0.7.0"
|
||||
"@esbuild-plugins/node-globals-polyfill" "^0.2.3"
|
||||
"@esbuild-plugins/node-modules-polyfill" "^0.2.2"
|
||||
blake3-wasm "^2.1.5"
|
||||
chokidar "^3.5.3"
|
||||
date-fns "^4.1.0"
|
||||
esbuild "0.17.19"
|
||||
itty-time "^1.0.6"
|
||||
miniflare "3.20241022.0"
|
||||
nanoid "^3.3.3"
|
||||
path-to-regexp "^6.3.0"
|
||||
resolve "^1.22.8"
|
||||
resolve.exports "^2.0.2"
|
||||
selfsigned "^2.0.1"
|
||||
source-map "^0.6.1"
|
||||
unenv "npm:unenv-nightly@2.0.0-20241018-011344-e666fcf"
|
||||
workerd "1.20241022.0"
|
||||
xxhash-wasm "^1.0.1"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
ws@^8.17.1:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
|
||||
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
|
||||
|
||||
xxhash-wasm@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz#ecc0f813219b727af4d5f3958ca6becee2f2f1ff"
|
||||
integrity sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==
|
||||
|
||||
youch@^3.2.2:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/youch/-/youch-3.3.4.tgz#f13ee0966846c6200e7fb9ece89306d95df5e489"
|
||||
integrity sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==
|
||||
dependencies:
|
||||
cookie "^0.7.1"
|
||||
mustache "^4.2.0"
|
||||
stacktracey "^2.1.8"
|
||||
|
||||
zod@^3.22.3:
|
||||
version "3.23.8"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
@@ -5942,6 +5942,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@remirror/core-constants/-/core-constants-2.0.2.tgz#f05eccdc69e3a65e7d524b52548f567904a11a1a"
|
||||
integrity sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==
|
||||
|
||||
"@revenuecat/purchases-typescript-internal@13.4.0":
|
||||
version "13.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@revenuecat/purchases-typescript-internal/-/purchases-typescript-internal-13.4.0.tgz#e95c29e7c44c281022d1d2eb6fef67f62249f945"
|
||||
integrity sha512-y3+tUEhBs7kcqd6pAQnX1x2rGfztCYAPzyzGR7gHgVKeBsGIu18GpokhjqzzxyJD/bNXJICwhnj4R4omf8KHmw==
|
||||
|
||||
"@rnx-kit/chromium-edge-launcher@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#c0df8ea00a902c7a417cd9655aab06de398b939c"
|
||||
@@ -18153,6 +18158,13 @@ react-native-progress@bluesky-social/react-native-progress:
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-native-purchases@^8.2.3:
|
||||
version "8.2.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-purchases/-/react-native-purchases-8.2.3.tgz#8a4cb39ba5e15a8bc43cc33313b360e3dfa35139"
|
||||
integrity sha512-5iWhfhebOHekqskrvL22xiJPiED+260JakMDtApA8XekkbEo+ozUEDUZ56x+Z/Q5t4uJo4SPylKxSpT6nHQ/rg==
|
||||
dependencies:
|
||||
"@revenuecat/purchases-typescript-internal" "13.4.0"
|
||||
|
||||
react-native-qrcode-styled@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-qrcode-styled/-/react-native-qrcode-styled-0.3.1.tgz#be6a0fab173511b0d3d8d71588771c2230982dbf"
|
||||
|
||||
Reference in New Issue
Block a user