@offworld/sdk 0.2.2 → 0.3.0

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.
@@ -0,0 +1,175 @@
1
+ import { RepoSource } from "@offworld/types";
2
+ import "convex/browser";
3
+
4
+ //#region src/sync/client.d.ts
5
+ declare class SyncUnavailableError extends Error {
6
+ constructor(message?: string);
7
+ }
8
+ //#endregion
9
+ //#region src/sync.d.ts
10
+ declare class SyncError extends Error {
11
+ constructor(message: string);
12
+ }
13
+ declare class NetworkError extends SyncError {
14
+ readonly statusCode?: number | undefined;
15
+ constructor(message: string, statusCode?: number | undefined);
16
+ }
17
+ declare class AuthenticationError extends SyncError {
18
+ constructor(message?: string);
19
+ }
20
+ declare class RateLimitError extends SyncError {
21
+ constructor(message?: string);
22
+ }
23
+ declare class ConflictError extends SyncError {
24
+ readonly remoteCommitSha?: string | undefined;
25
+ constructor(message?: string, remoteCommitSha?: string | undefined);
26
+ }
27
+ declare class CommitExistsError extends SyncError {
28
+ constructor(message?: string);
29
+ }
30
+ declare class InvalidInputError extends SyncError {
31
+ constructor(message: string);
32
+ }
33
+ declare class InvalidReferenceError extends SyncError {
34
+ constructor(message: string);
35
+ }
36
+ declare class RepoNotFoundError extends SyncError {
37
+ constructor(message?: string);
38
+ }
39
+ declare class LowStarsError extends SyncError {
40
+ constructor(message?: string);
41
+ }
42
+ declare class PrivateRepoError extends SyncError {
43
+ constructor(message?: string);
44
+ }
45
+ declare class CommitNotFoundError extends SyncError {
46
+ constructor(message?: string);
47
+ }
48
+ declare class GitHubError extends SyncError {
49
+ constructor(message?: string);
50
+ }
51
+ declare class PushNotAllowedError extends SyncError {
52
+ readonly reason: "local" | "not-github";
53
+ constructor(message: string, reason: "local" | "not-github");
54
+ }
55
+ /** Reference data structure for sync operations */
56
+ interface ReferenceData {
57
+ fullName: string;
58
+ referenceName: string;
59
+ referenceDescription: string;
60
+ referenceContent: string;
61
+ commitSha: string;
62
+ generatedAt: string;
63
+ }
64
+ /** Response from pull query */
65
+ interface PullResponse {
66
+ fullName: string;
67
+ referenceName: string;
68
+ referenceDescription: string;
69
+ referenceContent: string;
70
+ commitSha: string;
71
+ generatedAt: string;
72
+ }
73
+ /** Response from check query */
74
+ interface CheckResponse {
75
+ exists: boolean;
76
+ commitSha?: string;
77
+ generatedAt?: string;
78
+ }
79
+ /** Response from push mutation */
80
+ interface PushResponse {
81
+ success: boolean;
82
+ message?: string;
83
+ }
84
+ /** Staleness check result */
85
+ interface StalenessResult {
86
+ isStale: boolean;
87
+ localCommitSha?: string;
88
+ remoteCommitSha?: string;
89
+ }
90
+ /** Can push result */
91
+ interface CanPushResult {
92
+ allowed: boolean;
93
+ reason?: string;
94
+ stars?: number;
95
+ }
96
+ /**
97
+ * Fetches reference from the remote server
98
+ * @param fullName - Repository full name (owner/repo)
99
+ * @returns Reference data or null if not found
100
+ */
101
+ declare function pullReference(fullName: string): Promise<PullResponse | null>;
102
+ /**
103
+ * Fetches a specific reference by name from the remote server
104
+ * @param fullName - Repository full name (owner/repo)
105
+ * @param referenceName - Specific reference name to pull
106
+ * @returns Reference data or null if not found
107
+ */
108
+ declare function pullReferenceByName(fullName: string, referenceName: string): Promise<PullResponse | null>;
109
+ /**
110
+ * Pushes reference to the remote server
111
+ * All validation happens server-side
112
+ * @param reference - Reference data to push
113
+ * @param token - Authentication token
114
+ * @returns Push result
115
+ */
116
+ declare function pushReference(reference: ReferenceData, token: string): Promise<PushResponse>;
117
+ /**
118
+ * Checks if reference exists on remote server (lightweight check)
119
+ * @param fullName - Repository full name (owner/repo)
120
+ * @returns Check result
121
+ */
122
+ declare function checkRemote(fullName: string): Promise<CheckResponse>;
123
+ /**
124
+ * Checks if a specific reference exists on the remote server
125
+ * @param fullName - Repository full name (owner/repo)
126
+ * @param referenceName - Specific reference name to check
127
+ * @returns Check result
128
+ */
129
+ declare function checkRemoteByName(fullName: string, referenceName: string): Promise<CheckResponse>;
130
+ /**
131
+ * Compares local vs remote commit SHA to check staleness
132
+ * @param fullName - Repository full name (owner/repo)
133
+ * @param localCommitSha - Local commit SHA
134
+ * @returns Staleness result
135
+ */
136
+ declare function checkStaleness(fullName: string, localCommitSha: string): Promise<StalenessResult>;
137
+ /** GitHub repository metadata */
138
+ interface GitHubRepoMetadata {
139
+ stars: number;
140
+ description?: string;
141
+ language?: string;
142
+ defaultBranch: string;
143
+ }
144
+ /**
145
+ * Fetches GitHub repository metadata
146
+ * @param owner - Repository owner
147
+ * @param repo - Repository name
148
+ * @returns Repository metadata or null on error
149
+ */
150
+ declare function fetchGitHubMetadata(owner: string, repo: string): Promise<GitHubRepoMetadata | null>;
151
+ /**
152
+ * Fetches GitHub repository stars
153
+ * @param owner - Repository owner
154
+ * @param repo - Repository name
155
+ * @returns Number of stars, or 0 on error
156
+ */
157
+ declare function fetchRepoStars(owner: string, repo: string): Promise<number>;
158
+ /**
159
+ * Checks if a repository can be pushed to offworld.sh (client-side quick checks)
160
+ * Note: Star count and other validations happen server-side
161
+ *
162
+ * @param source - Repository source
163
+ * @returns Can push result
164
+ */
165
+ declare function canPushToWeb(source: RepoSource): CanPushResult;
166
+ /**
167
+ * Validates that a source can be pushed and throws appropriate error if not
168
+ * Note: This only does quick client-side checks. Full validation happens server-side.
169
+ * @param source - Repository source
170
+ * @throws PushNotAllowedError if push is not allowed
171
+ */
172
+ declare function validatePushAllowed(source: RepoSource): void;
173
+ //#endregion
174
+ export { AuthenticationError, CanPushResult, CheckResponse, CommitExistsError, CommitNotFoundError, ConflictError, GitHubError, GitHubRepoMetadata, InvalidInputError, InvalidReferenceError, LowStarsError, NetworkError, PrivateRepoError, PullResponse, PushNotAllowedError, PushResponse, RateLimitError, ReferenceData, RepoNotFoundError, StalenessResult, SyncError, SyncUnavailableError, canPushToWeb, checkRemote, checkRemoteByName, checkStaleness, fetchGitHubMetadata, fetchRepoStars, pullReference, pullReferenceByName, pushReference, validatePushAllowed };
175
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/sync/client.ts","../../src/sync.ts"],"mappings":";;;;cAEa,oBAAA,SAA6B,KAAA;cAExC,OAAA;AAAA;;;cCmCW,SAAA,SAAkB,KAAA;cAClB,OAAA;AAAA;AAAA,cAMA,YAAA,SAAqB,SAAA;EAAA,SAGhB,UAAA;cADhB,OAAA,UACgB,UAAA;AAAA;AAAA,cAOL,mBAAA,SAA4B,SAAA;cAC5B,OAAA;AAAA;AAAA,cAMA,cAAA,SAAuB,SAAA;cACvB,OAAA;AAAA;AAAA,cAMA,aAAA,SAAsB,SAAA;EAAA,SAGjB,eAAA;cADhB,OAAA,WACgB,eAAA;AAAA;AAAA,cAOL,iBAAA,SAA0B,SAAA;cAC1B,OAAA;AAAA;AAAA,cAMA,iBAAA,SAA0B,SAAA;cAC1B,OAAA;AAAA;AAAA,cAMA,qBAAA,SAA8B,SAAA;cAC9B,OAAA;AAAA;AAAA,cAMA,iBAAA,SAA0B,SAAA;cAC1B,OAAA;AAAA;AAAA,cAMA,aAAA,SAAsB,SAAA;cACtB,OAAA;AAAA;AAAA,cAMA,gBAAA,SAAyB,SAAA;cACzB,OAAA;AAAA;AAAA,cAMA,mBAAA,SAA4B,SAAA;cAC5B,OAAA;AAAA;AAAA,cAMA,WAAA,SAAoB,SAAA;cACpB,OAAA;AAAA;AAAA,cAMA,mBAAA,SAA4B,SAAA;EAAA,SAGvB,MAAA;cADhB,OAAA,UACgB,MAAA;AAAA;;UAQD,aAAA;EAChB,QAAA;EACA,aAAA;EACA,oBAAA;EACA,gBAAA;EACA,SAAA;EACA,WAAA;AAAA;;UAIgB,YAAA;EAChB,QAAA;EACA,aAAA;EACA,oBAAA;EACA,gBAAA;EACA,SAAA;EACA,WAAA;AAAA;;UAegB,aAAA;EAChB,MAAA;EACA,SAAA;EACA,WAAA;AAAA;AA9FD;AAAA,UAkGiB,YAAA;EAChB,OAAA;EACA,OAAA;AAAA;;UAIgB,eAAA;EAChB,OAAA;EACA,cAAA;EACA,eAAA;AAAA;;UAIgB,aAAA;EAChB,OAAA;EACA,MAAA;EACA,KAAA;AAAA;;AApGD;;;;iBAgHsB,aAAA,CAAc,QAAA,WAAmB,OAAA,CAAQ,YAAA;;;;;AAzG/D;;iBAwIsB,mBAAA,CACrB,QAAA,UACA,aAAA,WACE,OAAA,CAAQ,YAAA;;;;;;;AApIX;iBA4JsB,aAAA,CACrB,SAAA,EAAW,aAAA,EACX,KAAA,WACE,OAAA,CAAQ,YAAA;;;;;;iBAsDW,WAAA,CAAY,QAAA,WAAmB,OAAA,CAAQ,aAAA;;AA9M7D;;;;;iBA8OsB,iBAAA,CACrB,QAAA,UACA,aAAA,WACE,OAAA,CAAQ,aAAA;;;;AA1OX;;;iBAoQsB,cAAA,CACrB,QAAA,UACA,cAAA,WACE,OAAA,CAAQ,eAAA;;UAmBM,kBAAA;EAChB,KAAA;EACA,WAAA;EACA,QAAA;EACA,aAAA;AAAA;;;;;;;iBASqB,mBAAA,CACrB,KAAA,UACA,IAAA,WACE,OAAA,CAAQ,kBAAA;;;AAxRX;;;;iBA6TsB,cAAA,CAAe,KAAA,UAAe,IAAA,WAAe,OAAA;;;;;;;;iBAYnD,YAAA,CAAa,MAAA,EAAQ,UAAA,GAAa,aAAA;;;;;;;iBA8BlC,mBAAA,CAAoB,MAAA,EAAQ,UAAA"}
@@ -0,0 +1,4 @@
1
+ import "../config-DW8J4gl5.mjs";
2
+ import { C as pushReference, S as pullReferenceByName, T as SyncUnavailableError, _ as checkRemoteByName, a as GitHubError, b as fetchRepoStars, c as LowStarsError, d as PushNotAllowedError, f as RateLimitError, g as checkRemote, h as canPushToWeb, i as ConflictError, l as NetworkError, m as SyncError, n as CommitExistsError, o as InvalidInputError, p as RepoNotFoundError, r as CommitNotFoundError, s as InvalidReferenceError, t as AuthenticationError, u as PrivateRepoError, v as checkStaleness, w as validatePushAllowed, x as pullReference, y as fetchGitHubMetadata } from "../sync-wcy5fJRb.mjs";
3
+
4
+ export { AuthenticationError, CommitExistsError, CommitNotFoundError, ConflictError, GitHubError, InvalidInputError, InvalidReferenceError, LowStarsError, NetworkError, PrivateRepoError, PushNotAllowedError, RateLimitError, RepoNotFoundError, SyncError, SyncUnavailableError, canPushToWeb, checkRemote, checkRemoteByName, checkStaleness, fetchGitHubMetadata, fetchRepoStars, pullReference, pullReferenceByName, pushReference, validatePushAllowed };
@@ -0,0 +1,4 @@
1
+ import "./config-DW8J4gl5.mjs";
2
+ import { C as pushReference, S as pullReferenceByName, T as SyncUnavailableError, _ as checkRemoteByName, a as GitHubError, b as fetchRepoStars, c as LowStarsError, d as PushNotAllowedError, f as RateLimitError, g as checkRemote, h as canPushToWeb, i as ConflictError, l as NetworkError, m as SyncError, n as CommitExistsError, o as InvalidInputError, p as RepoNotFoundError, r as CommitNotFoundError, s as InvalidReferenceError, t as AuthenticationError, u as PrivateRepoError, v as checkStaleness, w as validatePushAllowed, x as pullReference, y as fetchGitHubMetadata } from "./sync-wcy5fJRb.mjs";
3
+
4
+ export { checkRemote };
@@ -0,0 +1,372 @@
1
+ import { d as toReferenceName } from "./config-DW8J4gl5.mjs";
2
+ import { GitHubRepoMetadataSchema } from "@offworld/types";
3
+
4
+ //#region src/sync/client.ts
5
+ var SyncUnavailableError = class extends Error {
6
+ constructor(message = "Sync requires the 'convex' package. Install it to use @offworld/sdk/sync.") {
7
+ super(message);
8
+ this.name = "SyncUnavailableError";
9
+ }
10
+ };
11
+ async function loadConvexModule() {
12
+ try {
13
+ return await import("convex/browser");
14
+ } catch (error) {
15
+ if (error?.code === "ERR_MODULE_NOT_FOUND") throw new SyncUnavailableError();
16
+ throw error;
17
+ }
18
+ }
19
+ async function getConvexClient(url, token) {
20
+ const { ConvexHttpClient } = await loadConvexModule();
21
+ const client = new ConvexHttpClient(url);
22
+ if (token) client.setAuth(token);
23
+ return client;
24
+ }
25
+
26
+ //#endregion
27
+ //#region src/sync.ts
28
+ /**
29
+ * Sync utilities for CLI-Convex communication
30
+ * Uses ConvexHttpClient for direct type-safe API calls
31
+ */
32
+ let cachedApi = null;
33
+ async function getApi() {
34
+ if (cachedApi) return cachedApi;
35
+ try {
36
+ const { api } = await import("@offworld/sdk/convex/api");
37
+ cachedApi = api;
38
+ return api;
39
+ } catch (error) {
40
+ if (error?.code === "ERR_MODULE_NOT_FOUND") throw new SyncUnavailableError("Convex API types not found. Run `bun run build` to generate SDK artifacts.");
41
+ throw error;
42
+ }
43
+ }
44
+ const PRODUCTION_CONVEX_URL = "https://trustworthy-coyote-128.convex.cloud";
45
+ function getConvexUrl() {
46
+ return process.env.CONVEX_URL ?? PRODUCTION_CONVEX_URL;
47
+ }
48
+ const GITHUB_API_BASE = "https://api.github.com";
49
+ var SyncError = class extends Error {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = "SyncError";
53
+ }
54
+ };
55
+ var NetworkError = class extends SyncError {
56
+ constructor(message, statusCode) {
57
+ super(message);
58
+ this.statusCode = statusCode;
59
+ this.name = "NetworkError";
60
+ }
61
+ };
62
+ var AuthenticationError = class extends SyncError {
63
+ constructor(message = "Authentication required. Please run 'ow auth login' first.") {
64
+ super(message);
65
+ this.name = "AuthenticationError";
66
+ }
67
+ };
68
+ var RateLimitError = class extends SyncError {
69
+ constructor(message = "Rate limit exceeded. You can push up to 3 times per repo per day.") {
70
+ super(message);
71
+ this.name = "RateLimitError";
72
+ }
73
+ };
74
+ var ConflictError = class extends SyncError {
75
+ constructor(message = "A newer reference already exists on the server.", remoteCommitSha) {
76
+ super(message);
77
+ this.remoteCommitSha = remoteCommitSha;
78
+ this.name = "ConflictError";
79
+ }
80
+ };
81
+ var CommitExistsError = class extends SyncError {
82
+ constructor(message = "A reference already exists for this commit SHA.") {
83
+ super(message);
84
+ this.name = "CommitExistsError";
85
+ }
86
+ };
87
+ var InvalidInputError = class extends SyncError {
88
+ constructor(message) {
89
+ super(message);
90
+ this.name = "InvalidInputError";
91
+ }
92
+ };
93
+ var InvalidReferenceError = class extends SyncError {
94
+ constructor(message) {
95
+ super(message);
96
+ this.name = "InvalidReferenceError";
97
+ }
98
+ };
99
+ var RepoNotFoundError = class extends SyncError {
100
+ constructor(message = "Repository not found on GitHub.") {
101
+ super(message);
102
+ this.name = "RepoNotFoundError";
103
+ }
104
+ };
105
+ var LowStarsError = class extends SyncError {
106
+ constructor(message = "Repository has less than 5 stars.") {
107
+ super(message);
108
+ this.name = "LowStarsError";
109
+ }
110
+ };
111
+ var PrivateRepoError = class extends SyncError {
112
+ constructor(message = "Private repositories are not supported.") {
113
+ super(message);
114
+ this.name = "PrivateRepoError";
115
+ }
116
+ };
117
+ var CommitNotFoundError = class extends SyncError {
118
+ constructor(message = "Commit not found in repository.") {
119
+ super(message);
120
+ this.name = "CommitNotFoundError";
121
+ }
122
+ };
123
+ var GitHubError = class extends SyncError {
124
+ constructor(message = "GitHub API error.") {
125
+ super(message);
126
+ this.name = "GitHubError";
127
+ }
128
+ };
129
+ var PushNotAllowedError = class extends SyncError {
130
+ constructor(message, reason) {
131
+ super(message);
132
+ this.reason = reason;
133
+ this.name = "PushNotAllowedError";
134
+ }
135
+ };
136
+ function toPullResponse(result) {
137
+ return {
138
+ fullName: result.fullName,
139
+ referenceName: result.referenceName,
140
+ referenceDescription: result.referenceDescription,
141
+ referenceContent: result.referenceContent,
142
+ commitSha: result.commitSha,
143
+ generatedAt: result.generatedAt
144
+ };
145
+ }
146
+ async function createClient(token) {
147
+ return getConvexClient(getConvexUrl(), token);
148
+ }
149
+ /**
150
+ * Fetches reference from the remote server
151
+ * @param fullName - Repository full name (owner/repo)
152
+ * @returns Reference data or null if not found
153
+ */
154
+ async function pullReference(fullName) {
155
+ const client = await createClient();
156
+ const api = await getApi();
157
+ try {
158
+ let result = await client.query(api.references.pull, {
159
+ fullName,
160
+ referenceName: toReferenceName(fullName)
161
+ });
162
+ if (!result) result = await client.query(api.references.pull, { fullName });
163
+ if (!result) return null;
164
+ client.mutation(api.references.recordPull, {
165
+ fullName,
166
+ referenceName: result.referenceName
167
+ }).catch(() => {});
168
+ return toPullResponse(result);
169
+ } catch (error) {
170
+ throw new NetworkError(`Failed to pull reference: ${error instanceof Error ? error.message : error}`);
171
+ }
172
+ }
173
+ /**
174
+ * Fetches a specific reference by name from the remote server
175
+ * @param fullName - Repository full name (owner/repo)
176
+ * @param referenceName - Specific reference name to pull
177
+ * @returns Reference data or null if not found
178
+ */
179
+ async function pullReferenceByName(fullName, referenceName) {
180
+ const client = await createClient();
181
+ const api = await getApi();
182
+ try {
183
+ const result = await client.query(api.references.pull, {
184
+ fullName,
185
+ referenceName
186
+ });
187
+ if (!result) return null;
188
+ client.mutation(api.references.recordPull, {
189
+ fullName,
190
+ referenceName
191
+ }).catch(() => {});
192
+ return toPullResponse(result);
193
+ } catch (error) {
194
+ throw new NetworkError(`Failed to pull reference: ${error instanceof Error ? error.message : error}`);
195
+ }
196
+ }
197
+ /**
198
+ * Pushes reference to the remote server
199
+ * All validation happens server-side
200
+ * @param reference - Reference data to push
201
+ * @param token - Authentication token
202
+ * @returns Push result
203
+ */
204
+ async function pushReference(reference, token) {
205
+ const client = await createClient(token);
206
+ const api = await getApi();
207
+ try {
208
+ const result = await client.action(api.references.push, {
209
+ fullName: reference.fullName,
210
+ referenceName: reference.referenceName,
211
+ referenceDescription: reference.referenceDescription,
212
+ referenceContent: reference.referenceContent,
213
+ commitSha: reference.commitSha,
214
+ generatedAt: reference.generatedAt
215
+ });
216
+ if (!result.success) switch (result.error) {
217
+ case "auth_required": throw new AuthenticationError();
218
+ case "rate_limit": throw new RateLimitError("Rate limit exceeded. You can push up to 20 times per day.");
219
+ case "commit_already_exists": throw new CommitExistsError(result.message);
220
+ case "invalid_input": throw new InvalidInputError(result.message ?? "Invalid input");
221
+ case "invalid_reference": throw new InvalidReferenceError(result.message ?? "Invalid reference content");
222
+ case "repo_not_found": throw new RepoNotFoundError(result.message);
223
+ case "low_stars": throw new LowStarsError(result.message);
224
+ case "private_repo": throw new PrivateRepoError(result.message);
225
+ case "commit_not_found": throw new CommitNotFoundError(result.message);
226
+ case "github_error": throw new GitHubError(result.message);
227
+ default: throw new SyncError(result.message ?? "Unknown error");
228
+ }
229
+ return { success: true };
230
+ } catch (error) {
231
+ if (error instanceof SyncError) throw error;
232
+ throw new NetworkError(`Failed to push reference: ${error instanceof Error ? error.message : error}`);
233
+ }
234
+ }
235
+ /**
236
+ * Checks if reference exists on remote server (lightweight check)
237
+ * @param fullName - Repository full name (owner/repo)
238
+ * @returns Check result
239
+ */
240
+ async function checkRemote(fullName) {
241
+ const client = await createClient();
242
+ const api = await getApi();
243
+ try {
244
+ let result = await client.query(api.references.check, {
245
+ fullName,
246
+ referenceName: toReferenceName(fullName)
247
+ });
248
+ if (!result.exists) result = await client.query(api.references.check, { fullName });
249
+ if (!result.exists) return { exists: false };
250
+ return {
251
+ exists: true,
252
+ commitSha: result.commitSha,
253
+ generatedAt: result.generatedAt
254
+ };
255
+ } catch (error) {
256
+ throw new NetworkError(`Failed to check remote: ${error instanceof Error ? error.message : error}`);
257
+ }
258
+ }
259
+ /**
260
+ * Checks if a specific reference exists on the remote server
261
+ * @param fullName - Repository full name (owner/repo)
262
+ * @param referenceName - Specific reference name to check
263
+ * @returns Check result
264
+ */
265
+ async function checkRemoteByName(fullName, referenceName) {
266
+ const client = await createClient();
267
+ const api = await getApi();
268
+ try {
269
+ const result = await client.query(api.references.check, {
270
+ fullName,
271
+ referenceName
272
+ });
273
+ if (!result.exists) return { exists: false };
274
+ return {
275
+ exists: true,
276
+ commitSha: result.commitSha,
277
+ generatedAt: result.generatedAt
278
+ };
279
+ } catch (error) {
280
+ throw new NetworkError(`Failed to check remote: ${error instanceof Error ? error.message : error}`);
281
+ }
282
+ }
283
+ /**
284
+ * Compares local vs remote commit SHA to check staleness
285
+ * @param fullName - Repository full name (owner/repo)
286
+ * @param localCommitSha - Local commit SHA
287
+ * @returns Staleness result
288
+ */
289
+ async function checkStaleness(fullName, localCommitSha) {
290
+ const remote = await checkRemote(fullName);
291
+ if (!remote.exists || !remote.commitSha) return {
292
+ isStale: false,
293
+ localCommitSha,
294
+ remoteCommitSha: void 0
295
+ };
296
+ return {
297
+ isStale: localCommitSha !== remote.commitSha,
298
+ localCommitSha,
299
+ remoteCommitSha: remote.commitSha
300
+ };
301
+ }
302
+ /**
303
+ * Fetches GitHub repository metadata
304
+ * @param owner - Repository owner
305
+ * @param repo - Repository name
306
+ * @returns Repository metadata or null on error
307
+ */
308
+ async function fetchGitHubMetadata(owner, repo) {
309
+ try {
310
+ const response = await fetch(`${GITHUB_API_BASE}/repos/${owner}/${repo}`, { headers: {
311
+ Accept: "application/vnd.github.v3+json",
312
+ "User-Agent": "offworld-cli"
313
+ } });
314
+ if (!response.ok) return null;
315
+ const json = await response.json();
316
+ const result = GitHubRepoMetadataSchema.safeParse(json);
317
+ if (!result.success) return null;
318
+ const data = result.data;
319
+ return {
320
+ stars: data.stargazers_count ?? 0,
321
+ description: data.description ?? void 0,
322
+ language: data.language ?? void 0,
323
+ defaultBranch: data.default_branch ?? "main"
324
+ };
325
+ } catch {
326
+ return null;
327
+ }
328
+ }
329
+ /**
330
+ * Fetches GitHub repository stars
331
+ * @param owner - Repository owner
332
+ * @param repo - Repository name
333
+ * @returns Number of stars, or 0 on error
334
+ */
335
+ async function fetchRepoStars(owner, repo) {
336
+ return (await fetchGitHubMetadata(owner, repo))?.stars ?? 0;
337
+ }
338
+ /**
339
+ * Checks if a repository can be pushed to offworld.sh (client-side quick checks)
340
+ * Note: Star count and other validations happen server-side
341
+ *
342
+ * @param source - Repository source
343
+ * @returns Can push result
344
+ */
345
+ function canPushToWeb(source) {
346
+ if (source.type === "local") return {
347
+ allowed: false,
348
+ reason: "Local repositories cannot be pushed to offworld.sh. Only remote repositories with a public URL are supported."
349
+ };
350
+ if (source.provider !== "github") return {
351
+ allowed: false,
352
+ reason: `${source.provider} repositories are not yet supported. GitHub support only for now - GitLab and Bitbucket coming soon!`
353
+ };
354
+ return { allowed: true };
355
+ }
356
+ /**
357
+ * Validates that a source can be pushed and throws appropriate error if not
358
+ * Note: This only does quick client-side checks. Full validation happens server-side.
359
+ * @param source - Repository source
360
+ * @throws PushNotAllowedError if push is not allowed
361
+ */
362
+ function validatePushAllowed(source) {
363
+ const result = canPushToWeb(source);
364
+ if (!result.allowed) {
365
+ const reason = source.type === "local" ? "local" : "not-github";
366
+ throw new PushNotAllowedError(result.reason, reason);
367
+ }
368
+ }
369
+
370
+ //#endregion
371
+ export { pushReference as C, pullReferenceByName as S, SyncUnavailableError as T, checkRemoteByName as _, GitHubError as a, fetchRepoStars as b, LowStarsError as c, PushNotAllowedError as d, RateLimitError as f, checkRemote as g, canPushToWeb as h, ConflictError as i, NetworkError as l, SyncError as m, CommitExistsError as n, InvalidInputError as o, RepoNotFoundError as p, CommitNotFoundError as r, InvalidReferenceError as s, AuthenticationError as t, PrivateRepoError as u, checkStaleness as v, validatePushAllowed as w, pullReference as x, fetchGitHubMetadata as y };
372
+ //# sourceMappingURL=sync-wcy5fJRb.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-wcy5fJRb.mjs","names":[],"sources":["../src/sync/client.ts","../src/sync.ts"],"sourcesContent":["import type { ConvexHttpClient } from \"convex/browser\";\n\nexport class SyncUnavailableError extends Error {\n\tconstructor(\n\t\tmessage = \"Sync requires the 'convex' package. Install it to use @offworld/sdk/sync.\",\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncUnavailableError\";\n\t}\n}\n\nasync function loadConvexModule(): Promise<typeof import(\"convex/browser\")> {\n\ttry {\n\t\treturn await import(\"convex/browser\");\n\t} catch (error) {\n\t\tconst err = error as { code?: string };\n\t\tif (err?.code === \"ERR_MODULE_NOT_FOUND\") {\n\t\t\tthrow new SyncUnavailableError();\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nexport async function getConvexClient(url: string, token?: string): Promise<ConvexHttpClient> {\n\tconst { ConvexHttpClient } = await loadConvexModule();\n\tconst client = new ConvexHttpClient(url);\n\tif (token) client.setAuth(token);\n\treturn client;\n}\n","/**\n * Sync utilities for CLI-Convex communication\n * Uses ConvexHttpClient for direct type-safe API calls\n */\n\nimport { toReferenceName } from \"./config.js\";\nimport { GitHubRepoMetadataSchema, type RepoSource } from \"@offworld/types\";\nimport { getConvexClient, SyncUnavailableError } from \"./sync/client.js\";\n\ntype ConvexApi = typeof import(\"@offworld/sdk/convex/api\").api;\n\nlet cachedApi: ConvexApi | null = null;\n\nasync function getApi(): Promise<ConvexApi> {\n\tif (cachedApi) return cachedApi;\n\ttry {\n\t\tconst { api } = await import(\"@offworld/sdk/convex/api\");\n\t\tcachedApi = api;\n\t\treturn api;\n\t} catch (error) {\n\t\tconst err = error as { code?: string };\n\t\tif (err?.code === \"ERR_MODULE_NOT_FOUND\") {\n\t\t\tthrow new SyncUnavailableError(\n\t\t\t\t\"Convex API types not found. Run `bun run build` to generate SDK artifacts.\",\n\t\t\t);\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n// Production Convex URL - dev can override via CONVEX_URL env var\nconst PRODUCTION_CONVEX_URL = \"https://trustworthy-coyote-128.convex.cloud\";\n\nfunction getConvexUrl(): string {\n\treturn process.env.CONVEX_URL ?? PRODUCTION_CONVEX_URL;\n}\n\nconst GITHUB_API_BASE = \"https://api.github.com\";\n\nexport class SyncError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncError\";\n\t}\n}\n\nexport class NetworkError extends SyncError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly statusCode?: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"NetworkError\";\n\t}\n}\n\nexport class AuthenticationError extends SyncError {\n\tconstructor(message = \"Authentication required. Please run 'ow auth login' first.\") {\n\t\tsuper(message);\n\t\tthis.name = \"AuthenticationError\";\n\t}\n}\n\nexport class RateLimitError extends SyncError {\n\tconstructor(message = \"Rate limit exceeded. You can push up to 3 times per repo per day.\") {\n\t\tsuper(message);\n\t\tthis.name = \"RateLimitError\";\n\t}\n}\n\nexport class ConflictError extends SyncError {\n\tconstructor(\n\t\tmessage = \"A newer reference already exists on the server.\",\n\t\tpublic readonly remoteCommitSha?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"ConflictError\";\n\t}\n}\n\nexport class CommitExistsError extends SyncError {\n\tconstructor(message = \"A reference already exists for this commit SHA.\") {\n\t\tsuper(message);\n\t\tthis.name = \"CommitExistsError\";\n\t}\n}\n\nexport class InvalidInputError extends SyncError {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidInputError\";\n\t}\n}\n\nexport class InvalidReferenceError extends SyncError {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidReferenceError\";\n\t}\n}\n\nexport class RepoNotFoundError extends SyncError {\n\tconstructor(message = \"Repository not found on GitHub.\") {\n\t\tsuper(message);\n\t\tthis.name = \"RepoNotFoundError\";\n\t}\n}\n\nexport class LowStarsError extends SyncError {\n\tconstructor(message = \"Repository has less than 5 stars.\") {\n\t\tsuper(message);\n\t\tthis.name = \"LowStarsError\";\n\t}\n}\n\nexport class PrivateRepoError extends SyncError {\n\tconstructor(message = \"Private repositories are not supported.\") {\n\t\tsuper(message);\n\t\tthis.name = \"PrivateRepoError\";\n\t}\n}\n\nexport class CommitNotFoundError extends SyncError {\n\tconstructor(message = \"Commit not found in repository.\") {\n\t\tsuper(message);\n\t\tthis.name = \"CommitNotFoundError\";\n\t}\n}\n\nexport class GitHubError extends SyncError {\n\tconstructor(message = \"GitHub API error.\") {\n\t\tsuper(message);\n\t\tthis.name = \"GitHubError\";\n\t}\n}\n\nexport class PushNotAllowedError extends SyncError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly reason: \"local\" | \"not-github\",\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"PushNotAllowedError\";\n\t}\n}\n\n/** Reference data structure for sync operations */\nexport interface ReferenceData {\n\tfullName: string;\n\treferenceName: string;\n\treferenceDescription: string;\n\treferenceContent: string;\n\tcommitSha: string;\n\tgeneratedAt: string;\n}\n\n/** Response from pull query */\nexport interface PullResponse {\n\tfullName: string;\n\treferenceName: string;\n\treferenceDescription: string;\n\treferenceContent: string;\n\tcommitSha: string;\n\tgeneratedAt: string;\n}\n\nfunction toPullResponse(result: PullResponse): PullResponse {\n\treturn {\n\t\tfullName: result.fullName,\n\t\treferenceName: result.referenceName,\n\t\treferenceDescription: result.referenceDescription,\n\t\treferenceContent: result.referenceContent,\n\t\tcommitSha: result.commitSha,\n\t\tgeneratedAt: result.generatedAt,\n\t};\n}\n\n/** Response from check query */\nexport interface CheckResponse {\n\texists: boolean;\n\tcommitSha?: string;\n\tgeneratedAt?: string;\n}\n\n/** Response from push mutation */\nexport interface PushResponse {\n\tsuccess: boolean;\n\tmessage?: string;\n}\n\n/** Staleness check result */\nexport interface StalenessResult {\n\tisStale: boolean;\n\tlocalCommitSha?: string;\n\tremoteCommitSha?: string;\n}\n\n/** Can push result */\nexport interface CanPushResult {\n\tallowed: boolean;\n\treason?: string;\n\tstars?: number;\n}\n\nasync function createClient(token?: string) {\n\treturn getConvexClient(getConvexUrl(), token);\n}\n\n/**\n * Fetches reference from the remote server\n * @param fullName - Repository full name (owner/repo)\n * @returns Reference data or null if not found\n */\nexport async function pullReference(fullName: string): Promise<PullResponse | null> {\n\tconst client = await createClient();\n\tconst api = await getApi();\n\ttry {\n\t\tlet result = await client.query(api.references.pull, {\n\t\t\tfullName,\n\t\t\treferenceName: toReferenceName(fullName),\n\t\t});\n\t\tif (!result) {\n\t\t\tresult = await client.query(api.references.pull, { fullName });\n\t\t}\n\t\tif (!result) return null;\n\n\t\tclient\n\t\t\t.mutation(api.references.recordPull, { fullName, referenceName: result.referenceName })\n\t\t\t.catch(() => {});\n\n\t\treturn toPullResponse(result);\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to pull reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Fetches a specific reference by name from the remote server\n * @param fullName - Repository full name (owner/repo)\n * @param referenceName - Specific reference name to pull\n * @returns Reference data or null if not found\n */\nexport async function pullReferenceByName(\n\tfullName: string,\n\treferenceName: string,\n): Promise<PullResponse | null> {\n\tconst client = await createClient();\n\tconst api = await getApi();\n\ttry {\n\t\tconst result = await client.query(api.references.pull, { fullName, referenceName });\n\t\tif (!result) return null;\n\n\t\tclient.mutation(api.references.recordPull, { fullName, referenceName }).catch(() => {});\n\n\t\treturn toPullResponse(result);\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to pull reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Pushes reference to the remote server\n * All validation happens server-side\n * @param reference - Reference data to push\n * @param token - Authentication token\n * @returns Push result\n */\nexport async function pushReference(\n\treference: ReferenceData,\n\ttoken: string,\n): Promise<PushResponse> {\n\tconst client = await createClient(token);\n\tconst api = await getApi();\n\ttry {\n\t\tconst result = await client.action(api.references.push, {\n\t\t\tfullName: reference.fullName,\n\t\t\treferenceName: reference.referenceName,\n\t\t\treferenceDescription: reference.referenceDescription,\n\t\t\treferenceContent: reference.referenceContent,\n\t\t\tcommitSha: reference.commitSha,\n\t\t\tgeneratedAt: reference.generatedAt,\n\t\t});\n\n\t\tif (!result.success) {\n\t\t\tswitch (result.error) {\n\t\t\t\tcase \"auth_required\":\n\t\t\t\t\tthrow new AuthenticationError();\n\t\t\t\tcase \"rate_limit\":\n\t\t\t\t\tthrow new RateLimitError(\"Rate limit exceeded. You can push up to 20 times per day.\");\n\t\t\t\tcase \"commit_already_exists\":\n\t\t\t\t\tthrow new CommitExistsError(result.message);\n\t\t\t\tcase \"invalid_input\":\n\t\t\t\t\tthrow new InvalidInputError(result.message ?? \"Invalid input\");\n\t\t\t\tcase \"invalid_reference\":\n\t\t\t\t\tthrow new InvalidReferenceError(result.message ?? \"Invalid reference content\");\n\t\t\t\tcase \"repo_not_found\":\n\t\t\t\t\tthrow new RepoNotFoundError(result.message);\n\t\t\t\tcase \"low_stars\":\n\t\t\t\t\tthrow new LowStarsError(result.message);\n\t\t\t\tcase \"private_repo\":\n\t\t\t\t\tthrow new PrivateRepoError(result.message);\n\t\t\t\tcase \"commit_not_found\":\n\t\t\t\t\tthrow new CommitNotFoundError(result.message);\n\t\t\t\tcase \"github_error\":\n\t\t\t\t\tthrow new GitHubError(result.message);\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new SyncError(result.message ?? \"Unknown error\");\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true };\n\t} catch (error) {\n\t\tif (error instanceof SyncError) throw error;\n\t\tthrow new NetworkError(\n\t\t\t`Failed to push reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Checks if reference exists on remote server (lightweight check)\n * @param fullName - Repository full name (owner/repo)\n * @returns Check result\n */\nexport async function checkRemote(fullName: string): Promise<CheckResponse> {\n\tconst client = await createClient();\n\tconst api = await getApi();\n\ttry {\n\t\tlet result = await client.query(api.references.check, {\n\t\t\tfullName,\n\t\t\treferenceName: toReferenceName(fullName),\n\t\t});\n\t\tif (!result.exists) {\n\t\t\tresult = await client.query(api.references.check, { fullName });\n\t\t}\n\t\tif (!result.exists) {\n\t\t\treturn { exists: false };\n\t\t}\n\t\treturn {\n\t\t\texists: true,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to check remote: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Checks if a specific reference exists on the remote server\n * @param fullName - Repository full name (owner/repo)\n * @param referenceName - Specific reference name to check\n * @returns Check result\n */\nexport async function checkRemoteByName(\n\tfullName: string,\n\treferenceName: string,\n): Promise<CheckResponse> {\n\tconst client = await createClient();\n\tconst api = await getApi();\n\ttry {\n\t\tconst result = await client.query(api.references.check, { fullName, referenceName });\n\t\tif (!result.exists) {\n\t\t\treturn { exists: false };\n\t\t}\n\t\treturn {\n\t\t\texists: true,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to check remote: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Compares local vs remote commit SHA to check staleness\n * @param fullName - Repository full name (owner/repo)\n * @param localCommitSha - Local commit SHA\n * @returns Staleness result\n */\nexport async function checkStaleness(\n\tfullName: string,\n\tlocalCommitSha: string,\n): Promise<StalenessResult> {\n\tconst remote = await checkRemote(fullName);\n\n\tif (!remote.exists || !remote.commitSha) {\n\t\treturn {\n\t\t\tisStale: false,\n\t\t\tlocalCommitSha,\n\t\t\tremoteCommitSha: undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\tisStale: localCommitSha !== remote.commitSha,\n\t\tlocalCommitSha,\n\t\tremoteCommitSha: remote.commitSha,\n\t};\n}\n\n/** GitHub repository metadata */\nexport interface GitHubRepoMetadata {\n\tstars: number;\n\tdescription?: string;\n\tlanguage?: string;\n\tdefaultBranch: string;\n}\n\n/**\n * Fetches GitHub repository metadata\n * @param owner - Repository owner\n * @param repo - Repository name\n * @returns Repository metadata or null on error\n */\nexport async function fetchGitHubMetadata(\n\towner: string,\n\trepo: string,\n): Promise<GitHubRepoMetadata | null> {\n\ttry {\n\t\tconst response = await fetch(`${GITHUB_API_BASE}/repos/${owner}/${repo}`, {\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/vnd.github.v3+json\",\n\t\t\t\t\"User-Agent\": \"offworld-cli\",\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst json = await response.json();\n\t\tconst result = GitHubRepoMetadataSchema.safeParse(json);\n\t\tif (!result.success) {\n\t\t\treturn null;\n\t\t}\n\t\tconst data = result.data;\n\n\t\treturn {\n\t\t\tstars: data.stargazers_count ?? 0,\n\t\t\tdescription: data.description ?? undefined,\n\t\t\tlanguage: data.language ?? undefined,\n\t\t\tdefaultBranch: data.default_branch ?? \"main\",\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Fetches GitHub repository stars\n * @param owner - Repository owner\n * @param repo - Repository name\n * @returns Number of stars, or 0 on error\n */\nexport async function fetchRepoStars(owner: string, repo: string): Promise<number> {\n\tconst metadata = await fetchGitHubMetadata(owner, repo);\n\treturn metadata?.stars ?? 0;\n}\n\n/**\n * Checks if a repository can be pushed to offworld.sh (client-side quick checks)\n * Note: Star count and other validations happen server-side\n *\n * @param source - Repository source\n * @returns Can push result\n */\nexport function canPushToWeb(source: RepoSource): CanPushResult {\n\tif (source.type === \"local\") {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason:\n\t\t\t\t\"Local repositories cannot be pushed to offworld.sh. \" +\n\t\t\t\t\"Only remote repositories with a public URL are supported.\",\n\t\t};\n\t}\n\n\tif (source.provider !== \"github\") {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason:\n\t\t\t\t`${source.provider} repositories are not yet supported. ` +\n\t\t\t\t\"GitHub support only for now - GitLab and Bitbucket coming soon!\",\n\t\t};\n\t}\n\n\treturn {\n\t\tallowed: true,\n\t};\n}\n\n/**\n * Validates that a source can be pushed and throws appropriate error if not\n * Note: This only does quick client-side checks. Full validation happens server-side.\n * @param source - Repository source\n * @throws PushNotAllowedError if push is not allowed\n */\nexport function validatePushAllowed(source: RepoSource): void {\n\tconst result = canPushToWeb(source);\n\n\tif (!result.allowed) {\n\t\tconst reason: \"local\" | \"not-github\" = source.type === \"local\" ? \"local\" : \"not-github\";\n\n\t\tthrow new PushNotAllowedError(result.reason!, reason);\n\t}\n}\n\nexport { SyncUnavailableError } from \"./sync/client.js\";\n"],"mappings":"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"}