@pierre/storage 0.0.2 → 0.0.5

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.
package/src/index.ts CHANGED
@@ -5,6 +5,23 @@
5
5
  */
6
6
 
7
7
  import { importPKCS8, SignJWT } from 'jose';
8
+ import type {
9
+ GetBranchDiffOptions,
10
+ GetBranchDiffResponse,
11
+ GetCommitDiffOptions,
12
+ GetCommitDiffResponse,
13
+ GetCommitOptions,
14
+ GetCommitResponse,
15
+ GetFileOptions,
16
+ GetFileResponse,
17
+ ListBranchesOptions,
18
+ ListBranchesResponse,
19
+ ListCommitsOptions,
20
+ ListCommitsResponse,
21
+ ListFilesOptions,
22
+ ListFilesResponse,
23
+ Repo,
24
+ } from './types';
8
25
 
9
26
  /**
10
27
  * Type definitions for Pierre Git Storage SDK
@@ -20,10 +37,7 @@ export interface GetRemoteURLOptions {
20
37
  ttl?: number;
21
38
  }
22
39
 
23
- export interface Repo {
24
- id: string;
25
- getRemoteURL(options?: GetRemoteURLOptions): Promise<string>;
26
- }
40
+ // Repo interface is now imported from types.ts
27
41
 
28
42
  export interface FindOneOptions {
29
43
  id: string;
@@ -38,6 +52,9 @@ export interface CreateRepoResponse {
38
52
  url: string;
39
53
  }
40
54
 
55
+ // Import additional types from types.ts
56
+ export * from './types';
57
+
41
58
  /**
42
59
  * Git Storage API
43
60
  */
@@ -47,6 +64,210 @@ declare const __STORAGE_BASE_URL__: string;
47
64
  const API_BASE_URL = __API_BASE_URL__;
48
65
  const STORAGE_BASE_URL = __STORAGE_BASE_URL__;
49
66
 
