atproxy 0.0.0-experimental-4283f3a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +151 -0
  3. package/dist/config/auth.d.ts +6 -0
  4. package/dist/config/auth.d.ts.map +1 -0
  5. package/dist/config/auth.js +18 -0
  6. package/dist/config/auth.js.map +1 -0
  7. package/dist/config/config.d.ts +4 -0
  8. package/dist/config/config.d.ts.map +1 -0
  9. package/dist/config/config.js +22 -0
  10. package/dist/config/config.js.map +1 -0
  11. package/dist/config/permissions.d.ts +2 -0
  12. package/dist/config/permissions.d.ts.map +1 -0
  13. package/dist/config/permissions.js +8 -0
  14. package/dist/config/permissions.js.map +1 -0
  15. package/dist/config/prompts.d.ts +5 -0
  16. package/dist/config/prompts.d.ts.map +1 -0
  17. package/dist/config/prompts.js +52 -0
  18. package/dist/config/prompts.js.map +1 -0
  19. package/dist/config/types.d.ts +6 -0
  20. package/dist/config/types.d.ts.map +1 -0
  21. package/dist/config/types.js +3 -0
  22. package/dist/config/types.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +67 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/server/methods.d.ts +5 -0
  28. package/dist/server/methods.d.ts.map +1 -0
  29. package/dist/server/methods.js +52 -0
  30. package/dist/server/methods.js.map +1 -0
  31. package/dist/server/request-handler.d.ts +4 -0
  32. package/dist/server/request-handler.d.ts.map +1 -0
  33. package/dist/server/request-handler.js +31 -0
  34. package/dist/server/request-handler.js.map +1 -0
  35. package/dist/server/server.d.ts +3 -0
  36. package/dist/server/server.d.ts.map +1 -0
  37. package/dist/server/server.js +16 -0
  38. package/dist/server/server.js.map +1 -0
  39. package/dist/server/types.d.ts +8 -0
  40. package/dist/server/types.d.ts.map +1 -0
  41. package/dist/server/types.js +3 -0
  42. package/dist/server/types.js.map +1 -0
  43. package/dist/utils/http-utils.d.ts +3 -0
  44. package/dist/utils/http-utils.d.ts.map +1 -0
  45. package/dist/utils/http-utils.js +9 -0
  46. package/dist/utils/http-utils.js.map +1 -0
  47. package/dist/utils/path-utils.d.ts +5 -0
  48. package/dist/utils/path-utils.d.ts.map +1 -0
  49. package/dist/utils/path-utils.js +34 -0
  50. package/dist/utils/path-utils.js.map +1 -0
  51. package/package.json +31 -0
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Alex Savelyev <dev@alexdln.com>
4
+
5
+ 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:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ 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.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Atproxy
2
+
3
+ > Local XRPC Proxy for atproto and Bluesky-like Applications
4
+
5
+ Atproxy is a privacy-first browser extension and local proxy server that gives you complete control over XRPC requests from atproto applications. Intercept, filter, and manage all XRPC traffic through your own local server, keeping session data and sensitive information entirely under your control.
6
+
7
+ ## Overview
8
+
9
+ Atproxy consists of two components working together:
10
+
11
+ - **Browser Extension** (Manifest V3): Intercepts XRPC requests from web pages and forwards them to your local proxy server
12
+ - **Proxy Server** (Node.js CLI): A local HTTP server that authenticates with Bluesky, validates permissions, and proxies requests to the atproto network
13
+
14
+ This architecture ensures that all session management, authentication tokens, and request filtering happens on your machine—never in the browser or on external servers.
15
+
16
+ ## Privacy & Security
17
+ - **Local-first architecture**: All session data and credentials stored exclusively on your server
18
+ - **Permission-based access control**: Whitelist specific XRPC methods (queries and procedures)
19
+ - **No data collection**: Zero telemetry, tracking, or external data transmission
20
+ - **Transparent proxying**: Requests flow through your server with full visibility
21
+
22
+ ### Request Flow
23
+
24
+ 1. **Interception**: Injected script overrides `window.fetch()` and matches requests against configured regex pattern (default: `^.*/xrpc/`)
25
+ 2. **Extension Bridge**: Content script forwards serialized request to background service worker
26
+ 3. **Proxy Forwarding**: Background worker sends HTTP request to local proxy server (default: `http://localhost:9523`)
27
+ 4. **Permission Check**: Proxy validates request path against whitelisted permissions
28
+ 5. **Authentication**: Proxy uses stored Bluesky credentials to authenticate with atproto network
29
+ 6. **XRPC Call**: Proxy makes authenticated call using `@atproto/api` Agent
30
+ 7. **Response**: Response flows back through the chain to the original web application
31
+
32
+ ## API Reference
33
+
34
+ ### Proxy Server CLI
35
+
36
+ ```bash
37
+ atproxy [options]
38
+
39
+ Options:
40
+ --handle <string> Bluesky handle (e.g., handle.bsky.social)
41
+ --permissions <...> Permission IDs (can specify multiple times)
42
+ --port <number> Server port (default: 9523)
43
+ ```
44
+
45
+ ### Proxy Server Endpoints
46
+
47
+ - `GET /xrpc/<method>` - Proxy GET requests (queries)
48
+ - `POST /xrpc/<method>` - Proxy POST requests (procedures)
49
+ - `GET /` - Health check endpoint
50
+
51
+ ### Extension Configuration
52
+
53
+ Extension settings are stored in Chrome's sync storage and accessible via the popup:
54
+
55
+ - **Enabled**: Toggle to enable/disable request proxying
56
+ - **Proxyfying rule**: Regex pattern to match URLs (default: `^.*/xrpc/`)
57
+
58
+ ## Use Cases
59
+
60
+ ### For Developers
61
+
62
+ - **Testing & Development**: Test Bluesky integrations without affecting production accounts
63
+ - **API Experimentation**: Explore atproto APIs with full request/response visibility
64
+ - **Custom Clients**: Build or use Bluesky clients with custom authentication or filtering logic
65
+ - **Debugging**: Inspect XRPC traffic and understand application behavior
66
+
67
+ ### For Privacy-Conscious Users
68
+
69
+ - **Session Control**: Keep authentication tokens on your machine, not in browser storage
70
+ - **Request Filtering**: Block or modify specific API calls before they reach Bluesky
71
+ - **Traffic Analysis**: Monitor and log all XRPC requests for security auditing
72
+
73
+ ## Troubleshooting
74
+
75
+ ### Extension shows "Not started"
76
+
77
+ - Verify the proxy server is running: `curl http://localhost:9523/`
78
+ - Check the port matches in extension configuration
79
+ - Ensure no firewall is blocking `localhost:9523`
80
+
81
+ ### Requests not being intercepted
82
+
83
+ - Verify the regex pattern matches your application's XRPC URLs
84
+ - Check browser console for injection errors
85
+ - Ensure extension is enabled in the popup
86
+
87
+ ## Local Usage
88
+
89
+ ### Installation
90
+
91
+ **Prerequisites**
92
+
93
+ - Node.js >= 18.0.0
94
+ - pnpm (recommended) or npm
95
+ - Chrome, Edge, or other Chromium-based browser
96
+
97
+ ```bash
98
+ git clone <repository-url>
99
+ cd atproxy
100
+ pnpm install
101
+ pnpm build
102
+ ```
103
+
104
+ ### Starting the Proxy Server
105
+
106
+ The proxy server requires Bluesky credentials and permission configuration:
107
+
108
+ ```bash
109
+ pnpm start:proxy
110
+ pnpm start:proxy --handle yourhandle.bsky.social \
111
+ --permissions app.bsky.feed.getTimeline \
112
+ --permissions app.bsky.actor.getProfile \
113
+ --port 9523
114
+ ```
115
+
116
+ **Server setup:**
117
+ 1. Enter your Bluesky handle (e.g., `yourhandle.bsky.social`)
118
+ 2. Enter your account or app password
119
+ 3. Select permissions from the interactive list (use arrow keys, space to select)
120
+ 4. Configuration (excluding password) is saved to `~/.atproxy.json` for future runs
121
+
122
+ ### Installing the Extension
123
+
124
+ 1. Build the extension:
125
+ ```bash
126
+ pnpm build:extension
127
+ ```
128
+ 2. Load in Chrome/Edge:
129
+ - Open `chrome://extensions/` (or `edge://extensions/`)
130
+ - Enable "Developer mode"
131
+ - Click "Load unpacked"
132
+ - Select `packages/extension/dist`
133
+ 3. Configure the extension:
134
+ - Click the extension icon in your toolbar
135
+ - Toggle the switch to enable proxying
136
+ - Adjust the regex pattern if needed (default: `^.*/xrpc/`)
137
+ - Verify the status indicator shows "Connected"
138
+
139
+ ## Resources
140
+
141
+ - [AT Protocol Documentation](https://atproto.com)
142
+ - [XRPC Specification](https://atproto.com/specs/xrpc)
143
+ - [Bluesky Developer Resources](https://docs.bsky.app)
144
+
145
+ ---
146
+
147
+ **Note**: This extension does not collect, store, or transmit any data outside of your local machine. All request handling, session management, and data processing occurs entirely under your control.
148
+
149
+ ## License
150
+
151
+ MIT License
@@ -0,0 +1,6 @@
1
+ import { Agent } from "@atproto/api";
2
+ export declare const authenticate: (handle: string, password: string) => Promise<{
3
+ agent: Agent;
4
+ did: string;
5
+ }>;
6
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/config/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,cAAc,CAAC;AAExD,eAAO,MAAM,YAAY,GAAU,QAAQ,MAAM,EAAE,UAAU,MAAM;;;EAYlE,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authenticate = void 0;
4
+ const api_1 = require("@atproto/api");
5
+ const authenticate = async (handle, password) => {
6
+ const credentials = new api_1.CredentialSession(new URL("https://bsky.social"));
7
+ await credentials.login({
8
+ identifier: handle,
9
+ password: password,
10
+ });
11
+ const agent = new api_1.Agent(credentials);
12
+ const did = agent.did;
13
+ if (!did)
14
+ throw new Error("Authentication failed");
15
+ return { agent, did };
16
+ };
17
+ exports.authenticate = authenticate;
18
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/config/auth.ts"],"names":[],"mappings":";;;AAAA,sCAAwD;AAEjD,MAAM,YAAY,GAAG,KAAK,EAAE,MAAc,EAAE,QAAgB,EAAE,EAAE;IACnE,MAAM,WAAW,GAAG,IAAI,uBAAiB,CAAC,IAAI,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC1E,MAAM,WAAW,CAAC,KAAK,CAAC;QACpB,UAAU,EAAE,MAAM;QAClB,QAAQ,EAAE,QAAQ;KACrB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,IAAI,WAAK,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IAEtB,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEnD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC,CAAC;AAZW,QAAA,YAAY,gBAYvB"}
@@ -0,0 +1,4 @@
1
+ import { type ProxyConfig } from "./types";
2
+ export declare const loadConfig: () => Promise<ProxyConfig>;
3
+ export declare const saveConfig: (config: ProxyConfig) => Promise<void>;
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,WAAW,CAOtD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,QAAQ,WAAW,KAAG,OAAO,CAAC,IAAI,CAElE,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveConfig = exports.loadConfig = void 0;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ const os_1 = require("os");
7
+ const CONFIG_FILE = (0, path_1.join)((0, os_1.homedir)(), ".atproxy.json");
8
+ const loadConfig = async () => {
9
+ try {
10
+ const content = await (0, promises_1.readFile)(CONFIG_FILE, "utf-8");
11
+ return JSON.parse(content);
12
+ }
13
+ catch {
14
+ return {};
15
+ }
16
+ };
17
+ exports.loadConfig = loadConfig;
18
+ const saveConfig = async (config) => {
19
+ return (0, promises_1.writeFile)(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
20
+ };
21
+ exports.saveConfig = saveConfig;
22
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":";;;AAAA,0CAAkD;AAClD,+BAA4B;AAC5B,2BAA6B;AAI7B,MAAM,WAAW,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,eAAe,CAAC,CAAC;AAE9C,MAAM,UAAU,GAAG,KAAK,IAA0B,EAAE;IACvD,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC,CAAC;AAPW,QAAA,UAAU,cAOrB;AAEK,MAAM,UAAU,GAAG,KAAK,EAAE,MAAmB,EAAiB,EAAE;IACnE,OAAO,IAAA,oBAAS,EAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC5E,CAAC,CAAC;AAFW,QAAA,UAAU,cAErB"}
@@ -0,0 +1,2 @@
1
+ export declare const PERMISSIONS: ("app.bsky.actor.defs" | "app.bsky.actor.getPreferences" | "app.bsky.actor.getProfile" | "app.bsky.actor.getProfiles" | "app.bsky.actor.getSuggestions" | "app.bsky.actor.profile" | "app.bsky.actor.putPreferences" | "app.bsky.actor.searchActors" | "app.bsky.actor.searchActorsTypeahead" | "app.bsky.actor.status" | "app.bsky.ageassurance.begin" | "app.bsky.ageassurance.defs" | "app.bsky.ageassurance.getConfig" | "app.bsky.ageassurance.getState" | "app.bsky.bookmark.createBookmark" | "app.bsky.bookmark.defs" | "app.bsky.bookmark.deleteBookmark" | "app.bsky.bookmark.getBookmarks" | "app.bsky.contact.defs" | "app.bsky.contact.dismissMatch" | "app.bsky.contact.getMatches" | "app.bsky.contact.getSyncStatus" | "app.bsky.contact.importContacts" | "app.bsky.contact.removeData" | "app.bsky.contact.sendNotification" | "app.bsky.contact.startPhoneVerification" | "app.bsky.contact.verifyPhone" | "app.bsky.embed.defs" | "app.bsky.embed.external" | "app.bsky.embed.images" | "app.bsky.embed.record" | "app.bsky.embed.recordWithMedia" | "app.bsky.embed.video" | "app.bsky.feed.defs" | "app.bsky.feed.describeFeedGenerator" | "app.bsky.feed.generator" | "app.bsky.feed.getActorFeeds" | "app.bsky.feed.getActorLikes" | "app.bsky.feed.getAuthorFeed" | "app.bsky.feed.getFeed" | "app.bsky.feed.getFeedGenerator" | "app.bsky.feed.getFeedGenerators" | "app.bsky.feed.getFeedSkeleton" | "app.bsky.feed.getLikes" | "app.bsky.feed.getListFeed" | "app.bsky.feed.getPostThread" | "app.bsky.feed.getPosts" | "app.bsky.feed.getQuotes" | "app.bsky.feed.getRepostedBy" | "app.bsky.feed.getSuggestedFeeds" | "app.bsky.feed.getTimeline" | "app.bsky.feed.like" | "app.bsky.feed.post" | "app.bsky.feed.postgate" | "app.bsky.feed.repost" | "app.bsky.feed.searchPosts" | "app.bsky.feed.sendInteractions" | "app.bsky.feed.threadgate" | "app.bsky.graph.block" | "app.bsky.graph.defs" | "app.bsky.graph.follow" | "app.bsky.graph.getActorStarterPacks" | "app.bsky.graph.getBlocks" | "app.bsky.graph.getFollowers" | "app.bsky.graph.getFollows" | "app.bsky.graph.getKnownFollowers" | "app.bsky.graph.getList" | "app.bsky.graph.getListBlocks" | "app.bsky.graph.getListMutes" | "app.bsky.graph.getLists" | "app.bsky.graph.getListsWithMembership" | "app.bsky.graph.getMutes" | "app.bsky.graph.getRelationships" | "app.bsky.graph.getStarterPack" | "app.bsky.graph.getStarterPacks" | "app.bsky.graph.getStarterPacksWithMembership" | "app.bsky.graph.getSuggestedFollowsByActor" | "app.bsky.graph.list" | "app.bsky.graph.listblock" | "app.bsky.graph.listitem" | "app.bsky.graph.muteActor" | "app.bsky.graph.muteActorList" | "app.bsky.graph.muteThread" | "app.bsky.graph.searchStarterPacks" | "app.bsky.graph.starterpack" | "app.bsky.graph.unmuteActor" | "app.bsky.graph.unmuteActorList" | "app.bsky.graph.unmuteThread" | "app.bsky.graph.verification" | "app.bsky.labeler.defs" | "app.bsky.labeler.getServices" | "app.bsky.labeler.service" | "app.bsky.notification.declaration" | "app.bsky.notification.defs" | "app.bsky.notification.getPreferences" | "app.bsky.notification.getUnreadCount" | "app.bsky.notification.listActivitySubscriptions" | "app.bsky.notification.listNotifications" | "app.bsky.notification.putActivitySubscription" | "app.bsky.notification.putPreferences" | "app.bsky.notification.putPreferencesV2" | "app.bsky.notification.registerPush" | "app.bsky.notification.unregisterPush" | "app.bsky.notification.updateSeen" | "app.bsky.richtext.facet" | "app.bsky.unspecced.defs" | "app.bsky.unspecced.getAgeAssuranceState" | "app.bsky.unspecced.getConfig" | "app.bsky.unspecced.getOnboardingSuggestedStarterPacks" | "app.bsky.unspecced.getOnboardingSuggestedStarterPacksSkeleton" | "app.bsky.unspecced.getPopularFeedGenerators" | "app.bsky.unspecced.getPostThreadOtherV2" | "app.bsky.unspecced.getPostThreadV2" | "app.bsky.unspecced.getSuggestedFeeds" | "app.bsky.unspecced.getSuggestedFeedsSkeleton" | "app.bsky.unspecced.getSuggestedStarterPacks" | "app.bsky.unspecced.getSuggestedStarterPacksSkeleton" | "app.bsky.unspecced.getSuggestedUsers" | "app.bsky.unspecced.getSuggestedUsersSkeleton" | "app.bsky.unspecced.getSuggestionsSkeleton" | "app.bsky.unspecced.getTaggedSuggestions" | "app.bsky.unspecced.getTrendingTopics" | "app.bsky.unspecced.getTrends" | "app.bsky.unspecced.getTrendsSkeleton" | "app.bsky.unspecced.initAgeAssurance" | "app.bsky.unspecced.searchActorsSkeleton" | "app.bsky.unspecced.searchPostsSkeleton" | "app.bsky.unspecced.searchStarterPacksSkeleton" | "app.bsky.video.defs" | "app.bsky.video.getJobStatus" | "app.bsky.video.getUploadLimits" | "app.bsky.video.uploadVideo" | "chat.bsky.actor.declaration" | "chat.bsky.actor.defs" | "chat.bsky.actor.deleteAccount" | "chat.bsky.actor.exportAccountData" | "chat.bsky.convo.acceptConvo" | "chat.bsky.convo.addReaction" | "chat.bsky.convo.defs" | "chat.bsky.convo.deleteMessageForSelf" | "chat.bsky.convo.getConvo" | "chat.bsky.convo.getConvoAvailability" | "chat.bsky.convo.getConvoForMembers" | "chat.bsky.convo.getLog" | "chat.bsky.convo.getMessages" | "chat.bsky.convo.leaveConvo" | "chat.bsky.convo.listConvos" | "chat.bsky.convo.muteConvo" | "chat.bsky.convo.removeReaction" | "chat.bsky.convo.sendMessage" | "chat.bsky.convo.sendMessageBatch" | "chat.bsky.convo.unmuteConvo" | "chat.bsky.convo.updateAllRead" | "chat.bsky.convo.updateRead" | "chat.bsky.moderation.getActorMetadata" | "chat.bsky.moderation.getMessageContext" | "chat.bsky.moderation.updateActorAccess" | "com.atproto.admin.defs" | "com.atproto.admin.deleteAccount" | "com.atproto.admin.disableAccountInvites" | "com.atproto.admin.disableInviteCodes" | "com.atproto.admin.enableAccountInvites" | "com.atproto.admin.getAccountInfo" | "com.atproto.admin.getAccountInfos" | "com.atproto.admin.getInviteCodes" | "com.atproto.admin.getSubjectStatus" | "com.atproto.admin.searchAccounts" | "com.atproto.admin.sendEmail" | "com.atproto.admin.updateAccountEmail" | "com.atproto.admin.updateAccountHandle" | "com.atproto.admin.updateAccountPassword" | "com.atproto.admin.updateAccountSigningKey" | "com.atproto.admin.updateSubjectStatus" | "com.atproto.identity.defs" | "com.atproto.identity.getRecommendedDidCredentials" | "com.atproto.identity.refreshIdentity" | "com.atproto.identity.requestPlcOperationSignature" | "com.atproto.identity.resolveDid" | "com.atproto.identity.resolveHandle" | "com.atproto.identity.resolveIdentity" | "com.atproto.identity.signPlcOperation" | "com.atproto.identity.submitPlcOperation" | "com.atproto.identity.updateHandle" | "com.atproto.label.defs" | "com.atproto.label.queryLabels" | "com.atproto.label.subscribeLabels" | "com.atproto.lexicon.resolveLexicon" | "com.atproto.lexicon.schema" | "com.atproto.moderation.createReport" | "com.atproto.moderation.defs" | "com.atproto.repo.applyWrites" | "com.atproto.repo.createRecord" | "com.atproto.repo.defs" | "com.atproto.repo.deleteRecord" | "com.atproto.repo.describeRepo" | "com.atproto.repo.getRecord" | "com.atproto.repo.importRepo" | "com.atproto.repo.listMissingBlobs" | "com.atproto.repo.listRecords" | "com.atproto.repo.putRecord" | "com.atproto.repo.strongRef" | "com.atproto.repo.uploadBlob" | "com.atproto.server.activateAccount" | "com.atproto.server.checkAccountStatus" | "com.atproto.server.confirmEmail" | "com.atproto.server.createAccount" | "com.atproto.server.createAppPassword" | "com.atproto.server.createInviteCode" | "com.atproto.server.createInviteCodes" | "com.atproto.server.createSession" | "com.atproto.server.deactivateAccount" | "com.atproto.server.defs" | "com.atproto.server.deleteAccount" | "com.atproto.server.deleteSession" | "com.atproto.server.describeServer" | "com.atproto.server.getAccountInviteCodes" | "com.atproto.server.getServiceAuth" | "com.atproto.server.getSession" | "com.atproto.server.listAppPasswords" | "com.atproto.server.refreshSession" | "com.atproto.server.requestAccountDelete" | "com.atproto.server.requestEmailConfirmation" | "com.atproto.server.requestEmailUpdate" | "com.atproto.server.requestPasswordReset" | "com.atproto.server.reserveSigningKey" | "com.atproto.server.resetPassword" | "com.atproto.server.revokeAppPassword" | "com.atproto.server.updateEmail" | "com.atproto.sync.defs" | "com.atproto.sync.getBlob" | "com.atproto.sync.getBlocks" | "com.atproto.sync.getCheckout" | "com.atproto.sync.getHead" | "com.atproto.sync.getHostStatus" | "com.atproto.sync.getLatestCommit" | "com.atproto.sync.getRecord" | "com.atproto.sync.getRepo" | "com.atproto.sync.getRepoStatus" | "com.atproto.sync.listBlobs" | "com.atproto.sync.listHosts" | "com.atproto.sync.listRepos" | "com.atproto.sync.listReposByCollection" | "com.atproto.sync.notifyOfUpdate" | "com.atproto.sync.requestCrawl" | "com.atproto.sync.subscribeRepos" | "com.atproto.temp.addReservedHandle" | "com.atproto.temp.checkHandleAvailability" | "com.atproto.temp.checkSignupQueue" | "com.atproto.temp.dereferenceScope" | "com.atproto.temp.fetchLabels" | "com.atproto.temp.requestPhoneVerification" | "com.atproto.temp.revokeAccountCredentials" | "tools.ozone.communication.createTemplate" | "tools.ozone.communication.defs" | "tools.ozone.communication.deleteTemplate" | "tools.ozone.communication.listTemplates" | "tools.ozone.communication.updateTemplate" | "tools.ozone.hosting.getAccountHistory" | "tools.ozone.moderation.cancelScheduledActions" | "tools.ozone.moderation.defs" | "tools.ozone.moderation.emitEvent" | "tools.ozone.moderation.getAccountTimeline" | "tools.ozone.moderation.getEvent" | "tools.ozone.moderation.getRecord" | "tools.ozone.moderation.getRecords" | "tools.ozone.moderation.getRepo" | "tools.ozone.moderation.getReporterStats" | "tools.ozone.moderation.getRepos" | "tools.ozone.moderation.getSubjects" | "tools.ozone.moderation.listScheduledActions" | "tools.ozone.moderation.queryEvents" | "tools.ozone.moderation.queryStatuses" | "tools.ozone.moderation.scheduleAction" | "tools.ozone.moderation.searchRepos" | "tools.ozone.report.defs" | "tools.ozone.safelink.addRule" | "tools.ozone.safelink.defs" | "tools.ozone.safelink.queryEvents" | "tools.ozone.safelink.queryRules" | "tools.ozone.safelink.removeRule" | "tools.ozone.safelink.updateRule" | "tools.ozone.server.getConfig" | "tools.ozone.set.addValues" | "tools.ozone.set.defs" | "tools.ozone.set.deleteSet" | "tools.ozone.set.deleteValues" | "tools.ozone.set.getValues" | "tools.ozone.set.querySets" | "tools.ozone.set.upsertSet" | "tools.ozone.setting.defs" | "tools.ozone.setting.listOptions" | "tools.ozone.setting.removeOptions" | "tools.ozone.setting.upsertOption" | "tools.ozone.signature.defs" | "tools.ozone.signature.findCorrelation" | "tools.ozone.signature.findRelatedAccounts" | "tools.ozone.signature.searchAccounts" | "tools.ozone.team.addMember" | "tools.ozone.team.defs" | "tools.ozone.team.deleteMember" | "tools.ozone.team.listMembers" | "tools.ozone.team.updateMember" | "tools.ozone.verification.defs" | "tools.ozone.verification.grantVerifications" | "tools.ozone.verification.listVerifications" | "tools.ozone.verification.revokeVerifications")[];
2
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/config/permissions.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,6tVAEK,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PERMISSIONS = void 0;
4
+ const lexicons_1 = require("@atproto/api/dist/client/lexicons");
5
+ exports.PERMISSIONS = Object.values(lexicons_1.schemaDict)
6
+ .filter((value) => "main" in value.defs && ["query", "procedure"].includes(value.defs.main.type))
7
+ .map((value) => value.id);
8
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/config/permissions.ts"],"names":[],"mappings":";;;AAAA,gEAA+D;AAElD,QAAA,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,qBAAU,CAAC;KAC/C,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KAChG,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { ProxyConfig } from "./types";
2
+ export declare const promptHandle: (defaultHandle?: string) => Promise<string>;
3
+ export declare const promptPassword: () => Promise<string>;
4
+ export declare const promptPermissions: (config: ProxyConfig) => Promise<string[]>;
5
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/config/prompts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC,eAAO,MAAM,YAAY,GAAU,gBAAgB,MAAM,KAAG,OAAO,CAAC,MAAM,CAWzE,CAAC;AAEF,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,CAWrD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,QAAQ,WAAW,KAAG,OAAO,CAAC,MAAM,EAAE,CAe7E,CAAC"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.promptPermissions = exports.promptPassword = exports.promptHandle = void 0;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ const permissions_1 = require("./permissions");
9
+ const promptHandle = async (defaultHandle) => {
10
+ const answer = await inquirer_1.default.prompt([
11
+ {
12
+ type: "input",
13
+ name: "handle",
14
+ message: "Enter your handle (e.g., handle.example.com):",
15
+ default: defaultHandle,
16
+ validate: (input) => input.trim().length > 0 || "Handle is required",
17
+ },
18
+ ]);
19
+ return answer.handle.trim();
20
+ };
21
+ exports.promptHandle = promptHandle;
22
+ const promptPassword = async () => {
23
+ const answer = await inquirer_1.default.prompt([
24
+ {
25
+ type: "password",
26
+ name: "password",
27
+ message: "Enter your account or app password:",
28
+ mask: "*",
29
+ validate: (input) => input.length > 0 || "Password is required",
30
+ },
31
+ ]);
32
+ return answer.password;
33
+ };
34
+ exports.promptPassword = promptPassword;
35
+ const promptPermissions = async (config) => {
36
+ const answer = await inquirer_1.default.prompt([
37
+ {
38
+ type: "checkbox",
39
+ name: "permissions",
40
+ message: "Select permissions (use space to select, enter to confirm):",
41
+ choices: permissions_1.PERMISSIONS.map((perm) => ({
42
+ name: perm,
43
+ value: perm,
44
+ checked: config.permissions?.includes(perm),
45
+ })),
46
+ pageSize: 15,
47
+ },
48
+ ]);
49
+ return answer.permissions;
50
+ };
51
+ exports.promptPermissions = promptPermissions;
52
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/config/prompts.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAGhC,+CAA4C;AAErC,MAAM,YAAY,GAAG,KAAK,EAAE,aAAsB,EAAmB,EAAE;IAC1E,MAAM,MAAM,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;QACjC;YACI,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,+CAA+C;YACxD,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,oBAAoB;SAC/E;KACJ,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAChC,CAAC,CAAC;AAXW,QAAA,YAAY,gBAWvB;AAEK,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACtD,MAAM,MAAM,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;QACjC;YACI,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,qCAAqC;YAC9C,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,sBAAsB;SAC1E;KACJ,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,QAAQ,CAAC;AAC3B,CAAC,CAAC;AAXW,QAAA,cAAc,kBAWzB;AAEK,MAAM,iBAAiB,GAAG,KAAK,EAAE,MAAmB,EAAqB,EAAE;IAC9E,MAAM,MAAM,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;QACjC;YACI,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,6DAA6D;YACtE,OAAO,EAAE,yBAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAChC,IAAI,EAAE,IAAI;gBACV,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC;aAC9C,CAAC,CAAC;YACH,QAAQ,EAAE,EAAE;SACf;KACJ,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,WAAW,CAAC;AAC9B,CAAC,CAAC;AAfW,QAAA,iBAAiB,qBAe5B"}
@@ -0,0 +1,6 @@
1
+ export interface ProxyConfig {
2
+ handle?: string;
3
+ permissions?: string[];
4
+ port?: number;
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const yargs_1 = __importDefault(require("yargs"));
8
+ const helpers_1 = require("yargs/helpers");
9
+ const config_1 = require("./config/config");
10
+ const server_1 = require("./server/server");
11
+ const auth_1 = require("./config/auth");
12
+ const prompts_1 = require("./config/prompts");
13
+ const DEFAULT_PORT = 9523;
14
+ const main = async () => {
15
+ const config = await (0, config_1.loadConfig)();
16
+ const argv = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
17
+ .option("handle", {
18
+ type: "string",
19
+ description: "Handle (e.g., handle.example.com)",
20
+ })
21
+ .option("permissions", {
22
+ type: "array",
23
+ description: "Permissions to enable (can be specified multiple times)",
24
+ string: true,
25
+ })
26
+ .option("port", {
27
+ type: "number",
28
+ description: "Port number for the server",
29
+ })
30
+ .parse();
31
+ const port = argv.port || config.port || DEFAULT_PORT;
32
+ console.log("Starting XRPC Server\n");
33
+ const handle = argv.handle || (await (0, prompts_1.promptHandle)(config.handle));
34
+ const password = await (0, prompts_1.promptPassword)();
35
+ const selectedPermissions = (argv.permissions && argv.permissions.length > 0
36
+ ? argv.permissions
37
+ : await (0, prompts_1.promptPermissions)(config)) || [];
38
+ if (selectedPermissions.length === 0) {
39
+ console.error("Error: At least one permission must be selected");
40
+ process.exit(1);
41
+ }
42
+ await (0, config_1.saveConfig)({
43
+ handle,
44
+ permissions: selectedPermissions,
45
+ port,
46
+ });
47
+ console.log("\nAuthenticating...");
48
+ try {
49
+ const { agent, did } = await (0, auth_1.authenticate)(handle, password);
50
+ console.log(`Authenticated as ${did}\n`);
51
+ await (0, server_1.createServer)({
52
+ agent,
53
+ did,
54
+ permissions: selectedPermissions,
55
+ port,
56
+ });
57
+ }
58
+ catch (error) {
59
+ console.error("Authentication failed:", error instanceof Error ? error.message : error);
60
+ process.exit(1);
61
+ }
62
+ };
63
+ main().catch((error) => {
64
+ console.error("Error:", error);
65
+ process.exit(1);
66
+ });
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAEA,kDAA0B;AAC1B,2CAAwC;AAExC,4CAAyD;AACzD,4CAA+C;AAC/C,wCAA6C;AAC7C,8CAAmF;AAEnF,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;IACnC,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAU,GAAE,CAAC;IAClC,MAAM,IAAI,GAAG,MAAM,IAAA,eAAK,EAAC,IAAA,iBAAO,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC1C,MAAM,CAAC,QAAQ,EAAE;QACd,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mCAAmC;KACnD,CAAC;SACD,MAAM,CAAC,aAAa,EAAE;QACnB,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,yDAAyD;QACtE,MAAM,EAAE,IAAI;KACf,CAAC;SACD,MAAM,CAAC,MAAM,EAAE;QACZ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,4BAA4B;KAC5C,CAAC;SACD,KAAK,EAAE,CAAC;IAEb,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,YAAY,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAA,sBAAY,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,IAAA,wBAAc,GAAE,CAAC;IAExC,MAAM,mBAAmB,GACrB,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAC5C,CAAC,CAAE,IAAI,CAAC,WAAwB;QAChC,CAAC,CAAC,MAAM,IAAA,2BAAiB,EAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAEjD,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,IAAA,mBAAU,EAAC;QACb,MAAM;QACN,WAAW,EAAE,mBAAmB;QAChC,IAAI;KACP,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,IAAA,mBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;QAEzC,MAAM,IAAA,qBAAY,EAAC;YACf,KAAK;YACL,GAAG;YACH,WAAW,EAAE,mBAAmB;YAChC,IAAI;SACP,CAAC,CAAC;IACP,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { IncomingMessage, ServerResponse } from "http";
2
+ import { type ServerConfig } from "./types";
3
+ export declare const GET: (req: IncomingMessage, res: ServerResponse, path: string, config: ServerConfig) => Promise<void>;
4
+ export declare const POST: (req: IncomingMessage, res: ServerResponse, path: string, config: ServerConfig) => Promise<void>;
5
+ //# sourceMappingURL=methods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../../src/server/methods.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,eAAO,MAAM,GAAG,GACZ,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,MAAM,EACZ,QAAQ,YAAY,KACrB,OAAO,CAAC,IAAI,CAsBd,CAAC;AAEF,eAAO,MAAM,IAAI,GACb,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,MAAM,EACZ,QAAQ,YAAY,KACrB,OAAO,CAAC,IAAI,CAmBd,CAAC"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = exports.GET = void 0;
4
+ const path_utils_1 = require("../utils/path-utils");
5
+ const http_utils_1 = require("../utils/http-utils");
6
+ const GET = async (req, res, path, config) => {
7
+ if (!(0, path_utils_1.checkIsQueryPath)(path) || !config.permissions.includes(path)) {
8
+ console.log("Blocked request: ", path);
9
+ return (0, http_utils_1.sendJson)(res, 400, {});
10
+ }
11
+ try {
12
+ const params = (0, path_utils_1.parseQueryParams)(req.url || "");
13
+ if (params.actor === "did:me") {
14
+ if (!config.did)
15
+ return (0, http_utils_1.sendJson)(res, 200, null);
16
+ params.actor = config.did;
17
+ }
18
+ delete params.lang;
19
+ const response = await config.agent.call(path, params);
20
+ return (0, http_utils_1.sendJson)(res, 200, response.data);
21
+ }
22
+ catch (e) {
23
+ console.error(e);
24
+ if (e instanceof Error && "status" in e && typeof e.status === "number") {
25
+ return (0, http_utils_1.sendJson)(res, e.status, { message: e.message });
26
+ }
27
+ return (0, http_utils_1.sendJson)(res, 400, {});
28
+ }
29
+ };
30
+ exports.GET = GET;
31
+ const POST = async (req, res, path, config) => {
32
+ if (!(0, path_utils_1.checkIsProcedurePath)(path) || !config.permissions.includes(path)) {
33
+ return (0, http_utils_1.sendJson)(res, 400, {});
34
+ }
35
+ try {
36
+ const queryParams = (0, path_utils_1.parseQueryParams)(req.url || "");
37
+ const response = await config.agent.call(path, queryParams, req, {
38
+ encoding: req.headers["content-type"],
39
+ headers: req.headers,
40
+ });
41
+ return (0, http_utils_1.sendJson)(res, 200, response.data);
42
+ }
43
+ catch (e) {
44
+ console.error(e);
45
+ if (e instanceof Error && "status" in e && typeof e.status === "number") {
46
+ return (0, http_utils_1.sendJson)(res, e.status, { message: e.message });
47
+ }
48
+ return (0, http_utils_1.sendJson)(res, 400, {});
49
+ }
50
+ };
51
+ exports.POST = POST;
52
+ //# sourceMappingURL=methods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/server/methods.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { IncomingMessage, ServerResponse } from "http";
2
+ import { type ServerConfig } from "./types";
3
+ export declare const createRequestHandler: (config: ServerConfig) => (req: IncomingMessage, res: ServerResponse) => Promise<void>;
4
+ //# sourceMappingURL=request-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-handler.d.ts","sourceRoot":"","sources":["../../src/server/request-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAGvD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,eAAO,MAAM,oBAAoB,GAAI,QAAQ,YAAY,MACvC,KAAK,eAAe,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,IAAI,CAsBzE,CAAC"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRequestHandler = void 0;
4
+ const url_1 = require("url");
5
+ const methods_1 = require("./methods");
6
+ const path_utils_1 = require("../utils/path-utils");
7
+ const http_utils_1 = require("../utils/http-utils");
8
+ const createRequestHandler = (config) => {
9
+ return async (req, res) => {
10
+ const url = new url_1.URL(req.url || "", `http://localhost`);
11
+ const path = (0, path_utils_1.parsePath)(url.pathname || "");
12
+ if (path === null) {
13
+ return (0, http_utils_1.sendJson)(res, 404, { error: "Not found" });
14
+ }
15
+ if (path === "") {
16
+ return (0, http_utils_1.sendJson)(res, 200, {});
17
+ }
18
+ console.log(`[${req.method}] ${req.url?.replace(url.origin, "")}`);
19
+ if (req.method === "GET") {
20
+ return (0, methods_1.GET)(req, res, path, config);
21
+ }
22
+ else if (req.method === "POST") {
23
+ return (0, methods_1.POST)(req, res, path, config);
24
+ }
25
+ else {
26
+ return (0, http_utils_1.sendJson)(res, 405, { error: "Method not allowed" });
27
+ }
28
+ };
29
+ };
30
+ exports.createRequestHandler = createRequestHandler;
31
+ //# sourceMappingURL=request-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-handler.js","sourceRoot":"","sources":["../../src/server/request-handler.ts"],"names":[],"mappings":";;;AACA,6BAA0B;AAG1B,uCAAsC;AACtC,oDAAgD;AAChD,oDAA+C;AAExC,MAAM,oBAAoB,GAAG,CAAC,MAAoB,EAAE,EAAE;IACzD,OAAO,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAiB,EAAE;QACtE,MAAM,GAAG,GAAG,IAAI,SAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,kBAAkB,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,IAAA,sBAAS,EAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAE3C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAChB,OAAO,IAAA,qBAAQ,EAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACd,OAAO,IAAA,qBAAQ,EAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAEnE,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACvB,OAAO,IAAA,aAAG,EAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,IAAA,cAAI,EAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACJ,OAAO,IAAA,qBAAQ,EAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC,CAAC;AACN,CAAC,CAAC;AAvBW,QAAA,oBAAoB,wBAuB/B"}
@@ -0,0 +1,3 @@
1
+ import { type ServerConfig } from "./types";
2
+ export declare const createServer: (config: ServerConfig) => Promise<void>;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,KAAG,OAAO,CAAC,IAAI,CAQ/D,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createServer = void 0;
4
+ const http_1 = require("http");
5
+ const request_handler_1 = require("./request-handler");
6
+ const createServer = (config) => {
7
+ const server = (0, http_1.createServer)((0, request_handler_1.createRequestHandler)(config));
8
+ return new Promise((resolve) => {
9
+ server.listen(config.port, () => {
10
+ console.log(`\nProxy server is running at http://localhost:${config.port}`);
11
+ resolve();
12
+ });
13
+ });
14
+ };
15
+ exports.createServer = createServer;
16
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":";;;AAAA,+BAAwD;AAGxD,uDAAyD;AAElD,MAAM,YAAY,GAAG,CAAC,MAAoB,EAAiB,EAAE;IAChE,MAAM,MAAM,GAAG,IAAA,mBAAgB,EAAC,IAAA,sCAAoB,EAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YAC5B,OAAO,CAAC,GAAG,CAAC,iDAAiD,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5E,OAAO,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AARW,QAAA,YAAY,gBAQvB"}
@@ -0,0 +1,8 @@
1
+ import { type Agent } from "@atproto/api";
2
+ export interface ServerConfig {
3
+ agent: Agent;
4
+ did: string;
5
+ permissions: string[];
6
+ port: number;
7
+ }
8
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import { type ServerResponse } from "http";
2
+ export declare const sendJson: (res: ServerResponse, statusCode: number, data: unknown) => void;
3
+ //# sourceMappingURL=http-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-utils.d.ts","sourceRoot":"","sources":["../../src/utils/http-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,MAAM,CAAC;AAE3C,eAAO,MAAM,QAAQ,GAAI,KAAK,cAAc,EAAE,YAAY,MAAM,EAAE,MAAM,OAAO,KAAG,IAGjF,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendJson = void 0;
4
+ const sendJson = (res, statusCode, data) => {
5
+ res.writeHead(statusCode, { "Content-Type": "application/json" });
6
+ res.end(JSON.stringify(data));
7
+ };
8
+ exports.sendJson = sendJson;
9
+ //# sourceMappingURL=http-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-utils.js","sourceRoot":"","sources":["../../src/utils/http-utils.ts"],"names":[],"mappings":";;;AAEO,MAAM,QAAQ,GAAG,CAAC,GAAmB,EAAE,UAAkB,EAAE,IAAa,EAAQ,EAAE;IACrF,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAClE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC,CAAC;AAHW,QAAA,QAAQ,YAGnB"}
@@ -0,0 +1,5 @@
1
+ export declare const checkIsQueryPath: (path: string) => boolean;
2
+ export declare const checkIsProcedurePath: (path: string) => boolean;
3
+ export declare const parseQueryParams: (url: string) => Record<string, string | string[]>;
4
+ export declare const parsePath: (pathname: string) => string | null;
5
+ //# sourceMappingURL=path-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,OAI/C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,OAInD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ9E,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,UAAU,MAAM,KAAG,MAAM,GAAG,IAErD,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePath = exports.parseQueryParams = exports.checkIsProcedurePath = exports.checkIsQueryPath = void 0;
4
+ const lexicons_1 = require("@atproto/api/dist/client/lexicons");
5
+ const invertedIds = Object.fromEntries(Object.entries(lexicons_1.ids).map(([key, value]) => [value, key]));
6
+ const checkIsQueryPath = (path) => {
7
+ if (!Object.prototype.hasOwnProperty.call(invertedIds, path))
8
+ return false;
9
+ const defs = lexicons_1.schemaDict[invertedIds[path]].defs;
10
+ return "main" in defs && defs.main.type === "query";
11
+ };
12
+ exports.checkIsQueryPath = checkIsQueryPath;
13
+ const checkIsProcedurePath = (path) => {
14
+ if (!Object.prototype.hasOwnProperty.call(invertedIds, path))
15
+ return false;
16
+ const defs = lexicons_1.schemaDict[invertedIds[path]].defs;
17
+ return "main" in defs && defs.main.type === "procedure";
18
+ };
19
+ exports.checkIsProcedurePath = checkIsProcedurePath;
20
+ const parseQueryParams = (url) => {
21
+ const urlObj = new URL(url, `http://localhost`);
22
+ const params = {};
23
+ urlObj.searchParams.forEach((value, key) => {
24
+ const existing = params[key];
25
+ params[key] = existing ? (Array.isArray(existing) ? [...existing, value] : [existing, value]) : value;
26
+ });
27
+ return params;
28
+ };
29
+ exports.parseQueryParams = parseQueryParams;
30
+ const parsePath = (pathname) => {
31
+ return pathname.startsWith("/xrpc/") ? pathname.slice(6) : null;
32
+ };
33
+ exports.parsePath = parsePath;
34
+ //# sourceMappingURL=path-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":";;;AAAA,gEAAoE;AAEpE,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,cAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAG7F,CAAC;AAEK,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAW,EAAE;IACtD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3E,MAAM,IAAI,GAAG,qBAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,OAAO,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;AACxD,CAAC,CAAC;AAJW,QAAA,gBAAgB,oBAI3B;AAEK,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAW,EAAE;IAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3E,MAAM,IAAI,GAAG,qBAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,OAAO,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;AAC5D,CAAC,CAAC;AAJW,QAAA,oBAAoB,wBAI/B;AAEK,MAAM,gBAAgB,GAAG,CAAC,GAAW,EAAqC,EAAE;IAC/E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IAChD,MAAM,MAAM,GAAsC,EAAE,CAAC;IACrD,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1G,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AARW,QAAA,gBAAgB,oBAQ3B;AAEK,MAAM,SAAS,GAAG,CAAC,QAAgB,EAAiB,EAAE;IACzD,OAAO,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACpE,CAAC,CAAC;AAFW,QAAA,SAAS,aAEpB"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "atproxy",
3
+ "version": "0.0.0-experimental-4283f3a",
4
+ "description": "XRPC proxy CLI Server",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "atproxy": "./dist/index.js",
8
+ "atp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx src/index.ts",
16
+ "start": "node dist/index.js",
17
+ "clean": "rm -rf dist"
18
+ },
19
+ "dependencies": {
20
+ "@atproto/api": "0.18.9",
21
+ "inquirer": "13.1.0",
22
+ "yargs": "18.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/inquirer": "9.0.9",
26
+ "@types/node": "25.0.3",
27
+ "@types/yargs": "17.0.35",
28
+ "tsx": "4.21.0",
29
+ "typescript": "5.9.3"
30
+ }
31
+ }