@pierre/storage 0.0.10 → 0.0.11

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/dist/index.js CHANGED
@@ -3,6 +3,352 @@ import snakecaseKeys from 'snakecase-keys';
3
3
 
4
4
  // src/index.ts
5
5
 
6
+ // src/commit.ts
7
+ var MAX_CHUNK_BYTES = 4 * 1024 * 1024;
8
+ var DEFAULT_TTL_SECONDS = 60 * 60;
9
+ var BufferCtor = globalThis.Buffer;
10
+ var CommitBuilderImpl = class {
11
+ options;
12
+ getAuthToken;
13
+ transport;
14
+ operations = [];
15
+ sent = false;
16
+ constructor(deps) {
17
+ this.options = { ...deps.options };
18
+ this.getAuthToken = deps.getAuthToken;
19
+ this.transport = deps.transport;
20
+ const trimmedTarget = this.options.targetRef?.trim();
21
+ const trimmedMessage = this.options.commitMessage?.trim();
22
+ if (!trimmedTarget) {
23
+ throw new Error("createCommit targetRef is required");
24
+ }
25
+ if (!trimmedMessage) {
26
+ throw new Error("createCommit commitMessage is required");
27
+ }
28
+ this.options.targetRef = trimmedTarget;
29
+ this.options.commitMessage = trimmedMessage;
30
+ if (typeof this.options.baseRef === "string") {
31
+ this.options.baseRef = this.options.baseRef.trim();
32
+ }
33
+ }
34
+ addFile(path, source, options) {
35
+ this.ensureNotSent();
36
+ const normalizedPath = this.normalizePath(path);
37
+ const contentId = randomContentId();
38
+ const mode = options?.mode ?? "100644";
39
+ this.operations.push({
40
+ path: normalizedPath,
41
+ contentId,
42
+ mode,
43
+ operation: "upsert",
44
+ streamFactory: () => toAsyncIterable(source)
45
+ });
46
+ return this;
47
+ }
48
+ addFileFromString(path, contents, options) {
49
+ const encoding = options?.encoding;
50
+ if (encoding && encoding !== "utf8" && encoding !== "utf-8") {
51
+ throw new Error(`Unsupported encoding "${encoding}". Only UTF-8 is supported.`);
52
+ }
53
+ const data = new TextEncoder().encode(contents);
54
+ return this.addFile(path, data, options);
55
+ }
56
+ deletePath(path) {
57
+ this.ensureNotSent();
58
+ const normalizedPath = this.normalizePath(path);
59
+ this.operations.push({
60
+ path: normalizedPath,
61
+ contentId: randomContentId(),
62
+ operation: "delete"
63
+ });
64
+ return this;
65
+ }
66
+ async send() {
67
+ this.ensureNotSent();
68
+ this.sent = true;
69
+ const metadata = this.buildMetadata();
70
+ const blobEntries = this.operations.filter((op) => op.operation === "upsert" && op.streamFactory).map((op) => ({
71
+ contentId: op.contentId,
72
+ chunks: chunkify(op.streamFactory())
73
+ }));
74
+ const authorization = await this.getAuthToken();
75
+ return this.transport.send({
76
+ authorization,
77
+ signal: this.options.signal,
78
+ metadata,
79
+ blobs: blobEntries
80
+ });
81
+ }
82
+ buildMetadata() {
83
+ const files = this.operations.map((op) => {
84
+ const entry = {
85
+ path: op.path,
86
+ content_id: op.contentId,
87
+ operation: op.operation
88
+ };
89
+ if (op.mode) {
90
+ entry.mode = op.mode;
91
+ }
92
+ return entry;
93
+ });
94
+ const metadata = {
95
+ target_ref: this.options.targetRef,
96
+ commit_message: this.options.commitMessage,
97
+ files
98
+ };
99
+ if (this.options.baseRef) {
100
+ metadata.base_ref = this.options.baseRef;
101
+ }
102
+ if (this.options.author) {
103
+ metadata.author = { ...this.options.author };
104
+ }
105
+ if (this.options.committer) {
106
+ metadata.committer = { ...this.options.committer };
107
+ }
108
+ return metadata;
109
+ }
110
+ ensureNotSent() {
111
+ if (this.sent) {
112
+ throw new Error("createCommit builder cannot be reused after send()");
113
+ }
114
+ }
115
+ normalizePath(path) {
116
+ if (!path || typeof path !== "string" || path.trim() === "") {
117
+ throw new Error("File path must be a non-empty string");
118
+ }
119
+ return path.replace(/^\//, "");
120
+ }
121
+ };
122
+ var FetchCommitTransport = class {
123
+ url;
124
+ constructor(config) {
125
+ const trimmedBase = config.baseUrl.replace(/\/+$/, "");
126
+ this.url = `${trimmedBase}/api/v${config.version}/repos/commit-pack`;
127
+ }
128
+ async send(request) {
129
+ const bodyIterable = buildMessageIterable(request.metadata, request.blobs);
130
+ const body = toRequestBody(bodyIterable);
131
+ const response = await fetch(this.url, {
132
+ method: "POST",
133
+ headers: {
134
+ Authorization: `Bearer ${request.authorization}`,
135
+ "Content-Type": "application/x-ndjson",
136
+ Accept: "application/json"
137
+ },
138
+ body,
139
+ signal: request.signal
140
+ });
141
+ if (!response.ok) {
142
+ const text = await response.text();
143
+ throw new Error(`createCommit request failed (${response.status}): ${text}`);
144
+ }
145
+ return await response.json();
146
+ }
147
+ };
148
+ function toRequestBody(iterable) {
149
+ const readableStreamCtor = globalThis.ReadableStream;
150
+ if (typeof readableStreamCtor === "function") {
151
+ const iterator = iterable[Symbol.asyncIterator]();
152
+ return new readableStreamCtor({
153
+ async pull(controller) {
154
+ const { value, done } = await iterator.next();
155
+ if (done) {
156
+ controller.close();
157
+ return;
158
+ }
159
+ controller.enqueue(value);
160
+ },
161
+ async cancel(reason) {
162
+ if (typeof iterator.return === "function") {
163
+ await iterator.return(reason);
164
+ }
165
+ }
166
+ });
167
+ }
168
+ return iterable;
169
+ }
170
+ function buildMessageIterable(metadata, blobs) {
171
+ const encoder = new TextEncoder();
172
+ return {
173
+ async *[Symbol.asyncIterator]() {
174
+ yield encoder.encode(`${JSON.stringify({ metadata })}
175
+ `);
176
+ for (const blob of blobs) {
177
+ for await (const segment of blob.chunks) {
178
+ const payload = {
179
+ blob_chunk: {
180
+ content_id: blob.contentId,
181
+ data: base64Encode(segment.chunk),
182
+ eof: segment.eof
183
+ }
184
+ };
185
+ yield encoder.encode(`${JSON.stringify(payload)}
186
+ `);
187
+ }
188
+ }
189
+ }
190
+ };
191
+ }
192
+ async function* chunkify(source) {
193
+ let pending = null;
194
+ let produced = false;
195
+ for await (const value of source) {
196
+ const bytes = value;
197
+ if (pending && pending.byteLength === MAX_CHUNK_BYTES) {
198
+ yield { chunk: pending, eof: false };
199
+ produced = true;
200
+ pending = null;
201
+ }
202
+ const merged = pending ? concatChunks(pending, bytes) : bytes;
203
+ pending = null;
204
+ let cursor = merged;
205
+ while (cursor.byteLength > MAX_CHUNK_BYTES) {
206
+ const chunk = cursor.slice(0, MAX_CHUNK_BYTES);
207
+ cursor = cursor.slice(MAX_CHUNK_BYTES);
208
+ yield { chunk, eof: false };
209
+ produced = true;
210
+ }
211
+ pending = cursor;
212
+ }
213
+ if (pending) {
214
+ yield { chunk: pending, eof: true };
215
+ produced = true;
216
+ }
217
+ if (!produced) {
218
+ yield { chunk: new Uint8Array(0), eof: true };
219
+ }
220
+ }
221
+ async function* toAsyncIterable(source) {
222
+ if (typeof source === "string") {
223
+ yield new TextEncoder().encode(source);
224
+ return;
225
+ }
226
+ if (source instanceof Uint8Array) {
227
+ yield source;
228
+ return;
229
+ }
230
+ if (source instanceof ArrayBuffer) {
231
+ yield new Uint8Array(source);
232
+ return;
233
+ }
234
+ if (ArrayBuffer.isView(source)) {
235
+ yield new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
236
+ return;
237
+ }
238
+ if (isBlobLike(source)) {
239
+ const stream = source.stream();
240
+ if (isAsyncIterable(stream)) {
241
+ for await (const chunk of stream) {
242
+ yield ensureUint8Array(chunk);
243
+ }
244
+ return;
245
+ }
246
+ if (isReadableStreamLike(stream)) {
247
+ yield* readReadableStream(stream);
248
+ return;
249
+ }
250
+ }
251
+ if (isAsyncIterable(source)) {
252
+ for await (const chunk of source) {
253
+ yield ensureUint8Array(chunk);
254
+ }
255
+ return;
256
+ }
257
+ if (isIterable(source)) {
258
+ for (const chunk of source) {
259
+ yield ensureUint8Array(chunk);
260
+ }
261
+ return;
262
+ }
263
+ throw new Error("Unsupported file source for createCommit");
264
+ }
265
+ async function* readReadableStream(stream) {
266
+ const reader = stream.getReader();
267
+ try {
268
+ while (true) {
269
+ const { value, done } = await reader.read();
270
+ if (done) {
271
+ break;
272
+ }
273
+ if (value !== void 0) {
274
+ yield ensureUint8Array(value);
275
+ }
276
+ }
277
+ } finally {
278
+ reader.releaseLock?.();
279
+ }
280
+ }
281
+ function ensureUint8Array(value) {
282
+ if (value instanceof Uint8Array) {
283
+ return value;
284
+ }
285
+ if (value instanceof ArrayBuffer) {
286
+ return new Uint8Array(value);
287
+ }
288
+ if (ArrayBuffer.isView(value)) {
289
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
290
+ }
291
+ if (typeof value === "string") {
292
+ return new TextEncoder().encode(value);
293
+ }
294
+ if (BufferCtor && BufferCtor.isBuffer(value)) {
295
+ return value;
296
+ }
297
+ throw new Error("Unsupported chunk type; expected binary data");
298
+ }
299
+ function isBlobLike(value) {
300
+ return typeof value === "object" && value !== null && typeof value.stream === "function";
301
+ }
302
+ function isReadableStreamLike(value) {
303
+ return typeof value === "object" && value !== null && typeof value.getReader === "function";
304
+ }
305
+ function isAsyncIterable(value) {
306
+ return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
307
+ }
308
+ function isIterable(value) {
309
+ return typeof value === "object" && value !== null && Symbol.iterator in value;
310
+ }
311
+ function concatChunks(a, b) {
312
+ if (a.byteLength === 0) {
313
+ return b;
314
+ }
315
+ if (b.byteLength === 0) {
316
+ return a;
317
+ }
318
+ const merged = new Uint8Array(a.byteLength + b.byteLength);
319
+ merged.set(a, 0);
320
+ merged.set(b, a.byteLength);
321
+ return merged;
322
+ }
323
+ function base64Encode(bytes) {
324
+ if (BufferCtor) {
325
+ return BufferCtor.from(bytes).toString("base64");
326
+ }
327
+ let binary = "";
328
+ for (let i = 0; i < bytes.byteLength; i++) {
329
+ binary += String.fromCharCode(bytes[i]);
330
+ }
331
+ const btoaFn = globalThis.btoa;
332
+ if (typeof btoaFn === "function") {
333
+ return btoaFn(binary);
334
+ }
335
+ throw new Error("Base64 encoding is not supported in this environment");
336
+ }
337
+ function randomContentId() {
338
+ const cryptoObj = globalThis.crypto;
339
+ if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
340
+ return cryptoObj.randomUUID();
341
+ }
342
+ const random = Math.random().toString(36).slice(2);
343
+ return `cid-${Date.now().toString(36)}-${random}`;
344
+ }
345
+ function createCommitBuilder(deps) {
346
+ return new CommitBuilderImpl(deps);
347
+ }
348
+ function resolveCommitTtlSeconds(options) {
349
+ return typeof options?.ttl === "number" && options.ttl > 0 ? options.ttl : DEFAULT_TTL_SECONDS;
350
+ }
351
+
6
352
  // src/fetch.ts