67
+ /**
68
+ * Implementation of the Repo interface
69
+ */
70
+ class RepoImpl implements Repo {
71
+ constructor(
72
+ public readonly id: string,
73
+ private readonly options: GitStorageOptions,
74
+ private readonly generateJWT: (
75
+ repoId: string,
76
+ options?: GetRemoteURLOptions,
77
+ ) => Promise<string>,
78
+ ) {}
79
+
80
+ async getRemoteURL(urlOptions?: GetRemoteURLOptions): Promise<string> {
81
+ const url = new URL(`https://${this.options.name}.${STORAGE_BASE_URL}/${this.id}.git`);
82
+ url.username = `t`;
83
+ url.password = await this.generateJWT(this.id, urlOptions);
84
+ return url.toString();
85
+ }
86
+
87
+ async getFile(options: GetFileOptions): Promise<GetFileResponse> {
88
+ const jwt = await this.generateJWT(this.id, {
89
+ permissions: ['git:read'],
90
+ ttl: 1 * 60 * 60, // 1hr in seconds
91
+ });
92
+
93
+ const url = new URL(`${API_BASE_URL}/api/v1/repos/file`);
94
+ url.searchParams.set('path', options.path);
95
+ if (options.ref) {
96
+ url.searchParams.set('ref', options.ref);
97
+ }
98
+
99
+ const response = await fetch(url.toString(), {
100
+ method: 'GET',
101
+ headers: {
102
+ Authorization: `Bearer ${jwt}`,
103
+ },
104
+ });
105
+
106
+ if (!response.ok) {
107
+ throw new Error(`Failed to get file: ${response.statusText}`);
108
+ }
109
+
110
+ return (await response.json()) as GetFileResponse;
111
+ }
112
+
113
+ async listFiles(options?: ListFilesOptions): Promise<ListFilesResponse> {
114
+ const jwt = await this.generateJWT(this.id, {
115
+ permissions: ['git:read'],
116
+ ttl: 1 * 60 * 60, // 1hr in seconds
117
+ });
118
+
119
+ const url = new URL(`${API_BASE_URL}/api/v1/repos/files`);
120
+ if (options?.ref) {
121
+ url.searchParams.set('ref', options.ref);
122
+ }
123
+
124
+ const response = await fetch(url.toString(), {
125
+ method: 'GET',
126
+ headers: {
127
+ Authorization: `Bearer ${jwt}`,
128
+ },
129
+ });
130
+
131
+ if (!response.ok) {
132
+ throw new Error(`Failed to list files: ${response.statusText}`);
133
+ }
134
+
135
+ return (await response.json()) as ListFilesResponse;
136
+ }
137
+
138
+ async listBranches(options?: ListBranchesOptions): Promise<ListBranchesResponse> {
139
+ const jwt = await this.generateJWT(this.id, {
140
+ permissions: ['git:read'],
141
+ ttl: 1 * 60 * 60, // 1hr in seconds
142
+ });
143
+
144
+ const url = new URL(`${API_BASE_URL}/api/v1/repos/branches`);
145
+ if (options?.cursor) {
146
+ url.searchParams.set('cursor', options.cursor);
147
+ }
148
+ if (options?.limit) {
149
+ url.searchParams.set('limit', options.limit.toString());
150
+ }
151
+
152
+ const response = await fetch(url.toString(), {
153
+ method: 'GET',
154
+ headers: {
155
+ Authorization: `Bearer ${jwt}`,
156
+ },
157
+ });
158
+
159
+ if (!response.ok) {
160
+ throw new Error(`Failed to list branches: ${response.statusText}`);
161
+ }
162
+
163
+ return (await response.json()) as ListBranchesResponse;
164
+ }
165
+
166
+ async listCommits(options?: ListCommitsOptions): Promise<ListCommitsResponse> {
167
+ const jwt = await this.generateJWT(this.id, {
168
+ permissions: ['git:read'],
169
+ ttl: 1 * 60 * 60, // 1hr in seconds
170
+ });
171
+
172
+ const url = new URL(`${API_BASE_URL}/api/v1/repos/commits`);
173
+ if (options?.branch) {
174
+ url.searchParams.set('branch', options.branch);
175
+ }
176
+ if (options?.cursor) {
177
+ url.searchParams.set('cursor', options.cursor);
178
+ }
179
+ if (options?.limit) {
180
+ url.searchParams.set('limit', options.limit.toString());
181
+ }
182
+
183
+ const response = await fetch(url.toString(), {
184
+ method: 'GET',
185
+ headers: {
186
+ Authorization: `Bearer ${jwt}`,
187
+ },
188
+ });
189
+
190
+ if (!response.ok) {
191
+ throw new Error(`Failed to list commits: ${response.statusText}`);
192
+ }
193
+
194
+ return (await response.json()) as ListCommitsResponse;
195
+ }
196
+
197
+ async getBranchDiff(options: GetBranchDiffOptions): Promise<GetBranchDiffResponse> {
198
+ const jwt = await this.generateJWT(this.id, {
199
+ permissions: ['git:read'],
200
+ ttl: 1 * 60 * 60, // 1hr in seconds
201
+ });
202
+
203
+ const url = new URL(`${API_BASE_URL}/api/v1/repos/branches/diff`);
204
+ url.searchParams.set('branch', options.branch);
205
+ if (options.base) {
206
+ url.searchParams.set('base', options.base);
207
+ }
208
+
209
+ const response = await fetch(url.toString(), {
210
+ method: 'GET',
211
+ headers: {
212
+ Authorization: `Bearer ${jwt}`,
213
+ },
214
+ });
215
+
216
+ if (!response.ok) {
217
+ throw new Error(`Failed to get branch diff: ${response.statusText}`);
218
+ }
219
+
220
+ return (await response.json()) as GetBranchDiffResponse;
221
+ }
222
+
223
+ async getCommitDiff(options: GetCommitDiffOptions): Promise<GetCommitDiffResponse> {
224
+ const jwt = await this.generateJWT(this.id, {
225
+ permissions: ['git:read'],
226
+ ttl: 1 * 60 * 60, // 1hr in seconds
227
+ });
228
+
229
+ const url = new URL(`${API_BASE_URL}/api/v1/repos/diff`);
230
+ url.searchParams.set('sha', options.sha);
231
+
232
+ const response = await fetch(url.toString(), {
233
+ method: 'GET',
234
+ headers: {
235
+ Authorization: `Bearer ${jwt}`,
236
+ },
237
+ });
238
+
239
+ if (!response.ok) {
240
+ throw new Error(`Failed to get commit diff: ${response.statusText}`);
241
+ }
242
+
243
+ return (await response.json()) as GetCommitDiffResponse;
244
+ }
245
+
246
+ async getCommit(options: GetCommitOptions): Promise<GetCommitResponse> {
247
+ const jwt = await this.generateJWT(this.id, {
248
+ permissions: ['git:read'],
249
+ ttl: 1 * 60 * 60, // 1hr in seconds
250
+ });
251
+
252
+ const url = new URL(`${API_BASE_URL}/commit`);
253
+ url.searchParams.set('repo', this.id);
254
+ url.searchParams.set('sha', options.sha);
255
+
256
+ const response = await fetch(url.toString(), {
257
+ method: 'GET',
258
+ headers: {
259
+ Authorization: `Bearer ${jwt}`,
260
+ },
261
+ });
262
+
263
+ if (!response.ok) {
264
+ throw new Error(`Failed to get commit: ${response.statusText}`);
265
+ }
266
+
267
+ return (await response.json()) as GetCommitResponse;
268
+ }
269
+ }
270
+
50
271
  export class GitStorage {
51
272
  private options: GitStorageOptions;
52
273
 
@@ -100,15 +321,7 @@ export class GitStorage {
100
321
  throw new Error(`Failed to create repository: ${response.statusText}`);
101
322
  }
102
323
 
103
- return {
104
- id: repoId,
105
- getRemoteURL: async (urlOptions?: GetRemoteURLOptions): Promise<string> => {
106
- const url = new URL(`https://${this.options.name}.${STORAGE_BASE_URL}/${repoId}.git`);
107
- url.username = `t`;
108
- url.password = await this.generateJWT(repoId, urlOptions);
109
- return url.toString();
110
- },
111
- };
324
+ return new RepoImpl(repoId, this.options, this.generateJWT.bind(this));
112
325
  }
