Add validate util
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@atproto/api": "0.14.0-next.6",
|
||||
"@atproto/lexicon": "0.4.6-next.5",
|
||||
"@bitdrift/react-native": "^0.6.2",
|
||||
"@braintree/sanitize-url": "^6.0.2",
|
||||
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
|
||||
|
||||
@@ -4,11 +4,7 @@ import type ViewShot from 'react-native-view-shot'
|
||||
import {requestMediaLibraryPermissionsAsync} from 'expo-image-picker'
|
||||
import {createAssetAsync} from 'expo-media-library'
|
||||
import * as Sharing from 'expo-sharing'
|
||||
import {
|
||||
AppBskyGraphDefs,
|
||||
AppBskyGraphStarterpack,
|
||||
asPredicate,
|
||||
} from '@atproto/api'
|
||||
import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
@@ -22,6 +18,7 @@ import * as Dialog from '#/components/Dialog'
|
||||
import {DialogControlProps} from '#/components/Dialog'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {QrCode} from '#/components/StarterPack/QrCode'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export function QrCodeDialog({
|
||||
starterPack,
|
||||
@@ -82,8 +79,9 @@ export function QrCodeDialog({
|
||||
setIsProcessing(true)
|
||||
|
||||
if (
|
||||
!asPredicate(AppBskyGraphStarterpack.validateRecord)(
|
||||
!bsky.validate(
|
||||
starterPack.record,
|
||||
AppBskyGraphStarterpack.validateRecord,
|
||||
)
|
||||
) {
|
||||
return
|
||||
|
||||
@@ -4,9 +4,9 @@ import {
|
||||
AppBskyEmbedRecordWithMedia,
|
||||
AppBskyFeedDefs,
|
||||
AppBskyFeedPost,
|
||||
asPredicate,
|
||||
} from '@atproto/api'
|
||||
|
||||
import * as bsky from '#/types/bsky'
|
||||
import {isPostInLanguage} from '../../locale/helpers'
|
||||
import {FALLBACK_MARKER_POST} from './feed/home'
|
||||
import {ReasonFeedSource} from './feed/types'
|
||||
@@ -68,7 +68,7 @@ export class FeedViewPostsSlice {
|
||||
}
|
||||
if (
|
||||
!AppBskyFeedPost.isRecord(post.record) ||
|
||||
!asPredicate(AppBskyFeedPost.validateRecord)(post.record)
|
||||
!bsky.validate(post.record, AppBskyFeedPost.validateRecord)
|
||||
) {
|
||||
return
|
||||
}
|
||||
@@ -100,7 +100,7 @@ export class FeedViewPostsSlice {
|
||||
if (
|
||||
!AppBskyFeedDefs.isPostView(parent) ||
|
||||
!AppBskyFeedPost.isRecord(parent.record) ||
|
||||
!asPredicate(AppBskyFeedPost.validateRecord)(parent.record)
|
||||
!bsky.validate(parent.record, AppBskyFeedPost.validateRecord)
|
||||
) {
|
||||
this.isOrphan = true
|
||||
return
|
||||
@@ -142,7 +142,7 @@ export class FeedViewPostsSlice {
|
||||
if (
|
||||
!AppBskyFeedDefs.isPostView(root) ||
|
||||
!AppBskyFeedPost.isRecord(root.record) ||
|
||||
!asPredicate(AppBskyFeedPost.validateRecord)(root.record)
|
||||
!bsky.validate(root.record, AppBskyFeedPost.validateRecord)
|
||||
) {
|
||||
this.isOrphan = true
|
||||
return
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {$Typed, asPredicate,ComAtprotoLabelDefs} from '@atproto/api'
|
||||
import {$Typed, ComAtprotoLabelDefs} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
@@ -12,6 +12,7 @@ import {useSession} from '#/state/session'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import * as Toggle from '#/components/forms/Toggle'
|
||||
import {Text} from '#/components/Typography'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export function PwiOptOut() {
|
||||
const t = useTheme()
|
||||
@@ -33,9 +34,10 @@ export function PwiOptOut() {
|
||||
profile,
|
||||
updates: existing => {
|
||||
// create labels attr if needed
|
||||
const labels: $Typed<ComAtprotoLabelDefs.SelfLabels> = asPredicate(
|
||||
const labels: $Typed<ComAtprotoLabelDefs.SelfLabels> = bsky.validate(
|
||||
existing.labels,
|
||||
ComAtprotoLabelDefs.validateSelfLabels,
|
||||
)(existing.labels)
|
||||
)
|
||||
? existing.labels
|
||||
: {
|
||||
$type: 'com.atproto.label.defs#selfLabels',
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
AppBskyGraphDefs,
|
||||
AppBskyGraphStarterpack,
|
||||
asPredicate,
|
||||
} from '@atproto/api'
|
||||
import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
|
||||
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
|
||||
import {msg} from '@lingui/macro'
|
||||
|
||||
@@ -128,7 +124,7 @@ export function Provider({
|
||||
const createInitialState = (): State => {
|
||||
if (
|
||||
starterPack &&
|
||||
asPredicate(AppBskyGraphStarterpack.validateRecord)(starterPack.record)
|
||||
bsky.validate(starterPack.record, AppBskyGraphStarterpack.validateRecord)
|
||||
) {
|
||||
return {
|
||||
canNext: true,
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
AppBskyEmbedRecordWithMedia,
|
||||
AppBskyFeedDefs,
|
||||
AppBskyFeedPostgate,
|
||||
asPredicate,
|
||||
AtUri,
|
||||
BskyAgent,
|
||||
} from '@atproto/api'
|
||||
@@ -22,6 +21,7 @@ import {
|
||||
POSTGATE_COLLECTION,
|
||||
} from '#/state/queries/postgate/util'
|
||||
import {useAgent} from '#/state/session'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export async function getPostgateRecord({
|
||||
agent,
|
||||
@@ -63,7 +63,7 @@ export async function getPostgateRecord({
|
||||
|
||||
if (
|
||||
data.value &&
|
||||
asPredicate(AppBskyFeedPostgate.validateRecord)(data.value)
|
||||
bsky.validate(data.value, AppBskyFeedPostgate.validateRecord)
|
||||
) {
|
||||
return data.value
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
AppBskyGraphGetStarterPack,
|
||||
AppBskyGraphStarterpack,
|
||||
AppBskyRichtextFacet,
|
||||
asPredicate,
|
||||
AtUri,
|
||||
BskyAgent,
|
||||
RichText,
|
||||
@@ -369,7 +368,7 @@ export async function precacheStarterPack(
|
||||
starterPackView = starterPack
|
||||
} else if (
|
||||
AppBskyGraphDefs.isStarterPackViewBasic(starterPack) &&
|
||||
asPredicate(AppBskyGraphStarterpack.validateRecord)(starterPack.record)
|
||||
bsky.validate(starterPack.record, AppBskyGraphStarterpack.validateRecord)
|
||||
) {
|
||||
const listView: AppBskyGraphDefs.ListViewBasic = {
|
||||
uri: starterPack.record.list,
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
AppBskyFeedDefs,
|
||||
AppBskyFeedGetPostThread,
|
||||
AppBskyFeedThreadgate,
|
||||
asPredicate,
|
||||
AtUri,
|
||||
BskyAgent,
|
||||
} from '@atproto/api'
|
||||
@@ -21,6 +20,7 @@ import {
|
||||
} from '#/state/queries/threadgate/util'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {useThreadgateHiddenReplyUrisAPI} from '#/state/threadgate-hidden-replies'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export * from '#/state/queries/threadgate/types'
|
||||
export * from '#/state/queries/threadgate/util'
|
||||
@@ -141,7 +141,7 @@ export async function getThreadgateRecord({
|
||||
|
||||
if (
|
||||
data.value &&
|
||||
asPredicate(AppBskyFeedThreadgate.validateRecord)(data.value)
|
||||
bsky.validate(data.value, AppBskyFeedThreadgate.validateRecord)
|
||||
) {
|
||||
return data.value
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {AppBskyFeedDefs, AppBskyFeedThreadgate, asPredicate} from '@atproto/api'
|
||||
import {AppBskyFeedDefs, AppBskyFeedThreadgate} from '@atproto/api'
|
||||
|
||||
import {ThreadgateAllowUISetting} from '#/state/queries/threadgate/types'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export function threadgateViewToAllowUISetting(
|
||||
threadgateView: AppBskyFeedDefs.ThreadgateView | undefined,
|
||||
@@ -8,7 +9,7 @@ export function threadgateViewToAllowUISetting(
|
||||
// Validate the record for clarity, since backwards compat code is a little confusing
|
||||
const threadgate =
|
||||
threadgateView &&
|
||||
asPredicate(AppBskyFeedThreadgate.validateRecord)(threadgateView.record)
|
||||
bsky.validate(threadgateView.record, AppBskyFeedThreadgate.validateRecord)
|
||||
? threadgateView.record
|
||||
: undefined
|
||||
return threadgateRecordToAllowUISetting(threadgate)
|
||||
|
||||
+31
-7
@@ -1,19 +1,22 @@
|
||||
import {asPredicate} from '@atproto/api'
|
||||
import {ValidationResult} from '@atproto/lexicon'
|
||||
|
||||
export * as profile from '#/types/bsky/profile'
|
||||
export * as starterPack from '#/types/bsky/starterPack'
|
||||
|
||||
/**
|
||||
* Use sparingly, and only when you know it's safe to do so.
|
||||
* Fast type checking without full schema validation, for use with data we
|
||||
* trust, or for non-critical path use cases. Why? Our SDK's `is*` identity
|
||||
* utils do not assert the type of the entire object, only the `$type` string.
|
||||
*
|
||||
* Our SDK's `is*` identity utils do not assert the type of the entire object,
|
||||
* and although the `isValid*` utils do, they also fully validate the object
|
||||
* shape, which has a performance cost. This util allows us to prescribe the
|
||||
* type we expect, while only checking the `$type` value of the record.
|
||||
* For full validation of the object schema, use the `validate` export from
|
||||
* this file.
|
||||
*
|
||||
* Usage:
|
||||
* ```ts
|
||||
* import * as atp from '#/types/atproto'
|
||||
* import * as bsky from '#/types/bsky'
|
||||
*
|
||||
* if (atp.dangerousIsType<AppBskyFeedPost.Record>(item, AppBskyFeedPost.isRecord)) {
|
||||
* if (bsky.dangerousIsType<AppBskyFeedPost.Record>(item, AppBskyFeedPost.isRecord)) {
|
||||
* // `item` has type `$Typed<AppBskyFeedPost.Record>` here
|
||||
* }
|
||||
* ```
|
||||
@@ -24,3 +27,24 @@ export function dangerousIsType<R extends {$type?: string}>(
|
||||
): record is R {
|
||||
return identity(record)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully validates the object schema, which as a performance cost.
|
||||
*
|
||||
* For faster checks with data we trust, like that from our app view, use the
|
||||
* `dangerousIsType` export from this same file.
|
||||
*
|
||||
* Usage:
|
||||
* ```ts
|
||||
* import * as bsky from '#/types/bsky'
|
||||
*
|
||||
* if (bsky.validate(item, AppBskyFeedPost.validateRecord)) {
|
||||
* // `item` has type `$Typed<AppBskyFeedPost.Record>` here
|
||||
* }
|
||||
*/
|
||||
export function validate<R extends {$type?: string}>(
|
||||
record: unknown,
|
||||
identity: (v: unknown) => ValidationResult<R>,
|
||||
): record is R {
|
||||
return asPredicate(identity)(record)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
||||
import {
|
||||
AppBskyFeedDefs,
|
||||
AppBskyFeedPost,
|
||||
asPredicate,
|
||||
AtUri,
|
||||
ModerationDecision,
|
||||
RichText as RichTextAPI,
|
||||
@@ -29,6 +28,7 @@ import {atoms as a} from '#/alf'
|
||||
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
||||
import {RichText} from '#/components/RichText'
|
||||
import {SubtleWebHover} from '#/components/SubtleWebHover'
|
||||
import * as bsky from '#/types/bsky'
|
||||
import {ContentHider} from '../../../components/moderation/ContentHider'
|
||||
import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '../../../components/moderation/PostAlerts'
|
||||
@@ -54,7 +54,7 @@ export function Post({
|
||||
const moderationOpts = useModerationOpts()
|
||||
const record = useMemo<AppBskyFeedPost.Record | undefined>(
|
||||
() =>
|
||||
asPredicate(AppBskyFeedPost.validateRecord)(post.record)
|
||||
bsky.validate(post.record, AppBskyFeedPost.validateRecord)
|
||||
? post.record
|
||||
: undefined,
|
||||
[post],
|
||||
|
||||
@@ -282,6 +282,17 @@
|
||||
multiformats "^9.9.0"
|
||||
zod "^3.23.8"
|
||||
|
||||
"@atproto/lexicon@0.4.6-next.5", "@atproto/lexicon@^0.4.6-next.5":
|
||||
version "0.4.6-next.5"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.6-next.5.tgz#433a941cf8902afec15135f70cf2cbed37c35406"
|
||||
integrity sha512-Id1atQ1rZ3dUGAUyBcauD+zs5lGHSmoAlC1Kwb2DEvkaWMv3oTXUjtdQxyb0/Kz4YaFI+nxLLRH9NBO+BipG+w==
|
||||
dependencies:
|
||||
"@atproto/common-web" "^0.3.2"
|
||||
"@atproto/syntax" "^0.3.1"
|
||||
iso-datestring-validator "^2.2.2"
|
||||
multiformats "^9.9.0"
|
||||
zod "^3.23.8"
|
||||
|
||||
"@atproto/lexicon@^0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.4.tgz#0d97314bb57b693b76f2495fa5e02872469dd93a"
|
||||
@@ -304,17 +315,6 @@
|
||||
multiformats "^9.9.0"
|
||||
zod "^3.23.8"
|
||||
|
||||
"@atproto/lexicon@^0.4.6-next.5":
|
||||
version "0.4.6-next.5"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.6-next.5.tgz#433a941cf8902afec15135f70cf2cbed37c35406"
|
||||
integrity sha512-Id1atQ1rZ3dUGAUyBcauD+zs5lGHSmoAlC1Kwb2DEvkaWMv3oTXUjtdQxyb0/Kz4YaFI+nxLLRH9NBO+BipG+w==
|
||||
dependencies:
|
||||
"@atproto/common-web" "^0.3.2"
|
||||
"@atproto/syntax" "^0.3.1"
|
||||
iso-datestring-validator "^2.2.2"
|
||||
multiformats "^9.9.0"
|
||||
zod "^3.23.8"
|
||||
|
||||
"@atproto/oauth-provider@^0.2.10":
|
||||
version "0.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.2.10.tgz#f9820d7f82c33d3b74e81a75873f50e1e654b901"
|
||||
|
||||
Reference in New Issue
Block a user