7
353
  var ApiFetcher = class {
8
354
  constructor(API_BASE_URL2, version) {
@@ -232,8 +578,8 @@ async function validateWebhook(payload, headers, secret, options = {}) {
232
578
  }
233
579
 
234
580
  // src/index.ts
235
- var API_BASE_URL = "https://api.git.storage";
236
- var STORAGE_BASE_URL = "git.storage";
581
+ var API_BASE_URL = "https://api.code.storage";
582
+ var STORAGE_BASE_URL = "code.storage";
237
583
  var API_VERSION = 1;
238
584
  var apiInstanceMap = /* @__PURE__ */ new Map();
239
585
  function getApiInstance(baseUrl, version) {
@@ -381,6 +727,22 @@ var RepoImpl = class {
381
727
  }
382
728
  return;
383
729
  }
730
+ createCommit(options) {
731
+ const version = this.options.apiVersion ?? API_VERSION;
732
+ const baseUrl = this.options.apiBaseUrl ?? API_BASE_URL;
733
+ const transport = new FetchCommitTransport({ baseUrl, version });
734
+ const ttlSeconds = resolveCommitTtlSeconds(options);
735
+ const builderOptions = { ...options, ttl: ttlSeconds };
736
+ const getAuthToken = () => this.generateJWT(this.id, {
737
+ permissions: ["git:write"],
738
+ ttl: ttlSeconds
739
+ });
740
+ return createCommitBuilder({
741
+ options: builderOptions,
742
+ getAuthToken,
743
+ transport
744
+ });
745
+ }
384
746
  };
385
747
  var GitStorage = class _GitStorage {
386
748
  static overrides = {};
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fetch.ts","../src/util.ts","../src/webhook.ts","../src/index.ts"],"names":["API_BASE_URL","crypto"],"mappings":"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","file":"index.js","sourcesContent":["import type { ValidAPIVersion, ValidMethod, ValidPath } from './types';\n\ninterface RequestOptions {\n\tallowedStatus?: number[];\n}\n\nexport class ApiFetcher {\n\tconstructor(\n\t\tprivate readonly API_BASE_URL: string,\n\t\tprivate readonly version: ValidAPIVersion,\n\t) {\n\t\tconsole.log('api fetcher created', API_BASE_URL, version);\n\t}\n\n\tprivate getBaseUrl() {\n\t\treturn `${this.API_BASE_URL}/api/v${this.version}`;\n\t}\n\n\tprivate getRequestUrl(path: ValidPath) {\n\t\tif (typeof path === 'string') {\n\t\t\treturn `${this.getBaseUrl()}/${path}`;\n\t\t} else if (path.params) {\n\t\t\tconst paramStr = new URLSearchParams(path.params).toString();\n\t\t\treturn `${this.getBaseUrl()}/${path.path}${paramStr ? `?${paramStr}` : ''}`;\n\t\t} else {\n\t\t\treturn `${this.getBaseUrl()}/${path.path}`;\n\t\t}\n\t}\n\n\tprivate async fetch(path: ValidPath, method: ValidMethod, jwt: string, options?: RequestOptions) {\n\t\tconst requestUrl = this.getRequestUrl(path);\n\n\t\tconst requestOptions: RequestInit = {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${jwt}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t};\n\n\t\tif (method !== 'GET' && typeof path !== 'string' && path.body) {\n\t\t\trequestOptions.body = JSON.stringify(path.body);\n\t\t}\n\n\t\tconst response = await fetch(requestUrl, requestOptions);\n\n\t\tif (!response.ok) {\n\t\t\tconst allowed = options?.allowedStatus ?? [];\n\t\t\tif (!allowed.includes(response.status)) {\n\t\t\t\tthrow new Error(`Failed to fetch ${method} ${requestUrl}: ${response.statusText}`);\n\t\t\t}\n\t\t}\n\t\treturn response;\n\t}\n\n\tasync get(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'GET', jwt, options);\n\t}\n\n\tasync post(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'POST', jwt, options);\n\t}\n\n\tasync put(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'PUT', jwt, options);\n\t}\n\n\tasync delete(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'DELETE', jwt, options);\n\t}\n}\n","export function timingSafeEqual(a: string | Uint8Array, b: string | Uint8Array): boolean {\n\tconst bufferA = typeof a === 'string' ? new TextEncoder().encode(a) : a;\n\tconst bufferB = typeof b === 'string' ? new TextEncoder().encode(b) : b;\n\n\tif (bufferA.length !== bufferB.length) return false;\n\n\tlet result = 0;\n\tfor (let i = 0; i < bufferA.length; i++) {\n\t\tresult |= bufferA[i] ^ bufferB[i];\n\t}\n\treturn result === 0;\n}\n\nexport async function getEnvironmentCrypto() {\n\tif (!globalThis.crypto) {\n\t\tconst { webcrypto } = await import('node:crypto');\n\t\treturn webcrypto;\n\t}\n\treturn globalThis.crypto;\n}\n\nexport async function createHmac(algorithm: string, secret: string, data: string): Promise<string> {\n\tif (algorithm !== 'sha256') {\n\t\tthrow new Error('Only sha256 algorithm is supported');\n\t}\n\tif (!secret || secret.length === 0) {\n\t\tthrow new Error('Secret is required');\n\t}\n\n\tconst crypto = await getEnvironmentCrypto();\n\tconst encoder = new TextEncoder();\n\tconst key = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tencoder.encode(secret),\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign'],\n\t);\n\n\tconst signature = await crypto.subtle.sign('HMAC', key, encoder.encode(data));\n\treturn Array.from(new Uint8Array(signature))\n\t\t.map((b) => b.toString(16).padStart(2, '0'))\n\t\t.join('');\n}\n\n// Keep the legacy async function for backward compatibility\nexport async function createHmacAsync(secret: string, data: string): Promise<string> {\n\tconst crypto = await getEnvironmentCrypto();\n\tconst encoder = new TextEncoder();\n\tconst key = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tencoder.encode(secret),\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign'],\n\t);\n\n\tconst signature = await crypto.subtle.sign('HMAC', key, encoder.encode(data));\n\treturn Array.from(new Uint8Array(signature))\n\t\t.map((b) => b.toString(16).padStart(2, '0'))\n\t\t.join('');\n}\n","/**\n * Webhook validation utilities for Pierre Git Storage\n */\n\nimport type {\n\tParsedWebhookSignature,\n\tWebhookEventPayload,\n\tWebhookValidationOptions,\n\tWebhookValidationResult,\n} from './types';\n\nimport { createHmac, timingSafeEqual } from './util';\n\nconst DEFAULT_MAX_AGE_SECONDS = 300; // 5 minutes\n\n/**\n * Parse the X-Pierre-Signature header\n * Format: t=<timestamp>,sha256=<signature>\n */\nexport function parseSignatureHeader(header: string): ParsedWebhookSignature | null {\n\tif (!header || typeof header !== 'string') {\n\t\treturn null;\n\t}\n\n\tlet timestamp = '';\n\tlet signature = '';\n\n\t// Split by comma and parse each element\n\tconst elements = header.split(',');\n\tfor (const element of elements) {\n\t\tconst trimmedElement = element.trim();\n\t\tconst parts = trimmedElement.split('=', 2);\n\t\tif (parts.length !== 2) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst [key, value] = parts;\n\t\tswitch (key) {\n\t\t\tcase 't':\n\t\t\t\ttimestamp = value;\n\t\t\t\tbreak;\n\t\t\tcase 'sha256':\n\t\t\t\tsignature = value;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!timestamp || !signature) {\n\t\treturn null;\n\t}\n\n\treturn { timestamp, signature };\n}\n\n/**\n * Validate a webhook signature and timestamp\n *\n * @param payload - The raw webhook payload (request body)\n * @param signatureHeader - The X-Pierre-Signature header value\n * @param secret - The webhook secret for HMAC verification\n * @param options - Validation options\n * @returns Validation result with details\n *\n * @example\n * ```typescript\n * const result = await validateWebhookSignature(\n * requestBody,\n * request.headers['x-pierre-signature'],\n * webhookSecret\n * );\n *\n * if (!result.valid) {\n * console.error('Invalid webhook:', result.error);\n * return;\n * }\n * ```\n */\nexport async function validateWebhookSignature(\n\tpayload: string | Buffer,\n\tsignatureHeader: string,\n\tsecret: string,\n\toptions: WebhookValidationOptions = {},\n): Promise<WebhookValidationResult> {\n\tif (!secret || secret.length === 0) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Empty secret is not allowed',\n\t\t};\n\t}\n\n\t// Parse the signature header\n\tconst parsed = parseSignatureHeader(signatureHeader);\n\tif (!parsed) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid signature header format',\n\t\t};\n\t}\n\n\t// Parse timestamp\n\tconst timestamp = Number.parseInt(parsed.timestamp, 10);\n\tif (isNaN(timestamp)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid timestamp in signature',\n\t\t};\n\t}\n\n\t// Validate timestamp age (prevent replay attacks)\n\tconst maxAge = options.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS;\n\tif (maxAge > 0) {\n\t\tconst now = Math.floor(Date.now() / 1000);\n\t\tconst age = now - timestamp;\n\n\t\tif (age > maxAge) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\terror: `Webhook timestamp too old (${age} seconds)`,\n\t\t\t\ttimestamp,\n\t\t\t};\n\t\t}\n\n\t\t// Also reject timestamps from the future (clock skew tolerance of 60 seconds)\n\t\tif (age < -60) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\terror: 'Webhook timestamp is in the future',\n\t\t\t\ttimestamp,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Convert payload to string if it's a Buffer\n\tconst payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n\n\t// Compute expected signature\n\t// Format: HMAC-SHA256(secret, timestamp + \".\" + payload)\n\tconst signedData = `${parsed.timestamp}.${payloadStr}`;\n\tconst expectedSignature = await createHmac('sha256', secret, signedData);\n\n\t// Compare signatures using constant-time comparison\n\tconst expectedBuffer = Buffer.from(expectedSignature);\n\tconst actualBuffer = Buffer.from(parsed.signature);\n\n\t// Ensure both buffers are the same length for timing-safe comparison\n\tif (expectedBuffer.length !== actualBuffer.length) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid signature',\n\t\t\ttimestamp,\n\t\t};\n\t}\n\n\tconst signaturesMatch = timingSafeEqual(expectedBuffer, actualBuffer);\n\tif (!signaturesMatch) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid signature',\n\t\t\ttimestamp,\n\t\t};\n\t}\n\n\treturn {\n\t\tvalid: true,\n\t\ttimestamp,\n\t};\n}\n\n/**\n * Validate a webhook request\n *\n * This is a convenience function that validates the signature and parses the payload.\n *\n * @param payload - The raw webhook payload (request body)\n * @param headers - The request headers (must include x-pierre-signature and x-pierre-event)\n * @param secret - The webhook secret for HMAC verification\n * @param options - Validation options\n * @returns The parsed webhook payload if valid, or validation error\n *\n * @example\n * ```typescript\n * const result = await validateWebhook(\n * request.body,\n * request.headers,\n * process.env.WEBHOOK_SECRET\n * );\n *\n * if (!result.valid) {\n * return new Response('Invalid webhook', { status: 401 });\n * }\n *\n * // Type-safe access to the webhook payload\n * console.log('Push event:', result.payload);\n * ```\n */\nexport async function validateWebhook(\n\tpayload: string | Buffer,\n\theaders: Record<string, string | string[] | undefined>,\n\tsecret: string,\n\toptions: WebhookValidationOptions = {},\n): Promise<WebhookValidationResult & { payload?: WebhookEventPayload }> {\n\t// Get signature header\n\tconst signatureHeader = headers['x-pierre-signature'] || headers['X-Pierre-Signature'];\n\tif (!signatureHeader || Array.isArray(signatureHeader)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Missing or invalid X-Pierre-Signature header',\n\t\t};\n\t}\n\n\t// Get event type header\n\tconst eventType = headers['x-pierre-event'] || headers['X-Pierre-Event'];\n\tif (!eventType || Array.isArray(eventType)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Missing or invalid X-Pierre-Event header',\n\t\t};\n\t}\n\n\t// Validate signature\n\tconst validationResult = await validateWebhookSignature(\n\t\tpayload,\n\t\tsignatureHeader,\n\t\tsecret,\n\t\toptions,\n\t);\n\n\tif (!validationResult.valid) {\n\t\treturn validationResult;\n\t}\n\n\t// Parse payload\n\tconst payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n\tlet parsedPayload: WebhookEventPayload;\n\ttry {\n\t\tparsedPayload = JSON.parse(payloadStr);\n\t} catch {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid JSON payload',\n\t\t\ttimestamp: validationResult.timestamp,\n\t\t};\n\t}\n\n\treturn {\n\t\tvalid: true,\n\t\teventType,\n\t\ttimestamp: validationResult.timestamp,\n\t\tpayload: parsedPayload,\n\t};\n}\n","/**\n * Pierre Git Storage SDK\n *\n * A TypeScript SDK for interacting with Pierre's git storage system\n */\n\nimport { importPKCS8, SignJWT } from 'jose';\nimport snakecaseKeys from 'snakecase-keys';\nimport { ApiFetcher } from './fetch';\nimport type {\n\tCreateRepoOptions,\n\tFindOneOptions,\n\tGetBranchDiffOptions,\n\tGetBranchDiffResponse,\n\tGetCommitDiffOptions,\n\tGetCommitDiffResponse,\n\tGetCommitOptions,\n\tGetCommitResponse,\n\tGetFileOptions,\n\tGetRemoteURLOptions,\n\tGitStorageOptions,\n\tListBranchesOptions,\n\tListBranchesResponse,\n\tListCommitsOptions,\n\tListCommitsResponse,\n\tListFilesOptions,\n\tListFilesResponse,\n\tOverrideableGitStorageOptions,\n\tPullUpstreamOptions,\n\tRepo,\n\tValidAPIVersion,\n} from './types';\n\n/**\n * Type definitions for Pierre Git Storage SDK\n */\n\n// Import additional types from types.ts\nexport * from './types';\n\n// Export webhook validation utilities\nexport { parseSignatureHeader, validateWebhook, validateWebhookSignature } from './webhook';\n\n/**\n * Git Storage API\n */\n\ndeclare const __STORAGE_BASE_URL__: string;\ndeclare const __API_BASE_URL__: string;\n\nconst API_BASE_URL = __API_BASE_URL__;\nconst STORAGE_BASE_URL = __STORAGE_BASE_URL__;\nconst API_VERSION: ValidAPIVersion = 1;\n\nconst apiInstanceMap = new Map<string, ApiFetcher>();\n\nfunction getApiInstance(baseUrl: string, version: ValidAPIVersion) {\n\tif (!apiInstanceMap.has(`${baseUrl}--${version}`)) {\n\t\tapiInstanceMap.set(`${baseUrl}--${version}`, new ApiFetcher(baseUrl, version));\n\t}\n\treturn apiInstanceMap.get(`${baseUrl}--${version}`)!;\n}\n\n/**\n * Implementation of the Repo interface\n */\nclass RepoImpl implements Repo {\n\tprivate readonly api: ApiFetcher;\n\n\tconstructor(\n\t\tpublic readonly id: string,\n\t\tprivate readonly options: GitStorageOptions,\n\t\tprivate readonly generateJWT: (\n\t\t\trepoId: string,\n\t\t\toptions?: GetRemoteURLOptions,\n\t\t) => Promise<string>,\n\t) {\n\t\tthis.api = getApiInstance(\n\t\t\tthis.options.apiBaseUrl ?? API_BASE_URL,\n\t\t\tthis.options.apiVersion ?? API_VERSION,\n\t\t);\n\t}\n\n\tasync getRemoteURL(urlOptions?: GetRemoteURLOptions): Promise<string> {\n\t\tconst storageBaseUrl = this.options.storageBaseUrl ?? STORAGE_BASE_URL;\n\t\tconst url = new URL(`https://${this.options.name}.${storageBaseUrl}/${this.id}.git`);\n\t\turl.username = `t`;\n\t\turl.password = await this.generateJWT(this.id, urlOptions);\n\t\treturn url.toString();\n\t}\n\n\tasync getFileStream(options: GetFileOptions): Promise<Response> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\tpath: options.path,\n\t\t};\n\n\t\tif (options.ref) {\n\t\t\tparams.ref = options.ref;\n\t\t}\n\n\t\t// Return the raw fetch Response for streaming\n\t\treturn this.api.get({ path: 'repos/file', params }, jwt);\n\t}\n\n\tasync listFiles(options?: ListFilesOptions): Promise<ListFilesResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> | undefined = options?.ref\n\t\t\t? { ref: options.ref }\n\t\t\t: undefined;\n\t\tconst response = await this.api.get({ path: 'repos/files', params }, jwt);\n\n\t\treturn (await response.json()) as ListFilesResponse;\n\t}\n\n\tasync listBranches(options?: ListBranchesOptions): Promise<ListBranchesResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tlet params: Record<string, string> | undefined;\n\n\t\tif (options?.cursor || !options?.limit) {\n\t\t\tparams = {};\n\t\t\tif (options?.cursor) {\n\t\t\t\tparams.cursor = options.cursor;\n\t\t\t}\n\t\t\tif (typeof options?.limit == 'number') {\n\t\t\t\tparams.limit = options.limit.toString();\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.api.get({ path: 'repos/branches', params }, jwt);\n\n\t\treturn (await response.json()) as ListBranchesResponse;\n\t}\n\n\tasync listCommits(options?: ListCommitsOptions): Promise<ListCommitsResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tlet params: Record<string, string> | undefined;\n\n\t\tif (options?.branch || options?.cursor || options?.limit) {\n\t\t\tparams = {};\n\t\t\tif (options?.branch) {\n\t\t\t\tparams.branch = options.branch;\n\t\t\t}\n\t\t\tif (options?.cursor) {\n\t\t\t\tparams.cursor = options.cursor;\n\t\t\t}\n\t\t\tif (typeof options?.limit == 'number') {\n\t\t\t\tparams.limit = options.limit.toString();\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.api.get({ path: 'repos/commits', params }, jwt);\n\n\t\treturn (await response.json()) as ListCommitsResponse;\n\t}\n\n\tasync getBranchDiff(options: GetBranchDiffOptions): Promise<GetBranchDiffResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\tbranch: options.branch,\n\t\t};\n\n\t\tif (options.base) {\n\t\t\tparams.base = options.base;\n\t\t}\n\n\t\tconst response = await this.api.get({ path: 'repos/branches/diff', params }, jwt);\n\n\t\treturn (await response.json()) as GetBranchDiffResponse;\n\t}\n\n\tasync getCommitDiff(options: GetCommitDiffOptions): Promise<GetCommitDiffResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\tsha: options.sha,\n\t\t};\n\n\t\tconst response = await this.api.get({ path: 'repos/diff', params }, jwt);\n\n\t\treturn (await response.json()) as GetCommitDiffResponse;\n\t}\n\n\tasync getCommit(options: GetCommitOptions): Promise<GetCommitResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\trepo: this.id,\n\t\t\tsha: options.sha,\n\t\t};\n\t\tconst response = await this.api.get({ path: 'commit', params }, jwt);\n\n\t\treturn (await response.json()) as GetCommitResponse;\n\t}\n\n\tasync pullUpstream(options: PullUpstreamOptions): Promise<void> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:write'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst body: Record<string, string> = {};\n\n\t\tif (options.ref) {\n\t\t\tbody.ref = options.ref;\n\t\t}\n\n\t\tconst response = await this.api.post({ path: 'repos/pull-upstream', body }, jwt);\n\n\t\tif (response.status !== 202) {\n\t\t\tthrow new Error(`Pull Upstream failed: ${response.status} ${await response.text()}`);\n\t\t}\n\n\t\treturn;\n\t}\n}\n\nexport class GitStorage {\n\tprivate static overrides: OverrideableGitStorageOptions = {};\n\tprivate options: GitStorageOptions;\n\tprivate api: ApiFetcher;\n\n\tconstructor(options: GitStorageOptions) {\n\t\tif (\n\t\t\t!options ||\n\t\t\toptions.name === undefined ||\n\t\t\toptions.key === undefined ||\n\t\t\toptions.name === null ||\n\t\t\toptions.key === null\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t'GitStorage requires a name and key. Please check your configuration and try again.',\n\t\t\t);\n\t\t}\n\n\t\tif (typeof options.name !== 'string' || options.name.trim() === '') {\n\t\t\tthrow new Error('GitStorage name must be a non-empty string.');\n\t\t}\n\n\t\tif (typeof options.key !== 'string' || options.key.trim() === '') {\n\t\t\tthrow new Error('GitStorage key must be a non-empty string.');\n\t\t}\n\n\t\tconst resolvedApiBaseUrl =\n\t\t\toptions.apiBaseUrl ?? GitStorage.overrides.apiBaseUrl ?? API_BASE_URL;\n\t\tconst resolvedApiVersion = options.apiVersion ?? GitStorage.overrides.apiVersion ?? API_VERSION;\n\t\tconst resolvedStorageBaseUrl =\n\t\t\toptions.storageBaseUrl ?? GitStorage.overrides.storageBaseUrl ?? STORAGE_BASE_URL;\n\n\t\tthis.api = getApiInstance(resolvedApiBaseUrl, resolvedApiVersion);\n\n\t\tthis.options = {\n\t\t\tkey: options.key,\n\t\t\tname: options.name,\n\t\t\tapiBaseUrl: resolvedApiBaseUrl,\n\t\t\tapiVersion: resolvedApiVersion,\n\t\t\tstorageBaseUrl: resolvedStorageBaseUrl,\n\t\t};\n\t}\n\n\tstatic override(options: OverrideableGitStorageOptions): void {\n\t\tthis.overrides = Object.assign({}, this.overrides, options);\n\t}\n\n\t/**\n\t * Create a new repository\n\t * @returns The created repository\n\t */\n\tasync createRepo(options?: CreateRepoOptions): Promise<Repo> {\n\t\tconst repoId = options?.id || crypto.randomUUID();\n\n\t\tconst jwt = await this.generateJWT(repoId, {\n\t\t\tpermissions: ['repo:write'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst baseRepoOptions = options?.baseRepo\n\t\t\t? {\n\t\t\t\t\tprovider: 'github',\n\t\t\t\t\t...snakecaseKeys(options.baseRepo as unknown as Record<string, unknown>),\n\t\t\t\t}\n\t\t\t: null;\n\n\t\t// Default defaultBranch to 'main' if not provided\n\t\tconst defaultBranch = options?.defaultBranch ?? 'main';\n\n\t\tconst createRepoPath =\n\t\t\tbaseRepoOptions || defaultBranch\n\t\t\t\t? {\n\t\t\t\t\t\tpath: 'repos',\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t...(baseRepoOptions && { base_repo: baseRepoOptions }),\n\t\t\t\t\t\t\tdefault_branch: defaultBranch,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: 'repos';\n\n\t\t// Allow 409 so we can map it to a clearer error message\n\t\tconst resp = await this.api.post(createRepoPath, jwt, { allowedStatus: [409] });\n\t\tif (resp.status === 409) {\n\t\t\tthrow new Error('Repository already exists');\n\t\t}\n\n\t\treturn new RepoImpl(repoId, this.options, this.generateJWT.bind(this));\n\t}\n\n\t/**\n\t * Find a repository by ID\n\t * @param options The search options\n\t * @returns The found repository\n\t */\n\tasync findOne(options: FindOneOptions): Promise<Repo | null> {\n\t\tconst jwt = await this.generateJWT(options.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: 1 * 60 * 60,\n\t\t});\n\n\t\t// Allow 404 to indicate \"not found\" without throwing\n\t\tconst resp = await this.api.get('repo', jwt, { allowedStatus: [404] });\n\t\tif (resp.status === 404) {\n\t\t\treturn null;\n\t\t}\n\t\t// On 200, we could validate response, but RepoImpl only needs the repo URL/id\n\t\t// const body = await resp.json(); // not required for now\n\t\treturn new RepoImpl(options.id, this.options, this.generateJWT.bind(this));\n\t}\n\n\t/**\n\t * Get the current configuration\n\t * @returns The client configuration\n\t */\n\tgetConfig(): GitStorageOptions {\n\t\treturn { ...this.options };\n\t}\n\n\t/**\n\t * Generate a JWT token for git storage URL authentication\n\t * @private\n\t */\n\tprivate async generateJWT(repoId: string, options?: GetRemoteURLOptions): Promise<string> {\n\t\t// Default permissions and TTL\n\t\tconst permissions = options?.permissions || ['git:write', 'git:read'];\n\t\tconst ttl = options?.ttl || 365 * 24 * 60 * 60; // 1 year in seconds\n\n\t\t// Create the JWT payload\n\t\tconst now = Math.floor(Date.now() / 1000);\n\t\tconst payload = {\n\t\t\tiss: this.options.name,\n\t\t\tsub: '@pierre/storage',\n\t\t\trepo: repoId,\n\t\t\tscopes: permissions,\n\t\t\tiat: now,\n\t\t\texp: now + ttl,\n\t\t};\n\n\t\t// Sign the JWT with the key as the secret\n\t\t// Using HS256 for symmetric signing with the key\n\t\tconst key = await importPKCS8(this.options.key, 'ES256');\n\t\t// Sign the JWT with the key as the secret\n\t\tconst jwt = await new SignJWT(payload)\n\t\t\t.setProtectedHeader({ alg: 'ES256', typ: 'JWT' })\n\t\t\t.sign(key);\n\n\t\treturn jwt;\n\t}\n}\n\n// Export a default client factory\nexport function createClient(options: GitStorageOptions): GitStorage {\n\treturn new GitStorage(options);\n}\n\n// Type alias for backward compatibility\nexport type StorageOptions = GitStorageOptions;\n"]}
1
+ {"version":3,"sources":["../src/commit.ts","../src/fetch.ts","../src/util.ts","../src/webhook.ts","../src/index.ts"],"names":["API_BASE_URL","crypto"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n\tCommitBuilder,\n\tCommitFileOptions,\n\tCommitFileSource,\n\tCommitResponse,\n\tCommitTextFileOptions,\n\tCreateCommitOptions,\n} from './types';\n\nconst MAX_CHUNK_BYTES = 4 * 1024 * 1024;\nconst DEFAULT_TTL_SECONDS = 60 * 60;\n\ntype NodeBuffer = Uint8Array & { toString(encoding?: string): string };\ninterface NodeBufferConstructor {\n\tfrom(data: Uint8Array): NodeBuffer;\n\tfrom(data: string, encoding?: string): NodeBuffer;\n\tisBuffer(value: unknown): value is NodeBuffer;\n}\n\nconst BufferCtor: NodeBufferConstructor | undefined = (\n\tglobalThis as { Buffer?: NodeBufferConstructor }\n).Buffer;\n\ninterface ReadableStreamReaderLike<T> {\n\tread(): Promise<{ value?: T; done: boolean }>;\n\treleaseLock?(): void;\n}\n\ninterface ReadableStreamLike<T> {\n\tgetReader(): ReadableStreamReaderLike<T>;\n}\n\ninterface BlobLike {\n\tstream(): unknown;\n}\n\ntype ChunkSegment = {\n\tchunk: Uint8Array;\n\teof: boolean;\n};\n\ninterface CommitMetadataPayload {\n\ttarget_ref: string;\n\tbase_ref?: string;\n\tcommit_message: string;\n\tauthor?: {\n\t\tname: string;\n\t\temail: string;\n\t\tdate?: string;\n\t};\n\tcommitter?: {\n\t\tname: string;\n\t\temail: string;\n\t\tdate?: string;\n\t};\n\tfiles: Array<{\n\t\tpath: string;\n\t\tcontent_id: string;\n\t\toperation?: 'upsert' | 'delete';\n\t\tmode?: string;\n\t}>;\n}\n\ninterface CommitTransportRequest {\n\tauthorization: string;\n\tsignal?: AbortSignal;\n\tmetadata: CommitMetadataPayload;\n\tblobs: Array<{ contentId: string; chunks: AsyncIterable<ChunkSegment> }>;\n}\n\ninterface CommitTransport {\n\tsend(request: CommitTransportRequest): Promise<CommitResponse>;\n}\n\ninterface CommitBuilderDeps {\n\toptions: CreateCommitOptions;\n\tgetAuthToken: () => Promise<string>;\n\ttransport: CommitTransport;\n}\n\ntype FileOperationState = {\n\tpath: string;\n\tcontentId: string;\n\tmode?: string;\n\toperation: 'upsert' | 'delete';\n\tstreamFactory?: () => AsyncIterable<Uint8Array>;\n};\n\nexport class CommitBuilderImpl implements CommitBuilder {\n\tprivate readonly options: CreateCommitOptions;\n\tprivate readonly getAuthToken: () => Promise<string>;\n\tprivate readonly transport: CommitTransport;\n\tprivate readonly operations: FileOperationState[] = [];\n\tprivate sent = false;\n\n\tconstructor(deps: CommitBuilderDeps) {\n\t\tthis.options = { ...deps.options };\n\t\tthis.getAuthToken = deps.getAuthToken;\n\t\tthis.transport = deps.transport;\n\n\t\tconst trimmedTarget = this.options.targetRef?.trim();\n\t\tconst trimmedMessage = this.options.commitMessage?.trim();\n\t\tif (!trimmedTarget) {\n\t\t\tthrow new Error('createCommit targetRef is required');\n\t\t}\n\t\tif (!trimmedMessage) {\n\t\t\tthrow new Error('createCommit commitMessage is required');\n\t\t}\n\t\tthis.options.targetRef = trimmedTarget;\n\t\tthis.options.commitMessage = trimmedMessage;\n\t\tif (typeof this.options.baseRef === 'string') {\n\t\t\tthis.options.baseRef = this.options.baseRef.trim();\n\t\t}\n\t}\n\n\taddFile(path: string, source: CommitFileSource, options?: CommitFileOptions): CommitBuilder {\n\t\tthis.ensureNotSent();\n\t\tconst normalizedPath = this.normalizePath(path);\n\t\tconst contentId = randomContentId();\n\t\tconst mode = options?.mode ?? '100644';\n\n\t\tthis.operations.push({\n\t\t\tpath: normalizedPath,\n\t\t\tcontentId,\n\t\t\tmode,\n\t\t\toperation: 'upsert',\n\t\t\tstreamFactory: () => toAsyncIterable(source),\n\t\t});\n\n\t\treturn this;\n\t}\n\n\taddFileFromString(\n\t\tpath: string,\n\t\tcontents: string,\n\t\toptions?: CommitTextFileOptions,\n\t): CommitBuilder {\n\t\tconst encoding = options?.encoding;\n\t\tif (encoding && encoding !== 'utf8' && encoding !== 'utf-8') {\n\t\t\tthrow new Error(`Unsupported encoding \"${encoding}\". Only UTF-8 is supported.`);\n\t\t}\n\t\tconst data = new TextEncoder().encode(contents);\n\t\treturn this.addFile(path, data, options);\n\t}\n\n\tdeletePath(path: string): CommitBuilder {\n\t\tthis.ensureNotSent();\n\t\tconst normalizedPath = this.normalizePath(path);\n\t\tthis.operations.push({\n\t\t\tpath: normalizedPath,\n\t\t\tcontentId: randomContentId(),\n\t\t\toperation: 'delete',\n\t\t});\n\t\treturn this;\n\t}\n\n\tasync send(): Promise<CommitResponse> {\n\t\tthis.ensureNotSent();\n\t\tthis.sent = true;\n\n\t\tconst metadata = this.buildMetadata();\n\t\tconst blobEntries = this.operations\n\t\t\t.filter((op) => op.operation === 'upsert' && op.streamFactory)\n\t\t\t.map((op) => ({\n\t\t\t\tcontentId: op.contentId,\n\t\t\t\tchunks: chunkify(op.streamFactory!()),\n\t\t\t}));\n\n\t\tconst authorization = await this.getAuthToken();\n\t\treturn this.transport.send({\n\t\t\tauthorization,\n\t\t\tsignal: this.options.signal,\n\t\t\tmetadata,\n\t\t\tblobs: blobEntries,\n\t\t});\n\t}\n\n\tprivate buildMetadata(): CommitMetadataPayload {\n\t\tconst files = this.operations.map((op) => {\n\t\t\tconst entry: CommitMetadataPayload['files'][number] = {\n\t\t\t\tpath: op.path,\n\t\t\t\tcontent_id: op.contentId,\n\t\t\t\toperation: op.operation,\n\t\t\t};\n\t\t\tif (op.mode) {\n\t\t\t\tentry.mode = op.mode;\n\t\t\t}\n\t\t\treturn entry;\n\t\t});\n\n\t\tconst metadata: CommitMetadataPayload = {\n\t\t\ttarget_ref: this.options.targetRef,\n\t\t\tcommit_message: this.options.commitMessage,\n\t\t\tfiles,\n\t\t};\n\n\t\tif (this.options.baseRef) {\n\t\t\tmetadata.base_ref = this.options.baseRef;\n\t\t}\n\t\tif (this.options.author) {\n\t\t\tmetadata.author = { ...this.options.author };\n\t\t}\n\t\tif (this.options.committer) {\n\t\t\tmetadata.committer = { ...this.options.committer };\n\t\t}\n\n\t\treturn metadata;\n\t}\n\n\tprivate ensureNotSent(): void {\n\t\tif (this.sent) {\n\t\t\tthrow new Error('createCommit builder cannot be reused after send()');\n\t\t}\n\t}\n\n\tprivate normalizePath(path: string): string {\n\t\tif (!path || typeof path !== 'string' || path.trim() === '') {\n\t\t\tthrow new Error('File path must be a non-empty string');\n\t\t}\n\t\treturn path.replace(/^\\//, '');\n\t}\n}\n\nexport class FetchCommitTransport implements CommitTransport {\n\tprivate readonly url: string;\n\n\tconstructor(config: { baseUrl: string; version: number }) {\n\t\tconst trimmedBase = config.baseUrl.replace(/\\/+$/, '');\n\t\tthis.url = `${trimmedBase}/api/v${config.version}/repos/commit-pack`;\n\t}\n\n\tasync send(request: CommitTransportRequest): Promise<CommitResponse> {\n\t\tconst bodyIterable = buildMessageIterable(request.metadata, request.blobs);\n\t\tconst body = toRequestBody(bodyIterable);\n\n\t\tconst response = await fetch(this.url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${request.authorization}`,\n\t\t\t\t'Content-Type': 'application/x-ndjson',\n\t\t\t\tAccept: 'application/json',\n\t\t\t},\n\t\t\tbody: body as any,\n\t\t\tsignal: request.signal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst text = await response.text();\n\t\t\tthrow new Error(`createCommit request failed (${response.status}): ${text}`);\n\t\t}\n\n\t\treturn (await response.json()) as CommitResponse;\n\t}\n}\n\nfunction toRequestBody(iterable: AsyncIterable<Uint8Array>): unknown {\n\tconst readableStreamCtor = (\n\t\tglobalThis as { ReadableStream?: new (underlyingSource: unknown) => unknown }\n\t).ReadableStream;\n\tif (typeof readableStreamCtor === 'function') {\n\t\tconst iterator = iterable[Symbol.asyncIterator]();\n\t\treturn new readableStreamCtor({\n\t\t\tasync pull(controller: { enqueue(chunk: Uint8Array): void; close(): void }) {\n\t\t\t\tconst { value, done } = await iterator.next();\n\t\t\t\tif (done) {\n\t\t\t\t\tcontroller.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcontroller.enqueue(value!);\n\t\t\t},\n\t\t\tasync cancel(reason: unknown) {\n\t\t\t\tif (typeof iterator.return === 'function') {\n\t\t\t\t\tawait iterator.return(reason);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\treturn iterable;\n}\n\nfunction buildMessageIterable(\n\tmetadata: CommitMetadataPayload,\n\tblobs: Array<{ contentId: string; chunks: AsyncIterable<ChunkSegment> }>,\n): AsyncIterable<Uint8Array> {\n\tconst encoder = new TextEncoder();\n\treturn {\n\t\tasync *[Symbol.asyncIterator]() {\n\t\t\tyield encoder.encode(`${JSON.stringify({ metadata })}\\n`);\n\t\t\tfor (const blob of blobs) {\n\t\t\t\tfor await (const segment of blob.chunks) {\n\t\t\t\t\tconst payload = {\n\t\t\t\t\t\tblob_chunk: {\n\t\t\t\t\t\t\tcontent_id: blob.contentId,\n\t\t\t\t\t\t\tdata: base64Encode(segment.chunk),\n\t\t\t\t\t\t\teof: segment.eof,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tyield encoder.encode(`${JSON.stringify(payload)}\\n`);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nasync function* chunkify(source: AsyncIterable<Uint8Array>): AsyncIterable<ChunkSegment> {\n\tlet pending: Uint8Array | null = null;\n\tlet produced = false;\n\n\tfor await (const value of source) {\n\t\tconst bytes = value;\n\n\t\tif (pending && pending.byteLength === MAX_CHUNK_BYTES) {\n\t\t\tyield { chunk: pending, eof: false };\n\t\t\tproduced = true;\n\t\t\tpending = null;\n\t\t}\n\n\t\tconst merged: Uint8Array = pending ? concatChunks(pending, bytes) : bytes;\n\t\tpending = null;\n\n\t\tlet cursor: Uint8Array = merged;\n\t\twhile (cursor.byteLength > MAX_CHUNK_BYTES) {\n\t\t\tconst chunk: Uint8Array = cursor.slice(0, MAX_CHUNK_BYTES);\n\t\t\tcursor = cursor.slice(MAX_CHUNK_BYTES);\n\t\t\tyield { chunk, eof: false };\n\t\t\tproduced = true;\n\t\t}\n\n\t\tpending = cursor;\n\t}\n\n\tif (pending) {\n\t\tyield { chunk: pending, eof: true };\n\t\tproduced = true;\n\t}\n\n\tif (!produced) {\n\t\tyield { chunk: new Uint8Array(0), eof: true };\n\t}\n}\n\nasync function* toAsyncIterable(source: CommitFileSource): AsyncIterable<Uint8Array> {\n\tif (typeof source === 'string') {\n\t\tyield new TextEncoder().encode(source);\n\t\treturn;\n\t}\n\tif (source instanceof Uint8Array) {\n\t\tyield source;\n\t\treturn;\n\t}\n\tif (source instanceof ArrayBuffer) {\n\t\tyield new Uint8Array(source);\n\t\treturn;\n\t}\n\tif (ArrayBuffer.isView(source)) {\n\t\tyield new Uint8Array(source.buffer, source.byteOffset, source.byteLength);\n\t\treturn;\n\t}\n\tif (isBlobLike(source)) {\n\t\tconst stream = source.stream();\n\t\tif (isAsyncIterable(stream)) {\n\t\t\tfor await (const chunk of stream as AsyncIterable<unknown>) {\n\t\t\t\tyield ensureUint8Array(chunk);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (isReadableStreamLike(stream)) {\n\t\t\tyield* readReadableStream(stream);\n\t\t\treturn;\n\t\t}\n\t}\n\tif (isAsyncIterable(source)) {\n\t\tfor await (const chunk of source as AsyncIterable<unknown>) {\n\t\t\tyield ensureUint8Array(chunk);\n\t\t}\n\t\treturn;\n\t}\n\tif (isIterable(source)) {\n\t\tfor (const chunk of source as Iterable<unknown>) {\n\t\t\tyield ensureUint8Array(chunk);\n\t\t}\n\t\treturn;\n\t}\n\tthrow new Error('Unsupported file source for createCommit');\n}\n\nasync function* readReadableStream(stream: ReadableStreamLike<unknown>): AsyncIterable<Uint8Array> {\n\tconst reader = stream.getReader();\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (value !== undefined) {\n\t\t\t\tyield ensureUint8Array(value);\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock?.();\n\t}\n}\n\nfunction ensureUint8Array(value: unknown): Uint8Array {\n\tif (value instanceof Uint8Array) {\n\t\treturn value;\n\t}\n\tif (value instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(value);\n\t}\n\tif (ArrayBuffer.isView(value)) {\n\t\treturn new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n\t}\n\tif (typeof value === 'string') {\n\t\treturn new TextEncoder().encode(value);\n\t}\n\tif (BufferCtor && BufferCtor.isBuffer(value)) {\n\t\treturn value as Uint8Array;\n\t}\n\tthrow new Error('Unsupported chunk type; expected binary data');\n}\n\nfunction isBlobLike(value: unknown): value is BlobLike {\n\treturn (\n\t\ttypeof value === 'object' && value !== null && typeof (value as BlobLike).stream === 'function'\n\t);\n}\n\nfunction isReadableStreamLike<T>(value: unknown): value is ReadableStreamLike<T> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\ttypeof (value as ReadableStreamLike<T>).getReader === 'function'\n\t);\n}\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tSymbol.asyncIterator in (value as Record<string, unknown>)\n\t);\n}\n\nfunction isIterable(value: unknown): value is Iterable<unknown> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tSymbol.iterator in (value as Record<string, unknown>)\n\t);\n}\n\nfunction concatChunks(a: Uint8Array, b: Uint8Array): Uint8Array {\n\tif (a.byteLength === 0) {\n\t\treturn b;\n\t}\n\tif (b.byteLength === 0) {\n\t\treturn a;\n\t}\n\tconst merged = new Uint8Array(a.byteLength + b.byteLength);\n\tmerged.set(a, 0);\n\tmerged.set(b, a.byteLength);\n\treturn merged;\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n\tif (BufferCtor) {\n\t\treturn BufferCtor.from(bytes).toString('base64');\n\t}\n\tlet binary = '';\n\tfor (let i = 0; i < bytes.byteLength; i++) {\n\t\tbinary += String.fromCharCode(bytes[i]);\n\t}\n\tconst btoaFn = (globalThis as { btoa?: (data: string) => string }).btoa;\n\tif (typeof btoaFn === 'function') {\n\t\treturn btoaFn(binary);\n\t}\n\tthrow new Error('Base64 encoding is not supported in this environment');\n}\n\nfunction randomContentId(): string {\n\tconst cryptoObj = globalThis.crypto;\n\tif (cryptoObj && typeof cryptoObj.randomUUID === 'function') {\n\t\treturn cryptoObj.randomUUID();\n\t}\n\tconst random = Math.random().toString(36).slice(2);\n\treturn `cid-${Date.now().toString(36)}-${random}`;\n}\n\nexport function createCommitBuilder(deps: CommitBuilderDeps): CommitBuilder {\n\treturn new CommitBuilderImpl(deps);\n}\n\nexport function resolveCommitTtlSeconds(options?: { ttl?: number }): number {\n\treturn typeof options?.ttl === 'number' && options.ttl > 0 ? options.ttl : DEFAULT_TTL_SECONDS;\n}\n","import type { ValidAPIVersion, ValidMethod, ValidPath } from './types';\n\ninterface RequestOptions {\n\tallowedStatus?: number[];\n}\n\nexport class ApiFetcher {\n\tconstructor(\n\t\tprivate readonly API_BASE_URL: string,\n\t\tprivate readonly version: ValidAPIVersion,\n\t) {\n\t\tconsole.log('api fetcher created', API_BASE_URL, version);\n\t}\n\n\tprivate getBaseUrl() {\n\t\treturn `${this.API_BASE_URL}/api/v${this.version}`;\n\t}\n\n\tprivate getRequestUrl(path: ValidPath) {\n\t\tif (typeof path === 'string') {\n\t\t\treturn `${this.getBaseUrl()}/${path}`;\n\t\t} else if (path.params) {\n\t\t\tconst paramStr = new URLSearchParams(path.params).toString();\n\t\t\treturn `${this.getBaseUrl()}/${path.path}${paramStr ? `?${paramStr}` : ''}`;\n\t\t} else {\n\t\t\treturn `${this.getBaseUrl()}/${path.path}`;\n\t\t}\n\t}\n\n\tprivate async fetch(path: ValidPath, method: ValidMethod, jwt: string, options?: RequestOptions) {\n\t\tconst requestUrl = this.getRequestUrl(path);\n\n\t\tconst requestOptions: RequestInit = {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${jwt}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t};\n\n\t\tif (method !== 'GET' && typeof path !== 'string' && path.body) {\n\t\t\trequestOptions.body = JSON.stringify(path.body);\n\t\t}\n\n\t\tconst response = await fetch(requestUrl, requestOptions);\n\n\t\tif (!response.ok) {\n\t\t\tconst allowed = options?.allowedStatus ?? [];\n\t\t\tif (!allowed.includes(response.status)) {\n\t\t\t\tthrow new Error(`Failed to fetch ${method} ${requestUrl}: ${response.statusText}`);\n\t\t\t}\n\t\t}\n\t\treturn response;\n\t}\n\n\tasync get(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'GET', jwt, options);\n\t}\n\n\tasync post(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'POST', jwt, options);\n\t}\n\n\tasync put(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'PUT', jwt, options);\n\t}\n\n\tasync delete(path: ValidPath, jwt: string, options?: RequestOptions) {\n\t\treturn this.fetch(path, 'DELETE', jwt, options);\n\t}\n}\n","export function timingSafeEqual(a: string | Uint8Array, b: string | Uint8Array): boolean {\n\tconst bufferA = typeof a === 'string' ? new TextEncoder().encode(a) : a;\n\tconst bufferB = typeof b === 'string' ? new TextEncoder().encode(b) : b;\n\n\tif (bufferA.length !== bufferB.length) return false;\n\n\tlet result = 0;\n\tfor (let i = 0; i < bufferA.length; i++) {\n\t\tresult |= bufferA[i] ^ bufferB[i];\n\t}\n\treturn result === 0;\n}\n\nexport async function getEnvironmentCrypto() {\n\tif (!globalThis.crypto) {\n\t\tconst { webcrypto } = await import('node:crypto');\n\t\treturn webcrypto;\n\t}\n\treturn globalThis.crypto;\n}\n\nexport async function createHmac(algorithm: string, secret: string, data: string): Promise<string> {\n\tif (algorithm !== 'sha256') {\n\t\tthrow new Error('Only sha256 algorithm is supported');\n\t}\n\tif (!secret || secret.length === 0) {\n\t\tthrow new Error('Secret is required');\n\t}\n\n\tconst crypto = await getEnvironmentCrypto();\n\tconst encoder = new TextEncoder();\n\tconst key = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tencoder.encode(secret),\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign'],\n\t);\n\n\tconst signature = await crypto.subtle.sign('HMAC', key, encoder.encode(data));\n\treturn Array.from(new Uint8Array(signature))\n\t\t.map((b) => b.toString(16).padStart(2, '0'))\n\t\t.join('');\n}\n\n// Keep the legacy async function for backward compatibility\nexport async function createHmacAsync(secret: string, data: string): Promise<string> {\n\tconst crypto = await getEnvironmentCrypto();\n\tconst encoder = new TextEncoder();\n\tconst key = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tencoder.encode(secret),\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign'],\n\t);\n\n\tconst signature = await crypto.subtle.sign('HMAC', key, encoder.encode(data));\n\treturn Array.from(new Uint8Array(signature))\n\t\t.map((b) => b.toString(16).padStart(2, '0'))\n\t\t.join('');\n}\n","/**\n * Webhook validation utilities for Pierre Git Storage\n */\n\nimport type {\n\tParsedWebhookSignature,\n\tWebhookEventPayload,\n\tWebhookValidationOptions,\n\tWebhookValidationResult,\n} from './types';\n\nimport { createHmac, timingSafeEqual } from './util';\n\nconst DEFAULT_MAX_AGE_SECONDS = 300; // 5 minutes\n\n/**\n * Parse the X-Pierre-Signature header\n * Format: t=<timestamp>,sha256=<signature>\n */\nexport function parseSignatureHeader(header: string): ParsedWebhookSignature | null {\n\tif (!header || typeof header !== 'string') {\n\t\treturn null;\n\t}\n\n\tlet timestamp = '';\n\tlet signature = '';\n\n\t// Split by comma and parse each element\n\tconst elements = header.split(',');\n\tfor (const element of elements) {\n\t\tconst trimmedElement = element.trim();\n\t\tconst parts = trimmedElement.split('=', 2);\n\t\tif (parts.length !== 2) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst [key, value] = parts;\n\t\tswitch (key) {\n\t\t\tcase 't':\n\t\t\t\ttimestamp = value;\n\t\t\t\tbreak;\n\t\t\tcase 'sha256':\n\t\t\t\tsignature = value;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!timestamp || !signature) {\n\t\treturn null;\n\t}\n\n\treturn { timestamp, signature };\n}\n\n/**\n * Validate a webhook signature and timestamp\n *\n * @param payload - The raw webhook payload (request body)\n * @param signatureHeader - The X-Pierre-Signature header value\n * @param secret - The webhook secret for HMAC verification\n * @param options - Validation options\n * @returns Validation result with details\n *\n * @example\n * ```typescript\n * const result = await validateWebhookSignature(\n * requestBody,\n * request.headers['x-pierre-signature'],\n * webhookSecret\n * );\n *\n * if (!result.valid) {\n * console.error('Invalid webhook:', result.error);\n * return;\n * }\n * ```\n */\nexport async function validateWebhookSignature(\n\tpayload: string | Buffer,\n\tsignatureHeader: string,\n\tsecret: string,\n\toptions: WebhookValidationOptions = {},\n): Promise<WebhookValidationResult> {\n\tif (!secret || secret.length === 0) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Empty secret is not allowed',\n\t\t};\n\t}\n\n\t// Parse the signature header\n\tconst parsed = parseSignatureHeader(signatureHeader);\n\tif (!parsed) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid signature header format',\n\t\t};\n\t}\n\n\t// Parse timestamp\n\tconst timestamp = Number.parseInt(parsed.timestamp, 10);\n\tif (isNaN(timestamp)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid timestamp in signature',\n\t\t};\n\t}\n\n\t// Validate timestamp age (prevent replay attacks)\n\tconst maxAge = options.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS;\n\tif (maxAge > 0) {\n\t\tconst now = Math.floor(Date.now() / 1000);\n\t\tconst age = now - timestamp;\n\n\t\tif (age > maxAge) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\terror: `Webhook timestamp too old (${age} seconds)`,\n\t\t\t\ttimestamp,\n\t\t\t};\n\t\t}\n\n\t\t// Also reject timestamps from the future (clock skew tolerance of 60 seconds)\n\t\tif (age < -60) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\terror: 'Webhook timestamp is in the future',\n\t\t\t\ttimestamp,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Convert payload to string if it's a Buffer\n\tconst payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n\n\t// Compute expected signature\n\t// Format: HMAC-SHA256(secret, timestamp + \".\" + payload)\n\tconst signedData = `${parsed.timestamp}.${payloadStr}`;\n\tconst expectedSignature = await createHmac('sha256', secret, signedData);\n\n\t// Compare signatures using constant-time comparison\n\tconst expectedBuffer = Buffer.from(expectedSignature);\n\tconst actualBuffer = Buffer.from(parsed.signature);\n\n\t// Ensure both buffers are the same length for timing-safe comparison\n\tif (expectedBuffer.length !== actualBuffer.length) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid signature',\n\t\t\ttimestamp,\n\t\t};\n\t}\n\n\tconst signaturesMatch = timingSafeEqual(expectedBuffer, actualBuffer);\n\tif (!signaturesMatch) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid signature',\n\t\t\ttimestamp,\n\t\t};\n\t}\n\n\treturn {\n\t\tvalid: true,\n\t\ttimestamp,\n\t};\n}\n\n/**\n * Validate a webhook request\n *\n * This is a convenience function that validates the signature and parses the payload.\n *\n * @param payload - The raw webhook payload (request body)\n * @param headers - The request headers (must include x-pierre-signature and x-pierre-event)\n * @param secret - The webhook secret for HMAC verification\n * @param options - Validation options\n * @returns The parsed webhook payload if valid, or validation error\n *\n * @example\n * ```typescript\n * const result = await validateWebhook(\n * request.body,\n * request.headers,\n * process.env.WEBHOOK_SECRET\n * );\n *\n * if (!result.valid) {\n * return new Response('Invalid webhook', { status: 401 });\n * }\n *\n * // Type-safe access to the webhook payload\n * console.log('Push event:', result.payload);\n * ```\n */\nexport async function validateWebhook(\n\tpayload: string | Buffer,\n\theaders: Record<string, string | string[] | undefined>,\n\tsecret: string,\n\toptions: WebhookValidationOptions = {},\n): Promise<WebhookValidationResult & { payload?: WebhookEventPayload }> {\n\t// Get signature header\n\tconst signatureHeader = headers['x-pierre-signature'] || headers['X-Pierre-Signature'];\n\tif (!signatureHeader || Array.isArray(signatureHeader)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Missing or invalid X-Pierre-Signature header',\n\t\t};\n\t}\n\n\t// Get event type header\n\tconst eventType = headers['x-pierre-event'] || headers['X-Pierre-Event'];\n\tif (!eventType || Array.isArray(eventType)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Missing or invalid X-Pierre-Event header',\n\t\t};\n\t}\n\n\t// Validate signature\n\tconst validationResult = await validateWebhookSignature(\n\t\tpayload,\n\t\tsignatureHeader,\n\t\tsecret,\n\t\toptions,\n\t);\n\n\tif (!validationResult.valid) {\n\t\treturn validationResult;\n\t}\n\n\t// Parse payload\n\tconst payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n\tlet parsedPayload: WebhookEventPayload;\n\ttry {\n\t\tparsedPayload = JSON.parse(payloadStr);\n\t} catch {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: 'Invalid JSON payload',\n\t\t\ttimestamp: validationResult.timestamp,\n\t\t};\n\t}\n\n\treturn {\n\t\tvalid: true,\n\t\teventType,\n\t\ttimestamp: validationResult.timestamp,\n\t\tpayload: parsedPayload,\n\t};\n}\n","/**\n * Pierre Git Storage SDK\n *\n * A TypeScript SDK for interacting with Pierre's git storage system\n */\n\nimport { importPKCS8, SignJWT } from 'jose';\nimport snakecaseKeys from 'snakecase-keys';\nimport { createCommitBuilder, FetchCommitTransport, resolveCommitTtlSeconds } from './commit';\nimport { ApiFetcher } from './fetch';\nimport type {\n\tCommitBuilder,\n\tCreateCommitOptions,\n\tCreateRepoOptions,\n\tFindOneOptions,\n\tGetBranchDiffOptions,\n\tGetBranchDiffResponse,\n\tGetCommitDiffOptions,\n\tGetCommitDiffResponse,\n\tGetCommitOptions,\n\tGetCommitResponse,\n\tGetFileOptions,\n\tGetRemoteURLOptions,\n\tGitStorageOptions,\n\tListBranchesOptions,\n\tListBranchesResponse,\n\tListCommitsOptions,\n\tListCommitsResponse,\n\tListFilesOptions,\n\tListFilesResponse,\n\tOverrideableGitStorageOptions,\n\tPullUpstreamOptions,\n\tRepo,\n\tValidAPIVersion,\n} from './types';\n\n/**\n * Type definitions for Pierre Git Storage SDK\n */\n\n// Import additional types from types.ts\nexport * from './types';\n\n// Export webhook validation utilities\nexport { parseSignatureHeader, validateWebhook, validateWebhookSignature } from './webhook';\n\n/**\n * Git Storage API\n */\n\ndeclare const __STORAGE_BASE_URL__: string;\ndeclare const __API_BASE_URL__: string;\n\nconst API_BASE_URL = __API_BASE_URL__;\nconst STORAGE_BASE_URL = __STORAGE_BASE_URL__;\nconst API_VERSION: ValidAPIVersion = 1;\n\nconst apiInstanceMap = new Map<string, ApiFetcher>();\n\nfunction getApiInstance(baseUrl: string, version: ValidAPIVersion) {\n\tif (!apiInstanceMap.has(`${baseUrl}--${version}`)) {\n\t\tapiInstanceMap.set(`${baseUrl}--${version}`, new ApiFetcher(baseUrl, version));\n\t}\n\treturn apiInstanceMap.get(`${baseUrl}--${version}`)!;\n}\n\n/**\n * Implementation of the Repo interface\n */\nclass RepoImpl implements Repo {\n\tprivate readonly api: ApiFetcher;\n\n\tconstructor(\n\t\tpublic readonly id: string,\n\t\tprivate readonly options: GitStorageOptions,\n\t\tprivate readonly generateJWT: (\n\t\t\trepoId: string,\n\t\t\toptions?: GetRemoteURLOptions,\n\t\t) => Promise<string>,\n\t) {\n\t\tthis.api = getApiInstance(\n\t\t\tthis.options.apiBaseUrl ?? API_BASE_URL,\n\t\t\tthis.options.apiVersion ?? API_VERSION,\n\t\t);\n\t}\n\n\tasync getRemoteURL(urlOptions?: GetRemoteURLOptions): Promise<string> {\n\t\tconst storageBaseUrl = this.options.storageBaseUrl ?? STORAGE_BASE_URL;\n\t\tconst url = new URL(`https://${this.options.name}.${storageBaseUrl}/${this.id}.git`);\n\t\turl.username = `t`;\n\t\turl.password = await this.generateJWT(this.id, urlOptions);\n\t\treturn url.toString();\n\t}\n\n\tasync getFileStream(options: GetFileOptions): Promise<Response> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\tpath: options.path,\n\t\t};\n\n\t\tif (options.ref) {\n\t\t\tparams.ref = options.ref;\n\t\t}\n\n\t\t// Return the raw fetch Response for streaming\n\t\treturn this.api.get({ path: 'repos/file', params }, jwt);\n\t}\n\n\tasync listFiles(options?: ListFilesOptions): Promise<ListFilesResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> | undefined = options?.ref\n\t\t\t? { ref: options.ref }\n\t\t\t: undefined;\n\t\tconst response = await this.api.get({ path: 'repos/files', params }, jwt);\n\n\t\treturn (await response.json()) as ListFilesResponse;\n\t}\n\n\tasync listBranches(options?: ListBranchesOptions): Promise<ListBranchesResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tlet params: Record<string, string> | undefined;\n\n\t\tif (options?.cursor || !options?.limit) {\n\t\t\tparams = {};\n\t\t\tif (options?.cursor) {\n\t\t\t\tparams.cursor = options.cursor;\n\t\t\t}\n\t\t\tif (typeof options?.limit == 'number') {\n\t\t\t\tparams.limit = options.limit.toString();\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.api.get({ path: 'repos/branches', params }, jwt);\n\n\t\treturn (await response.json()) as ListBranchesResponse;\n\t}\n\n\tasync listCommits(options?: ListCommitsOptions): Promise<ListCommitsResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tlet params: Record<string, string> | undefined;\n\n\t\tif (options?.branch || options?.cursor || options?.limit) {\n\t\t\tparams = {};\n\t\t\tif (options?.branch) {\n\t\t\t\tparams.branch = options.branch;\n\t\t\t}\n\t\t\tif (options?.cursor) {\n\t\t\t\tparams.cursor = options.cursor;\n\t\t\t}\n\t\t\tif (typeof options?.limit == 'number') {\n\t\t\t\tparams.limit = options.limit.toString();\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.api.get({ path: 'repos/commits', params }, jwt);\n\n\t\treturn (await response.json()) as ListCommitsResponse;\n\t}\n\n\tasync getBranchDiff(options: GetBranchDiffOptions): Promise<GetBranchDiffResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\tbranch: options.branch,\n\t\t};\n\n\t\tif (options.base) {\n\t\t\tparams.base = options.base;\n\t\t}\n\n\t\tconst response = await this.api.get({ path: 'repos/branches/diff', params }, jwt);\n\n\t\treturn (await response.json()) as GetBranchDiffResponse;\n\t}\n\n\tasync getCommitDiff(options: GetCommitDiffOptions): Promise<GetCommitDiffResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\tsha: options.sha,\n\t\t};\n\n\t\tconst response = await this.api.get({ path: 'repos/diff', params }, jwt);\n\n\t\treturn (await response.json()) as GetCommitDiffResponse;\n\t}\n\n\tasync getCommit(options: GetCommitOptions): Promise<GetCommitResponse> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst params: Record<string, string> = {\n\t\t\trepo: this.id,\n\t\t\tsha: options.sha,\n\t\t};\n\t\tconst response = await this.api.get({ path: 'commit', params }, jwt);\n\n\t\treturn (await response.json()) as GetCommitResponse;\n\t}\n\n\tasync pullUpstream(options: PullUpstreamOptions): Promise<void> {\n\t\tconst jwt = await this.generateJWT(this.id, {\n\t\t\tpermissions: ['git:write'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst body: Record<string, string> = {};\n\n\t\tif (options.ref) {\n\t\t\tbody.ref = options.ref;\n\t\t}\n\n\t\tconst response = await this.api.post({ path: 'repos/pull-upstream', body }, jwt);\n\n\t\tif (response.status !== 202) {\n\t\t\tthrow new Error(`Pull Upstream failed: ${response.status} ${await response.text()}`);\n\t\t}\n\n\t\treturn;\n\t}\n\n\tcreateCommit(options: CreateCommitOptions): CommitBuilder {\n\t\tconst version = this.options.apiVersion ?? API_VERSION;\n\t\tconst baseUrl = this.options.apiBaseUrl ?? API_BASE_URL;\n\t\tconst transport = new FetchCommitTransport({ baseUrl, version });\n\t\tconst ttlSeconds = resolveCommitTtlSeconds(options);\n\t\tconst builderOptions: CreateCommitOptions = { ...options, ttl: ttlSeconds };\n\t\tconst getAuthToken = () =>\n\t\t\tthis.generateJWT(this.id, {\n\t\t\t\tpermissions: ['git:write'],\n\t\t\t\tttl: ttlSeconds,\n\t\t\t});\n\n\t\treturn createCommitBuilder({\n\t\t\toptions: builderOptions,\n\t\t\tgetAuthToken,\n\t\t\ttransport,\n\t\t});\n\t}\n}\n\nexport class GitStorage {\n\tprivate static overrides: OverrideableGitStorageOptions = {};\n\tprivate options: GitStorageOptions;\n\tprivate api: ApiFetcher;\n\n\tconstructor(options: GitStorageOptions) {\n\t\tif (\n\t\t\t!options ||\n\t\t\toptions.name === undefined ||\n\t\t\toptions.key === undefined ||\n\t\t\toptions.name === null ||\n\t\t\toptions.key === null\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t'GitStorage requires a name and key. Please check your configuration and try again.',\n\t\t\t);\n\t\t}\n\n\t\tif (typeof options.name !== 'string' || options.name.trim() === '') {\n\t\t\tthrow new Error('GitStorage name must be a non-empty string.');\n\t\t}\n\n\t\tif (typeof options.key !== 'string' || options.key.trim() === '') {\n\t\t\tthrow new Error('GitStorage key must be a non-empty string.');\n\t\t}\n\n\t\tconst resolvedApiBaseUrl =\n\t\t\toptions.apiBaseUrl ?? GitStorage.overrides.apiBaseUrl ?? API_BASE_URL;\n\t\tconst resolvedApiVersion = options.apiVersion ?? GitStorage.overrides.apiVersion ?? API_VERSION;\n\t\tconst resolvedStorageBaseUrl =\n\t\t\toptions.storageBaseUrl ?? GitStorage.overrides.storageBaseUrl ?? STORAGE_BASE_URL;\n\n\t\tthis.api = getApiInstance(resolvedApiBaseUrl, resolvedApiVersion);\n\n\t\tthis.options = {\n\t\t\tkey: options.key,\n\t\t\tname: options.name,\n\t\t\tapiBaseUrl: resolvedApiBaseUrl,\n\t\t\tapiVersion: resolvedApiVersion,\n\t\t\tstorageBaseUrl: resolvedStorageBaseUrl,\n\t\t};\n\t}\n\n\tstatic override(options: OverrideableGitStorageOptions): void {\n\t\tthis.overrides = Object.assign({}, this.overrides, options);\n\t}\n\n\t/**\n\t * Create a new repository\n\t * @returns The created repository\n\t */\n\tasync createRepo(options?: CreateRepoOptions): Promise<Repo> {\n\t\tconst repoId = options?.id || crypto.randomUUID();\n\n\t\tconst jwt = await this.generateJWT(repoId, {\n\t\t\tpermissions: ['repo:write'],\n\t\t\tttl: options?.ttl ?? 1 * 60 * 60, // 1hr in seconds\n\t\t});\n\n\t\tconst baseRepoOptions = options?.baseRepo\n\t\t\t? {\n\t\t\t\t\tprovider: 'github',\n\t\t\t\t\t...snakecaseKeys(options.baseRepo as unknown as Record<string, unknown>),\n\t\t\t\t}\n\t\t\t: null;\n\n\t\t// Default defaultBranch to 'main' if not provided\n\t\tconst defaultBranch = options?.defaultBranch ?? 'main';\n\n\t\tconst createRepoPath =\n\t\t\tbaseRepoOptions || defaultBranch\n\t\t\t\t? {\n\t\t\t\t\t\tpath: 'repos',\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t...(baseRepoOptions && { base_repo: baseRepoOptions }),\n\t\t\t\t\t\t\tdefault_branch: defaultBranch,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: 'repos';\n\n\t\t// Allow 409 so we can map it to a clearer error message\n\t\tconst resp = await this.api.post(createRepoPath, jwt, { allowedStatus: [409] });\n\t\tif (resp.status === 409) {\n\t\t\tthrow new Error('Repository already exists');\n\t\t}\n\n\t\treturn new RepoImpl(repoId, this.options, this.generateJWT.bind(this));\n\t}\n\n\t/**\n\t * Find a repository by ID\n\t * @param options The search options\n\t * @returns The found repository\n\t */\n\tasync findOne(options: FindOneOptions): Promise<Repo | null> {\n\t\tconst jwt = await this.generateJWT(options.id, {\n\t\t\tpermissions: ['git:read'],\n\t\t\tttl: 1 * 60 * 60,\n\t\t});\n\n\t\t// Allow 404 to indicate \"not found\" without throwing\n\t\tconst resp = await this.api.get('repo', jwt, { allowedStatus: [404] });\n\t\tif (resp.status === 404) {\n\t\t\treturn null;\n\t\t}\n\t\t// On 200, we could validate response, but RepoImpl only needs the repo URL/id\n\t\t// const body = await resp.json(); // not required for now\n\t\treturn new RepoImpl(options.id, this.options, this.generateJWT.bind(this));\n\t}\n\n\t/**\n\t * Get the current configuration\n\t * @returns The client configuration\n\t */\n\tgetConfig(): GitStorageOptions {\n\t\treturn { ...this.options };\n\t}\n\n\t/**\n\t * Generate a JWT token for git storage URL authentication\n\t * @private\n\t */\n\tprivate async generateJWT(repoId: string, options?: GetRemoteURLOptions): Promise<string> {\n\t\t// Default permissions and TTL\n\t\tconst permissions = options?.permissions || ['git:write', 'git:read'];\n\t\tconst ttl = options?.ttl || 365 * 24 * 60 * 60; // 1 year in seconds\n\n\t\t// Create the JWT payload\n\t\tconst now = Math.floor(Date.now() / 1000);\n\t\tconst payload = {\n\t\t\tiss: this.options.name,\n\t\t\tsub: '@pierre/storage',\n\t\t\trepo: repoId,\n\t\t\tscopes: permissions,\n\t\t\tiat: now,\n\t\t\texp: now + ttl,\n\t\t};\n\n\t\t// Sign the JWT with the key as the secret\n\t\t// Using HS256 for symmetric signing with the key\n\t\tconst key = await importPKCS8(this.options.key, 'ES256');\n\t\t// Sign the JWT with the key as the secret\n\t\tconst jwt = await new SignJWT(payload)\n\t\t\t.setProtectedHeader({ alg: 'ES256', typ: 'JWT' })\n\t\t\t.sign(key);\n\n\t\treturn jwt;\n\t}\n}\n\n// Export a default client factory\nexport function createClient(options: GitStorageOptions): GitStorage {\n\treturn new GitStorage(options);\n}\n\n// Type alias for backward compatibility\nexport type StorageOptions = GitStorageOptions;\n"]}