@pierre/storage 0.1.2 → 0.1.3
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/README.md +22 -15
- package/dist/index.cjs +72 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +72 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commit.ts +93 -10
- package/src/types.ts +17 -2
package/README.md
CHANGED
|
@@ -133,7 +133,7 @@ console.log(commitDiff.files);
|
|
|
133
133
|
const fs = await import('node:fs/promises');
|
|
134
134
|
const result = await repo
|
|
135
135
|
.createCommit({
|
|
136
|
-
|
|
136
|
+
targetBranch: 'main',
|
|
137
137
|
commitMessage: 'Update docs',
|
|
138
138
|
author: { name: 'Docs Bot', email: 'docs@example.com' },
|
|
139
139
|
})
|
|
@@ -162,37 +162,44 @@ The builder exposes:
|
|
|
162
162
|
type CommitResult = {
|
|
163
163
|
commitSha: string;
|
|
164
164
|
treeSha: string;
|
|
165
|
-
|
|
165
|
+
targetBranch: string;
|
|
166
166
|
packBytes: number;
|
|
167
167
|
blobCount: number;
|
|
168
168
|
refUpdate: {
|
|
169
|
-
|
|
169
|
+
branch: string;
|
|
170
170
|
oldSha: string; // All zeroes when the ref is created
|
|
171
171
|
newSha: string;
|
|
172
172
|
};
|
|
173
173
|
};
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
-
If the backend reports a failure (for example, the branch advanced past `
|
|
177
|
-
throws a `RefUpdateError` containing the status, reason, and ref details.
|
|
176
|
+
If the backend reports a failure (for example, the branch advanced past `expectedHeadSha`) the
|
|
177
|
+
builder throws a `RefUpdateError` containing the status, reason, and ref details.
|
|
178
178
|
|
|
179
179
|
**Options**
|
|
180
180
|
|
|
181
|
-
- `
|
|
182
|
-
|
|
183
|
-
- `baseRef` (optional): Branch or commit that must match the remote tip; omit to fast-forward
|
|
181
|
+
- `targetBranch` (required): Branch name (for example `main`) that will receive the commit.
|
|
182
|
+
- `expectedHeadSha` (optional): Commit SHA that must match the remote tip; omit to fast-forward
|
|
184
183
|
unconditionally.
|
|
184
|
+
- `baseBranch` (optional): Mirrors the `base_branch` metadata and names an existing branch whose tip
|
|
185
|
+
should seed `targetBranch` if it does not exist. Leave `expectedHeadSha` empty when creating a new
|
|
186
|
+
branch from `baseBranch`; when both are provided and the branch already exists, `expectedHeadSha`
|
|
187
|
+
continues to enforce the fast-forward guard.
|
|
185
188
|
- `commitMessage` (required): The commit message.
|
|
186
189
|
- `author` (required): Include `name` and `email` for the commit author.
|
|
187
190
|
- `committer` (optional): Include `name` and `email`. If omitted, the author identity is reused.
|
|
188
191
|
- `signal` (optional): Abort an in-flight upload with `AbortController`.
|
|
192
|
+
- `targetRef` (deprecated, optional): Fully qualified ref (for example `refs/heads/main`). Prefer
|
|
193
|
+
`targetBranch`, which now accepts plain branch names.
|
|
189
194
|
|
|
190
195
|
> Files are chunked into 4 MiB segments under the hood, so you can stream large assets without
|
|
191
196
|
> buffering them entirely in memory. File paths are normalized relative to the repository root.
|
|
192
197
|
|
|
193
|
-
> The `
|
|
194
|
-
> the
|
|
195
|
-
>
|
|
198
|
+
> The `targetBranch` must already exist on the remote repository unless you provide `baseBranch` (or
|
|
199
|
+
> the repository has no refs). To seed an empty repository, point to the default branch and omit
|
|
200
|
+
> `expectedHeadSha`. To create a missing branch within an existing repository, set `baseBranch` to
|
|
201
|
+
> the source branch and omit `expectedHeadSha` so the service clones that tip before applying your
|
|
202
|
+
> changes.
|
|
196
203
|
|
|
197
204
|
### Streaming Large Files
|
|
198
205
|
|
|
@@ -204,8 +211,8 @@ import { createReadStream } from 'node:fs';
|
|
|
204
211
|
|
|
205
212
|
await repo
|
|
206
213
|
.createCommit({
|
|
207
|
-
|
|
208
|
-
|
|
214
|
+
targetBranch: 'assets',
|
|
215
|
+
expectedHeadSha: 'abc123def4567890abc123def4567890abc12345',
|
|
209
216
|
commitMessage: 'Upload latest design bundle',
|
|
210
217
|
author: { name: 'Assets Uploader', email: 'assets@example.com' },
|
|
211
218
|
})
|
|
@@ -425,7 +432,7 @@ interface FilteredFile {
|
|
|
425
432
|
}
|
|
426
433
|
|
|
427
434
|
interface RefUpdate {
|
|
428
|
-
|
|
435
|
+
branch: string;
|
|
429
436
|
oldSha: string;
|
|
430
437
|
newSha: string;
|
|
431
438
|
}
|
|
@@ -433,7 +440,7 @@ interface RefUpdate {
|
|
|
433
440
|
interface CommitResult {
|
|
434
441
|
commitSha: string;
|
|
435
442
|
treeSha: string;
|
|
436
|
-
|
|
443
|
+
targetBranch: string;
|
|
437
444
|
packBytes: number;
|
|
438
445
|
blobCount: number;
|
|
439
446
|
refUpdate: RefUpdate;
|
package/dist/index.cjs
CHANGED
|
@@ -157,6 +157,7 @@ var errorEnvelopeSchema = zod.z.object({
|
|
|
157
157
|
// src/commit.ts
|
|
158
158
|
var MAX_CHUNK_BYTES = 4 * 1024 * 1024;
|
|
159
159
|
var DEFAULT_TTL_SECONDS = 60 * 60;
|
|
160
|
+
var HEADS_REF_PREFIX = "refs/heads/";
|
|
160
161
|
var BufferCtor = globalThis.Buffer;
|
|
161
162
|
var CommitBuilderImpl = class {
|
|
162
163
|
options;
|
|
@@ -165,26 +166,18 @@ var CommitBuilderImpl = class {
|
|
|
165
166
|
operations = [];
|
|
166
167
|
sent = false;
|
|
167
168
|
constructor(deps) {
|
|
168
|
-
this.options =
|
|
169
|
+
this.options = normalizeCommitOptions(deps.options);
|
|
169
170
|
this.getAuthToken = deps.getAuthToken;
|
|
170
171
|
this.transport = deps.transport;
|
|
171
|
-
const trimmedTarget = this.options.targetBranch?.trim();
|
|
172
172
|
const trimmedMessage = this.options.commitMessage?.trim();
|
|
173
173
|
const trimmedAuthorName = this.options.author?.name?.trim();
|
|
174
174
|
const trimmedAuthorEmail = this.options.author?.email?.trim();
|
|
175
|
-
if (!trimmedTarget) {
|
|
176
|
-
throw new Error("createCommit targetBranch is required");
|
|
177
|
-
}
|
|
178
|
-
if (trimmedTarget.startsWith("refs/")) {
|
|
179
|
-
throw new Error("createCommit targetBranch must not include refs/ prefix");
|
|
180
|
-
}
|
|
181
175
|
if (!trimmedMessage) {
|
|
182
176
|
throw new Error("createCommit commitMessage is required");
|
|
183
177
|
}
|
|
184
178
|
if (!trimmedAuthorName || !trimmedAuthorEmail) {
|
|
185
179
|
throw new Error("createCommit author name and email are required");
|
|
186
180
|
}
|
|
187
|
-
this.options.targetBranch = trimmedTarget;
|
|
188
181
|
this.options.commitMessage = trimmedMessage;
|
|
189
182
|
this.options.author = {
|
|
190
183
|
name: trimmedAuthorName,
|
|
@@ -193,6 +186,17 @@ var CommitBuilderImpl = class {
|
|
|
193
186
|
if (typeof this.options.expectedHeadSha === "string") {
|
|
194
187
|
this.options.expectedHeadSha = this.options.expectedHeadSha.trim();
|
|
195
188
|
}
|
|
189
|
+
if (typeof this.options.baseBranch === "string") {
|
|
190
|
+
const trimmedBase = this.options.baseBranch.trim();
|
|
191
|
+
if (trimmedBase === "") {
|
|
192
|
+
delete this.options.baseBranch;
|
|
193
|
+
} else {
|
|
194
|
+
if (trimmedBase.startsWith("refs/")) {
|
|
195
|
+
throw new Error("createCommit baseBranch must not include refs/ prefix");
|
|
196
|
+
}
|
|
197
|
+
this.options.baseBranch = trimmedBase;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
196
200
|
}
|
|
197
201
|
addFile(path, source, options) {
|
|
198
202
|
this.ensureNotSent();
|
|
@@ -277,6 +281,9 @@ var CommitBuilderImpl = class {
|
|
|
277
281
|
if (this.options.expectedHeadSha) {
|
|
278
282
|
metadata.expected_head_sha = this.options.expectedHeadSha;
|
|
279
283
|
}
|
|
284
|
+
if (this.options.baseBranch) {
|
|
285
|
+
metadata.base_branch = this.options.baseBranch;
|
|
286
|
+
}
|
|
280
287
|
if (this.options.committer) {
|
|
281
288
|
metadata.committer = {
|
|
282
289
|
name: this.options.committer.name,
|
|
@@ -557,6 +564,62 @@ function randomContentId() {
|
|
|
557
564
|
const random = Math.random().toString(36).slice(2);
|
|
558
565
|
return `cid-${Date.now().toString(36)}-${random}`;
|
|
559
566
|
}
|
|
567
|
+
function normalizeCommitOptions(options) {
|
|
568
|
+
return {
|
|
569
|
+
targetBranch: resolveTargetBranch(options),
|
|
570
|
+
commitMessage: options.commitMessage,
|
|
571
|
+
expectedHeadSha: options.expectedHeadSha,
|
|
572
|
+
baseBranch: options.baseBranch,
|
|
573
|
+
author: options.author,
|
|
574
|
+
committer: options.committer,
|
|
575
|
+
signal: options.signal,
|
|
576
|
+
ttl: options.ttl
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function resolveTargetBranch(options) {
|
|
580
|
+
const branchCandidate = typeof options.targetBranch === "string" ? options.targetBranch.trim() : "";
|
|
581
|
+
if (branchCandidate) {
|
|
582
|
+
return normalizeBranchName(branchCandidate);
|
|
583
|
+
}
|
|
584
|
+
if (hasLegacyTargetRef(options)) {
|
|
585
|
+
return normalizeLegacyTargetRef(options.targetRef);
|
|
586
|
+
}
|
|
587
|
+
throw new Error("createCommit targetBranch is required");
|
|
588
|
+
}
|
|
589
|
+
function normalizeBranchName(value) {
|
|
590
|
+
const trimmed = value.trim();
|
|
591
|
+
if (!trimmed) {
|
|
592
|
+
throw new Error("createCommit targetBranch is required");
|
|
593
|
+
}
|
|
594
|
+
if (trimmed.startsWith(HEADS_REF_PREFIX)) {
|
|
595
|
+
const branch = trimmed.slice(HEADS_REF_PREFIX.length).trim();
|
|
596
|
+
if (!branch) {
|
|
597
|
+
throw new Error("createCommit targetBranch is required");
|
|
598
|
+
}
|
|
599
|
+
return branch;
|
|
600
|
+
}
|
|
601
|
+
if (trimmed.startsWith("refs/")) {
|
|
602
|
+
throw new Error("createCommit targetBranch must not include refs/ prefix");
|
|
603
|
+
}
|
|
604
|
+
return trimmed;
|
|
605
|
+
}
|
|
606
|
+
function normalizeLegacyTargetRef(ref) {
|
|
607
|
+
const trimmed = ref.trim();
|
|
608
|
+
if (!trimmed) {
|
|
609
|
+
throw new Error("createCommit targetRef is required");
|
|
610
|
+
}
|
|
611
|
+
if (!trimmed.startsWith(HEADS_REF_PREFIX)) {
|
|
612
|
+
throw new Error("createCommit targetRef must start with refs/heads/");
|
|
613
|
+
}
|
|
614
|
+
const branch = trimmed.slice(HEADS_REF_PREFIX.length).trim();
|
|
615
|
+
if (!branch) {
|
|
616
|
+
throw new Error("createCommit targetRef must include a branch name");
|
|
617
|
+
}
|
|
618
|
+
return branch;
|
|
619
|
+
}
|
|
620
|
+
function hasLegacyTargetRef(options) {
|
|
621
|
+
return typeof options.targetRef === "string";
|
|
622
|
+
}
|
|
560
623
|
function createCommitBuilder(deps) {
|
|
561
624
|
return new CommitBuilderImpl(deps);
|
|
562
625
|
}
|