113
326
 
114
327
  /**
@@ -117,15 +330,7 @@ export class GitStorage {
117
330
  * @returns The found repository
118
331
  */
119
332
  async findOne(options: FindOneOptions): Promise<Repo | null> {
120
- return {
121
- id: options.id,
122
- getRemoteURL: async (urlOptions?: GetRemoteURLOptions): Promise<string> => {
123
- const url = new URL(`https://${this.options.name}.${STORAGE_BASE_URL}/${options.id}.git`);
124
- url.username = `t`;
125
- url.password = await this.generateJWT(options.id, urlOptions);
126
- return url.toString();
127
- },
128
- };
333
+ return new RepoImpl(options.id, this.options, this.generateJWT.bind(this));
129
334
  }
130
335
 
131
336
  /**
@@ -148,7 +353,6 @@ export class GitStorage {
148
353
  // Create the JWT payload
149
354
  const now = Math.floor(Date.now() / 1000);
150
355
  const payload = {
151
- aud: 'git.pierre.co', // todo this should be updated to git.storage
152
356
  iss: this.options.name,
153
357
  sub: '@pierre/storage',
154
358
  repo: repoId,
package/src/types.ts CHANGED
@@ -15,6 +15,13 @@ export interface GetRemoteURLOptions {
15
15
  export interface Repo {
16
16
  id: string;
17
17
  getRemoteURL(options?: GetRemoteURLOptions): Promise<string>;
18
+ getFile(options: GetFileOptions): Promise<GetFileResponse>;
19
+ listFiles(options?: ListFilesOptions): Promise<ListFilesResponse>;
20
+ listBranches(options?: ListBranchesOptions): Promise<ListBranchesResponse>;
21
+ listCommits(options?: ListCommitsOptions): Promise<ListCommitsResponse>;
22
+ getBranchDiff(options: GetBranchDiffOptions): Promise<GetBranchDiffResponse>;
23
+ getCommitDiff(options: GetCommitDiffOptions): Promise<GetCommitDiffResponse>;
24
+ getCommit(options: GetCommitOptions): Promise<GetCommitResponse>;
18
25
  }
19
26
 
20
27
  export interface FindOneOptions {
@@ -29,3 +36,144 @@ export interface CreateRepoResponse {
29
36
  repo_id: string;
30
37
  url: string;
31
38
  }
39
+
40
+ // Get File API types
41
+ export interface GetFileOptions {
42
+ path: string;
43
+ ref?: string;
44
+ }
45
+
46
+ export interface GetFileResponse {
47
+ path: string;
48
+ ref: string;
49
+ content: string;
50
+ size: number;
51
+ is_binary: boolean;
52
+ }
53
+
54
+ // List Files API types
55
+ export interface ListFilesOptions {
56
+ ref?: string;
57
+ }
58
+
59
+ export interface ListFilesResponse {
60
+ paths: string[];
61
+ ref: string;
62
+ }
63
+
64
+ // List Branches API types
65
+ export interface ListBranchesOptions {
66
+ cursor?: string;
67
+ limit?: number;
68
+ }
69
+
70
+ export interface BranchInfo {
71
+ cursor: string;
72
+ name: string;
73
+ head_sha: string;
74
+ created_at: string;
75
+ }
76
+
77
+ export interface ListBranchesResponse {
78
+ branches: BranchInfo[];
79
+ next_cursor?: string;
80
+ has_more: boolean;
81
+ }
82
+
83
+ // List Commits API types
84
+ export interface ListCommitsOptions {
85
+ branch?: string;
86
+ cursor?: string;
87
+ limit?: number;
88
+ }
89
+
90
+ export interface CommitInfo {
91
+ sha: string;
92
+ message: string;
93
+ author_name: string;
94
+ author_email: string;
95
+ committer_name: string;
96
+ committer_email: string;
97
+ date: string;
98
+ }
99
+
100
+ export interface ListCommitsResponse {
101
+ commits: CommitInfo[];
102
+ next_cursor?: string;
103
+ has_more: boolean;
104
+ }
105
+
106
+ // Branch Diff API types
107
+ export interface GetBranchDiffOptions {
108
+ branch: string;
109
+ base?: string;
110
+ }
111
+
112
+ export interface GetBranchDiffResponse {
113
+ branch: string;
114
+ base: string;
115
+ stats: DiffStats;
116
+ files: FileDiff[];
117
+ filtered_files: FilteredFile[];
118
+ }
119
+
120
+ // Commit Diff API types
121
+ export interface GetCommitDiffOptions {
122
+ sha: string;
123
+ }
124
+
125
+ export interface GetCommitDiffResponse {
126
+ sha: string;
127
+ stats: DiffStats;
128
+ files: FileDiff[];
129
+ filtered_files: FilteredFile[];
130
+ }
131
+
132
+ // Shared diff types
133
+ export interface DiffStats {
134
+ files: number;
135
+ additions: number;
136
+ deletions: number;
137
+ changes: number;
138
+ }
139
+
140
+ export interface FileDiff {
141
+ path: string;
142
+ state: string;
143
+ old_path?: string;
144
+ bytes: number;
145
+ is_eof: boolean;
146
+ diff: string;
147
+ }
148
+
149
+ export interface FilteredFile {
150
+ path: string;
151
+ state: string;
152
+ old_path?: string;
153
+ bytes: number;
154
+ is_eof: boolean;
155
+ }
156
+
157
+ // Get Commit API types
158
+ export interface GetCommitOptions {
159
+ sha: string;
160
+ }
161
+
162
+ export interface GetCommitResponse {
163
+ sha: string;
164
+ message: string;
165
+ author: {
166
+ name: string;
167
+ email: string;
168
+ };
169
+ committer: {
170
+ name: string;
171
+ email: string;
172
+ };
173
+ date: string;
174
+ stats: {
175
+ additions: number;
176
+ deletions: number;
177
+ total: number;
178
+ };
179
+ }