Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 4 additions & 20 deletions .github/workflows/check-snippets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,30 +45,14 @@ jobs:
working-directory: snippets/js
run: npm install

- name: Type-check (vanilla JS)
- name: Validate snippets (vanilla JS)
working-directory: snippets/js
run: npx tsc --noEmit

- name: Lint (vanilla JS)
working-directory: snippets/js
run: npx eslint src/

- name: Format (vanilla JS)
working-directory: snippets/js
run: npx prettier --check src/
run: npm run check

- name: Install (React Native)
working-directory: snippets/react-native
run: npm install --legacy-peer-deps

- name: Type-check (React Native)
working-directory: snippets/react-native
run: npx tsc --noEmit

- name: Lint (React Native)
working-directory: snippets/react-native
run: npx eslint src/

- name: Format (React Native)
- name: Validate snippets (React Native)
working-directory: snippets/react-native
run: npx prettier --check src/
run: npm run check
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
"start": "astro dev",
"build": "astro build && node scripts/copy-md-sources.mjs && node scripts/generate-llms-small.mjs",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"check:snippets": "npm run check:snippets:js && npm run check:snippets:react-native && npm run check:snippets:rust",
"check:snippets:js": "npm --prefix snippets/js run check",
"check:snippets:react-native": "npm --prefix snippets/react-native run check",
"check:snippets:rust": "cargo clippy --manifest-path snippets/rust/Cargo.toml -- -D warnings && cargo fmt --manifest-path snippets/rust/Cargo.toml --check"
},
"dependencies": {
"@astrojs/starlight": "^0.37.6",
Expand Down
6 changes: 6 additions & 0 deletions snippets/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"name": "pubky-doc-snippets-js",
"private": true,
"type": "module",
"scripts": {
"check": "npm run typecheck && npm run lint && npm run format:check",
"typecheck": "tsc --noEmit",
"lint": "eslint src/",
"format:check": "prettier --check src/"
},
"dependencies": {
"@synonymdev/pubky": "0.8.0"
},
Expand Down
7 changes: 7 additions & 0 deletions snippets/js/src/quick-start-getting-started.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,10 @@ console.log("Files:", files);
// Sign out
await session.signout();
// --8<-- [end:js_getting_started_quick_example]

async function snippet_nexus_global_feed() {
// --8<-- [start:js_nexus_global_feed]
const response = await fetch("https://nexus.pubky.app/v0/feeds/global");
const posts = await response.json();
// --8<-- [end:js_nexus_global_feed]
}
146 changes: 146 additions & 0 deletions snippets/js/src/troubleshooting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import {
Client,
Pubky,
PublicKey,
setLogLevel,
type Path,
type PubkyError,
type Session,
type Signer,
} from "@synonymdev/pubky";

declare const signer: Signer;
declare const session: Session;
declare const homeserverPk: PublicKey;
declare const data: string;

async function snippet_publish_pkdns_record() {
// --8<-- [start:js_publish_pkdns_record]
await signer.pkdns.publishHomeserverForce(homeserverPk);
// --8<-- [end:js_publish_pkdns_record]
}

function snippet_republish_pkdns_record() {
// --8<-- [start:js_republish_pkdns_record]
// Periodically check whether the record is stale before republishing
setInterval(
async () => {
await signer.pkdns.publishHomeserverIfStale(homeserverPk);
},
2 * 60 * 60 * 1000,
); // Every 2 hours
// --8<-- [end:js_republish_pkdns_record]
}

async function snippet_reauth() {
// --8<-- [start:js_reauth]
const session = await signer.signin();
// --8<-- [end:js_reauth]
}

async function snippet_force_reauth() {
// --8<-- [start:js_force_reauth]
// Force re-authentication
await session.signout();
const newSession = await signer.signin();
// --8<-- [end:js_force_reauth]
}

function snippet_direct_homeserver_url() {
// --8<-- [start:js_direct_homeserver_url]
// In browser, use full HTTPS URL
const url = `https://your-homeserver.com/pub/...`;
// --8<-- [end:js_direct_homeserver_url]
}

async function snippet_valid_storage_path() {
// --8<-- [start:js_valid_storage_path]
await session.storage.putText("/pub/myapp/data.json", data);

// Invalid paths:
// - "data.json"
// - "/myapp/data.json"
// --8<-- [end:js_valid_storage_path]
}

function typecheck_invalid_storage_paths() {
// These intentionally stay outside the rendered docs. They verify that
// TypeScript still rejects the invalid paths described above.
// @ts-expect-error Path must start with /pub/.
void session.storage.putText("data.json", data);
// @ts-expect-error Path must start with /pub/.
void session.storage.putText("/myapp/data.json", data);
}

function statusCodeOf(error: unknown): number | undefined {
const data = (error as PubkyError).data;
if (typeof data !== "object" || data === null || !("statusCode" in data)) {
return undefined;
}

return (data as { statusCode?: number }).statusCode;
}

// --8<-- [start:js_put_with_retry]
async function putWithRetry(
session: Session,
path: Path,
data: string,
retries = 3,
): Promise<void> {
for (let i = 0; i < retries; i++) {
try {
return await session.storage.putText(path, data);
} catch (error) {
if (statusCodeOf(error) === 429) {
await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
continue;
}
throw error;
}
}

throw new Error("PUT failed after retrying rate limits");
}
// --8<-- [end:js_put_with_retry]

function snippet_pkarr_relay_config() {
// --8<-- [start:js_pkarr_relay_config]
const client = new Client({
pkarr: {
relays: ["https://pkarr.pubky.org"],
},
});

const pubky = Pubky.withClient(client);
// --8<-- [end:js_pkarr_relay_config]
}

const homeserverCache = new Map<string, PublicKey>();

// --8<-- [start:js_cache_homeserver_lookup]
async function getCachedHomeserver(
pubky: Pubky,
userPublicKey: string,
): Promise<PublicKey | undefined> {
const cached = homeserverCache.get(userPublicKey);
if (cached) return cached;

const user = PublicKey.from(userPublicKey);
const homeserver = await pubky.getHomeserverOf(user);

if (homeserver) {
homeserverCache.set(userPublicKey, homeserver);
}

return homeserver;
}
// --8<-- [end:js_cache_homeserver_lookup]

function snippet_enable_debug_logging() {
// --8<-- [start:js_enable_debug_logging]
// Call once at application startup, before creating Pubky or Client instances.
setLogLevel("debug");

// --8<-- [end:js_enable_debug_logging]
}
6 changes: 6 additions & 0 deletions snippets/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"name": "pubky-doc-snippets-react-native",
"private": true,
"type": "module",
"scripts": {
"check": "npm run typecheck && npm run lint && npm run format:check",
"typecheck": "tsc --noEmit",
"lint": "eslint src/",
"format:check": "prettier --check src/"
},
"dependencies": {
"@synonymdev/react-native-pubky": "0.11.3"
},
Expand Down
16 changes: 1 addition & 15 deletions src/content/docs/explore/pubkycore/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,20 +523,7 @@ PUT /pub/myapp/all_posts (large JSON array)

### Handle Rate Limits

```javascript
async function putWithRetry(session, path, data, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await session.storage.putText(path, data);
} catch (error) {
if (error.status === 429) { // Too Many Requests
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
continue;
}
throw error;
}
}
}
```javascript snippet="snippets/js/src/troubleshooting.ts:js_put_with_retry"
```

## Resources
Expand All @@ -550,4 +537,3 @@ async function putWithRetry(session, path, data, retries = 3) {
---

**The Pubky Core API provides a simple, RESTful interface for decentralized data storage.**

6 changes: 1 addition & 5 deletions src/content/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,7 @@ If building a social app, leverage [Pubky Nexus](/explore/pubky-apps/indexing-an
- User recommendations
- Notifications

```javascript
// Query Nexus API
const response = await fetch('https://nexus.pubky.app/v0/feeds/global');
const posts = await response.json();
```javascript snippet="snippets/js/src/quick-start-getting-started.ts:js_nexus_global_feed"
```

📊 [Nexus API Docs](https://nexus.pubky.app/swagger-ui/)
Expand Down Expand Up @@ -274,4 +271,3 @@ A: Several models work: Homeserver hosting, indexing services (like Nexus), prem
---

**Ready to build the decentralized web? Start with the [SDK](/explore/pubkycore/sdk/)!**

Loading
Loading