mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'codex/feature/spam-blocker-challenge'
# Conflicts: # package.json # src/components/settings-modal/advanced-settings/__tests__/advanced-settings.test.tsx # src/components/settings-modal/advanced-settings/advanced-settings.tsx # src/stores/__tests__/publish-stores.test.ts # yarn.lock
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
"license": "GPL-2.0-only",
|
"license": "GPL-2.0-only",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bitsocialnet/bitsocial-react-hooks": "https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/95b46a8350ed5a2f96721f0dc14f2aaf26d410bf",
|
"@bitsocialnet/bitsocial-react-hooks": "https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/648d789ff2c42feec208156a6c03af6e3825f45d",
|
||||||
"@capacitor/app": "7.0.1",
|
"@capacitor/app": "7.0.1",
|
||||||
"@capacitor/status-bar": "7.0.1",
|
"@capacitor/status-bar": "7.0.1",
|
||||||
"@capawesome/capacitor-android-edge-to-edge-support": "7.2.2",
|
"@capawesome/capacitor-android-edge-to-edge-support": "7.2.2",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { createElement } from 'react';
|
|||||||
import { createRoot, type Root } from 'react-dom/client';
|
import { createRoot, type Root } from 'react-dom/client';
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
import ChallengeModal from '../challenge-modal';
|
import ChallengeModal from '../challenge-modal';
|
||||||
|
import getShortAddress from '../../../lib/get-short-address';
|
||||||
|
|
||||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||||
@@ -88,7 +89,7 @@ let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
|
|||||||
let postMessageMock: ReturnType<typeof vi.fn>;
|
let postMessageMock: ReturnType<typeof vi.fn>;
|
||||||
let root: Root;
|
let root: Root;
|
||||||
|
|
||||||
const createPublication = () => ({
|
const createPublication = (): Record<string, any> => ({
|
||||||
author: { displayName: 'Alice' },
|
author: { displayName: 'Alice' },
|
||||||
content: 'Publication content',
|
content: 'Publication content',
|
||||||
link: 'https://example.com/link',
|
link: 'https://example.com/link',
|
||||||
@@ -285,6 +286,63 @@ describe('ChallengeModal', () => {
|
|||||||
expect(testState.removeChallengeMock).toHaveBeenCalledOnce();
|
expect(testState.removeChallengeMock).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('allows localhost http iframe challenges for local spam blocker testing', async () => {
|
||||||
|
const publication = createPublication();
|
||||||
|
testState.challenges = [
|
||||||
|
createStoredChallenge(
|
||||||
|
{
|
||||||
|
challenge: 'http://localhost:3000/api/v1/iframe/session-123?foo=bar',
|
||||||
|
type: 'url/iframe',
|
||||||
|
},
|
||||||
|
publication,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
await renderModal();
|
||||||
|
expect(container.textContent).toContain('mu wants to open localhost:3000');
|
||||||
|
|
||||||
|
await clickButton('Open');
|
||||||
|
|
||||||
|
const iframe = container.querySelector('iframe');
|
||||||
|
expect(iframe).not.toBeNull();
|
||||||
|
expect(iframe?.getAttribute('src')).toContain('http://localhost:3000/api/v1/iframe/session-123?foo=bar&theme=dark');
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
iframe?.dispatchEvent(new Event('load', { bubbles: true }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(postMessageMock).toHaveBeenCalledWith(
|
||||||
|
{
|
||||||
|
source: 'plebbit-5chan',
|
||||||
|
theme: 'dark',
|
||||||
|
type: 'plebbit-theme',
|
||||||
|
},
|
||||||
|
'http://localhost:3000',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses the shortened community address when shortCommunityAddress is unavailable', async () => {
|
||||||
|
const longCommunityAddress = '12D3KooWS6yKc5N7o6JcAYHZpaQwAwyh1VddYatarU75Se3HXEeD';
|
||||||
|
const publication = {
|
||||||
|
...createPublication(),
|
||||||
|
shortCommunityAddress: undefined,
|
||||||
|
communityAddress: longCommunityAddress,
|
||||||
|
};
|
||||||
|
testState.challenges = [
|
||||||
|
createStoredChallenge(
|
||||||
|
{
|
||||||
|
challenge: 'http://localhost:3000/api/v1/iframe/session-123?foo=bar',
|
||||||
|
type: 'url/iframe',
|
||||||
|
},
|
||||||
|
publication,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
await renderModal();
|
||||||
|
expect(container.textContent).toContain(`${getShortAddress(longCommunityAddress)} wants to open localhost:3000`);
|
||||||
|
expect(container.textContent).not.toContain(`${longCommunityAddress} wants to open localhost:3000`);
|
||||||
|
});
|
||||||
|
|
||||||
it('alerts when iframe challenges need a signer address and the account is missing one', async () => {
|
it('alerts when iframe challenges need a signer address and the account is missing one', async () => {
|
||||||
testState.account = { author: { address: '' } };
|
testState.account = { author: { address: '' } };
|
||||||
testState.challenges = [
|
testState.challenges = [
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import styles from './challenge-modal.module.css';
|
|||||||
import capitalize from 'lodash/capitalize';
|
import capitalize from 'lodash/capitalize';
|
||||||
import { useSpring, animated } from '@react-spring/web';
|
import { useSpring, animated } from '@react-spring/web';
|
||||||
import { useDrag } from '@use-gesture/react';
|
import { useDrag } from '@use-gesture/react';
|
||||||
|
import getShortAddress from '../../lib/get-short-address';
|
||||||
|
|
||||||
const useParentAddress = (parentCid?: string) => {
|
const useParentAddress = (parentCid?: string) => {
|
||||||
const parentComment = useComment({ commentCid: parentCid, onlyIfCached: true });
|
const parentComment = useComment({ commentCid: parentCid, onlyIfCached: true });
|
||||||
@@ -25,6 +26,17 @@ const TextChallenge = ({ challenge }: { challenge: string }) => <div className={
|
|||||||
|
|
||||||
const ImageChallenge = ({ challenge }: { challenge: string }) => <img alt='' className={styles.challengeMedia} src={`data:image/png;base64,${challenge}`} />;
|
const ImageChallenge = ({ challenge }: { challenge: string }) => <img alt='' className={styles.challengeMedia} src={`data:image/png;base64,${challenge}`} />;
|
||||||
|
|
||||||
|
const isLocalIframeHostname = (hostname: string) => hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]' || hostname.endsWith('.localhost');
|
||||||
|
|
||||||
|
const getReadableIframeUrl = (challengeUrl: string) => {
|
||||||
|
try {
|
||||||
|
const url = new URL(challengeUrl);
|
||||||
|
return url.host || url.hostname;
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
interface IframeChallengeProps {
|
interface IframeChallengeProps {
|
||||||
challenge: string;
|
challenge: string;
|
||||||
shortCommunityAddress?: string;
|
shortCommunityAddress?: string;
|
||||||
@@ -42,6 +54,7 @@ const IframeChallenge = ({ challenge, shortCommunityAddress, communityAddress, r
|
|||||||
const [iframeUrlState, setIframeUrl] = useState('');
|
const [iframeUrlState, setIframeUrl] = useState('');
|
||||||
const [iframeOrigin, setIframeOrigin] = useState('');
|
const [iframeOrigin, setIframeOrigin] = useState('');
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||||
|
const displayCommunityAddress = shortCommunityAddress || (communityAddress ? getShortAddress(communityAddress) : '') || communityAddress || 'unknown board';
|
||||||
|
|
||||||
const handleLoadIframe = useCallback(() => {
|
const handleLoadIframe = useCallback(() => {
|
||||||
const iframeUrl = challenge;
|
const iframeUrl = challenge;
|
||||||
@@ -60,8 +73,10 @@ const IframeChallenge = ({ challenge, shortCommunityAddress, communityAddress, r
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const validatedUrl = new URL(replacedUrl);
|
const validatedUrl = new URL(replacedUrl);
|
||||||
if (validatedUrl.protocol !== 'https:') {
|
const isHttps = validatedUrl.protocol === 'https:';
|
||||||
throw new Error('Only HTTPS iframe challenges are supported');
|
const isLocalHttp = validatedUrl.protocol === 'http:' && isLocalIframeHostname(validatedUrl.hostname);
|
||||||
|
if (!isHttps && !isLocalHttp) {
|
||||||
|
throw new Error('Only HTTPS iframe challenges or localhost HTTP challenges are supported');
|
||||||
}
|
}
|
||||||
validatedUrl.pathname = validatedUrl.pathname.replace(/\/{2,}/g, '/');
|
validatedUrl.pathname = validatedUrl.pathname.replace(/\/{2,}/g, '/');
|
||||||
validatedUrl.searchParams.set('theme', theme);
|
validatedUrl.searchParams.set('theme', theme);
|
||||||
@@ -101,7 +116,7 @@ const IframeChallenge = ({ challenge, shortCommunityAddress, communityAddress, r
|
|||||||
{publicationDetails}
|
{publicationDetails}
|
||||||
<div className={styles.challengeMediaWrapper}>
|
<div className={styles.challengeMediaWrapper}>
|
||||||
<div className={`${styles.challengeMedia} ${styles.iframeChallengeWarning}`}>
|
<div className={`${styles.challengeMedia} ${styles.iframeChallengeWarning}`}>
|
||||||
{shortCommunityAddress || communityAddress || 'unknown board'} wants to open {readableUrl || 'an external site'}
|
{displayCommunityAddress} wants to open {readableUrl || 'an external site'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles.challengeFooter} ${styles.iframeFooter}`}>
|
<div className={`${styles.challengeFooter} ${styles.iframeFooter}`}>
|
||||||
@@ -235,26 +250,11 @@ const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => {
|
|||||||
}, [abandonModal]);
|
}, [abandonModal]);
|
||||||
|
|
||||||
const getChallengeUrl = useCallback(() => {
|
const getChallengeUrl = useCallback(() => {
|
||||||
try {
|
const iframeUrl = currentChallenge?.challenge;
|
||||||
const iframeUrl = currentChallenge?.challenge;
|
if (!iframeUrl) return '';
|
||||||
if (!iframeUrl) return '';
|
return getReadableIframeUrl(iframeUrl);
|
||||||
const url = new URL(iframeUrl);
|
|
||||||
if (url.hostname === 'mintpass.org') return url.hostname;
|
|
||||||
return url.href;
|
|
||||||
} catch {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}, [currentChallenge]);
|
}, [currentChallenge]);
|
||||||
|
const readableUrl = getChallengeUrl();
|
||||||
const readableUrl = (() => {
|
|
||||||
const url = getChallengeUrl();
|
|
||||||
if (!url) return '';
|
|
||||||
try {
|
|
||||||
return decodeURIComponent(url);
|
|
||||||
} catch {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (!challenges?.length || !publication || !currentChallenge) {
|
if (!challenges?.length || !publication || !currentChallenge) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+12
-12
@@ -9,11 +9,11 @@ const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise
|
|||||||
const testState = vi.hoisted(() => ({
|
const testState = vi.hoisted(() => ({
|
||||||
account: {
|
account: {
|
||||||
mediaIpfsGatewayUrl: 'https://media.old.example',
|
mediaIpfsGatewayUrl: 'https://media.old.example',
|
||||||
|
chainProviders: {
|
||||||
|
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||||
|
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||||
|
},
|
||||||
pkcOptions: {
|
pkcOptions: {
|
||||||
chainProviders: {
|
|
||||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
|
||||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
|
||||||
},
|
|
||||||
httpRoutersOptions: ['https://router.old.example'],
|
httpRoutersOptions: ['https://router.old.example'],
|
||||||
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
||||||
pkcRpcClientsOptions: ['ws://old.example/key'],
|
pkcRpcClientsOptions: ['ws://old.example/key'],
|
||||||
@@ -86,11 +86,11 @@ describe('AdvancedSettings', () => {
|
|||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
testState.account = {
|
testState.account = {
|
||||||
mediaIpfsGatewayUrl: 'https://media.old.example',
|
mediaIpfsGatewayUrl: 'https://media.old.example',
|
||||||
|
chainProviders: {
|
||||||
|
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||||
|
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||||
|
},
|
||||||
pkcOptions: {
|
pkcOptions: {
|
||||||
chainProviders: {
|
|
||||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
|
||||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
|
||||||
},
|
|
||||||
httpRoutersOptions: ['https://router.old.example'],
|
httpRoutersOptions: ['https://router.old.example'],
|
||||||
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
||||||
pkcRpcClientsOptions: ['ws://old.example/key'],
|
pkcRpcClientsOptions: ['ws://old.example/key'],
|
||||||
@@ -154,11 +154,11 @@ describe('AdvancedSettings', () => {
|
|||||||
|
|
||||||
expect(testState.setAccountMock).toHaveBeenCalledWith({
|
expect(testState.setAccountMock).toHaveBeenCalledWith({
|
||||||
mediaIpfsGatewayUrl: 'https://media.new.example',
|
mediaIpfsGatewayUrl: 'https://media.new.example',
|
||||||
|
chainProviders: {
|
||||||
|
eth: { chainId: 1, urls: ['https://eth.one.example'] },
|
||||||
|
sol: { chainId: 101, urls: ['https://sol.one.example'] },
|
||||||
|
},
|
||||||
pkcOptions: {
|
pkcOptions: {
|
||||||
chainProviders: {
|
|
||||||
eth: { chainId: 1, urls: ['https://eth.one.example'] },
|
|
||||||
sol: { chainId: 101, urls: ['https://sol.one.example'] },
|
|
||||||
},
|
|
||||||
dataPath: '/tmp/next-plebbit',
|
dataPath: '/tmp/next-plebbit',
|
||||||
httpRoutersOptions: ['https://router.one.example'],
|
httpRoutersOptions: ['https://router.one.example'],
|
||||||
ipfsGatewayUrls: ['https://ipfs.one.example', 'https://ipfs.two.example'],
|
ipfsGatewayUrls: ['https://ipfs.one.example', 'https://ipfs.two.example'],
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ const AdvancedSettings = () => {
|
|||||||
|
|
||||||
const mediaIpfsGatewayUrl = mediaIpfsGatewayUrlRef.current?.value.trim();
|
const mediaIpfsGatewayUrl = mediaIpfsGatewayUrlRef.current?.value.trim();
|
||||||
|
|
||||||
const pubsubHttpClientsOptions = pubsubProvidersRef.current?.value
|
const pubsubKuboRpcClientsOptions = pubsubProvidersRef.current?.value
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map((url) => url.trim())
|
.map((url) => url.trim())
|
||||||
.filter((url) => url !== '');
|
.filter((url) => url !== '');
|
||||||
@@ -272,11 +272,11 @@ const AdvancedSettings = () => {
|
|||||||
await setAccount({
|
await setAccount({
|
||||||
...account,
|
...account,
|
||||||
mediaIpfsGatewayUrl,
|
mediaIpfsGatewayUrl,
|
||||||
|
chainProviders,
|
||||||
pkcOptions: {
|
pkcOptions: {
|
||||||
...protocolOptions,
|
...protocolOptions,
|
||||||
ipfsGatewayUrls,
|
ipfsGatewayUrls,
|
||||||
pubsubKuboRpcClientsOptions: pubsubHttpClientsOptions,
|
pubsubKuboRpcClientsOptions,
|
||||||
chainProviders,
|
|
||||||
httpRoutersOptions,
|
httpRoutersOptions,
|
||||||
pkcRpcClientsOptions,
|
pkcRpcClientsOptions,
|
||||||
dataPath,
|
dataPath,
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ describe('usePublishPost', () => {
|
|||||||
spoiler: true,
|
spoiler: true,
|
||||||
title: 'Hello world',
|
title: 'Hello world',
|
||||||
});
|
});
|
||||||
|
expect('subplebbitAddress' in latestValue.publishPostOptions).toBe(false);
|
||||||
expect(typeof latestValue.publishPostOptions.onChallengeVerification).toBe('function');
|
expect(typeof latestValue.publishPostOptions.onChallengeVerification).toBe('function');
|
||||||
expect(typeof latestValue.publishPostOptions.onError).toBe('function');
|
expect(typeof latestValue.publishPostOptions.onError).toBe('function');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ describe('usePublishReply', () => {
|
|||||||
quotedCids: ['quoted-cid'],
|
quotedCids: ['quoted-cid'],
|
||||||
spoiler: true,
|
spoiler: true,
|
||||||
});
|
});
|
||||||
|
expect('subplebbitAddress' in (testState.lastPublishOptions || {})).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves same-board external quote references before triggering publish', async () => {
|
it('resolves same-board external quote references before triggering publish', async () => {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ describe('publish stores', () => {
|
|||||||
expect(state.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
expect(state.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
||||||
expect(state.publishCommentOptions.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
expect(state.publishCommentOptions.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
||||||
expect(state.publishCommentOptions.communityAddress).toBe('music-posting.eth');
|
expect(state.publishCommentOptions.communityAddress).toBe('music-posting.eth');
|
||||||
|
expect('subplebbitAddress' in state.publishCommentOptions).toBe(false);
|
||||||
expect(state.publishCommentOptions.title).toBe('Hello');
|
expect(state.publishCommentOptions.title).toBe('Hello');
|
||||||
|
|
||||||
state.publishCommentOptions.onChallengeVerification?.({} as never, comment);
|
state.publishCommentOptions.onChallengeVerification?.({} as never, comment);
|
||||||
@@ -85,6 +86,7 @@ describe('publish stores', () => {
|
|||||||
expect(state.publishCommentOptions['parent-1']?.communityAddress).toBe('music-posting.eth');
|
expect(state.publishCommentOptions['parent-1']?.communityAddress).toBe('music-posting.eth');
|
||||||
expect(state.publishCommentOptions['parent-1']?.parentCid).toBe('parent-1');
|
expect(state.publishCommentOptions['parent-1']?.parentCid).toBe('parent-1');
|
||||||
expect(state.publishCommentOptions['parent-1']?.postCid).toBe('parent-1');
|
expect(state.publishCommentOptions['parent-1']?.postCid).toBe('parent-1');
|
||||||
|
expect('subplebbitAddress' in (state.publishCommentOptions['parent-1'] || {})).toBe(false);
|
||||||
|
|
||||||
state.publishCommentOptions['parent-1']?.onChallengeVerification?.({ token: 'challenge' } as never, comment);
|
state.publishCommentOptions['parent-1']?.onChallengeVerification?.({ token: 'challenge' } as never, comment);
|
||||||
expect(testState.alertChallengeVerificationFailedMock).toHaveBeenCalledWith({ token: 'challenge' }, comment);
|
expect(testState.alertChallengeVerificationFailedMock).toHaveBeenCalledWith({ token: 'challenge' }, comment);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "5chan@workspace:."
|
resolution: "5chan@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@bitsocialnet/bitsocial-react-hooks": "https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/95b46a8350ed5a2f96721f0dc14f2aaf26d410bf"
|
"@bitsocialnet/bitsocial-react-hooks": "https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/648d789ff2c42feec208156a6c03af6e3825f45d"
|
||||||
"@capacitor/android": "npm:7.4.5"
|
"@capacitor/android": "npm:7.4.5"
|
||||||
"@capacitor/app": "npm:7.0.1"
|
"@capacitor/app": "npm:7.0.1"
|
||||||
"@capacitor/cli": "npm:7.4.5"
|
"@capacitor/cli": "npm:7.4.5"
|
||||||
@@ -1519,22 +1519,22 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@bitsocial/bso-resolver@https://github.com/bitsocialnet/bso-resolver.git#a005e4b507435c0f399328800d6c421bf62b14ed":
|
"@bitsocial/bso-resolver@npm:0.0.4":
|
||||||
version: 0.0.2
|
version: 0.0.4
|
||||||
resolution: "@bitsocial/bso-resolver@https://github.com/bitsocialnet/bso-resolver.git#commit=a005e4b507435c0f399328800d6c421bf62b14ed"
|
resolution: "@bitsocial/bso-resolver@npm:0.0.4"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@pkc/pkc-logger": "github:pkcprotocol/pkc-logger#cb494fbaf332ed5b2cfd9d9d0f90ca7fd0058b4a"
|
"@pkc/pkc-logger": "github:pkcprotocol/pkc-logger#cb494fbaf332ed5b2cfd9d9d0f90ca7fd0058b4a"
|
||||||
better-sqlite3: "npm:12.6.2"
|
better-sqlite3: "npm:12.6.2"
|
||||||
viem: "npm:2.47.0"
|
viem: "npm:2.47.0"
|
||||||
checksum: 10c0/64f86a126ba3c3f4c9516bafa895dfbb4f18f72c9e9cd0e1f9584755291e768f8ff33b08988ce01fa0fcce0cafd987b79547e31770d5e4f038b7b8b74422e778
|
checksum: 10c0/39cf1f3381343591e98ae149c682acd245403bde5608135d849dd31904c6b539f3accdc46e1e6a3978ddf6dea71f85814be8792ce5f5e0d7526399f1eb23ac48
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@bitsocialnet/bitsocial-react-hooks@https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/95b46a8350ed5a2f96721f0dc14f2aaf26d410bf":
|
"@bitsocialnet/bitsocial-react-hooks@https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/648d789ff2c42feec208156a6c03af6e3825f45d":
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
resolution: "@bitsocialnet/bitsocial-react-hooks@https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/95b46a8350ed5a2f96721f0dc14f2aaf26d410bf"
|
resolution: "@bitsocialnet/bitsocial-react-hooks@https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/648d789ff2c42feec208156a6c03af6e3825f45d"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@bitsocial/bso-resolver": "https://github.com/bitsocialnet/bso-resolver.git#a005e4b507435c0f399328800d6c421bf62b14ed"
|
"@bitsocial/bso-resolver": "npm:0.0.4"
|
||||||
"@pkc/pkc-logger": "https://github.com/pkcprotocol/pkc-logger.git"
|
"@pkc/pkc-logger": "https://github.com/pkcprotocol/pkc-logger.git"
|
||||||
"@pkcprotocol/pkc-js": "https://github.com/pkcprotocol/pkc-js.git#e63026e6cd33df5af3a3b5e6473b1e364d89fbdb"
|
"@pkcprotocol/pkc-js": "https://github.com/pkcprotocol/pkc-js.git#e63026e6cd33df5af3a3b5e6473b1e364d89fbdb"
|
||||||
assert: "npm:2.0.0"
|
assert: "npm:2.0.0"
|
||||||
@@ -1551,7 +1551,7 @@ __metadata:
|
|||||||
zustand: "npm:4.0.0"
|
zustand: "npm:4.0.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ">=16.8"
|
react: ">=16.8"
|
||||||
checksum: 10c0/48a658a76f77d9febd6a11b6c8cb027574999acd6189beee5b121cae81653f123b06cebad134b10a36ca70ec3d5adbbf80c4c3e5de8e81d745d0430c95dfcf08
|
checksum: 10c0/e4acb68b8b1cc50e8fffaa9245cb47f7496164b98c38ec7891f7cedaac7d80e8b58e341cef1e591995e70854ed32a7320f55d2bd3cb94064df165a24f4f1aba0
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user