@pierre/storage 1.2.1 → 1.3.2
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 +18 -1
- package/dist/index.cjs +92 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -4
- package/dist/index.d.ts +52 -4
- package/dist/index.js +92 -4
- package/dist/index.js.map +1 -1
- package/package.json +43 -43
- package/src/index.ts +113 -3
- package/src/types.ts +50 -3
package/package.json
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
2
|
+
"name": "@pierre/storage",
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "Pierre Git Storage SDK",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/pierrecomputer/sdk"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.cjs",
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"require": "./dist/index.cjs",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"prepublishOnly": "pnpm build"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"jose": "^5.10.0",
|
|
33
|
+
"snakecase-keys": "^9.0.2",
|
|
34
|
+
"zod": "^3.23.8"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.0.0",
|
|
38
|
+
"tsup": "8.5.0",
|
|
39
|
+
"typescript": "5.8.3",
|
|
40
|
+
"vitest": "3.2.4"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
45
|
}
|
package/src/index.ts
CHANGED
|
@@ -44,8 +44,10 @@ import type {
|
|
|
44
44
|
CreateBranchResult,
|
|
45
45
|
CreateCommitFromDiffOptions,
|
|
46
46
|
CreateCommitOptions,
|
|
47
|
+
CreateGitCredentialOptions,
|
|
47
48
|
CreateNoteOptions,
|
|
48
49
|
CreateRepoOptions,
|
|
50
|
+
DeleteGitCredentialOptions,
|
|
49
51
|
DeleteNoteOptions,
|
|
50
52
|
DeleteRepoOptions,
|
|
51
53
|
DeleteRepoResult,
|
|
@@ -54,6 +56,7 @@ import type {
|
|
|
54
56
|
FileDiff,
|
|
55
57
|
FilteredFile,
|
|
56
58
|
FindOneOptions,
|
|
59
|
+
GenericGitBaseRepo,
|
|
57
60
|
GetBranchDiffOptions,
|
|
58
61
|
GetBranchDiffResponse,
|
|
59
62
|
GetBranchDiffResult,
|
|
@@ -64,6 +67,8 @@ import type {
|
|
|
64
67
|
GetNoteOptions,
|
|
65
68
|
GetNoteResult,
|
|
66
69
|
GetRemoteURLOptions,
|
|
70
|
+
GitCredential,
|
|
71
|
+
GitHubBaseRepo,
|
|
67
72
|
GitStorageOptions,
|
|
68
73
|
GrepFileMatch,
|
|
69
74
|
GrepLine,
|
|
@@ -96,6 +101,7 @@ import type {
|
|
|
96
101
|
Repo,
|
|
97
102
|
RestoreCommitOptions,
|
|
98
103
|
RestoreCommitResult,
|
|
104
|
+
UpdateGitCredentialOptions,
|
|
99
105
|
ValidAPIVersion,
|
|
100
106
|
} from './types';
|
|
101
107
|
|
|
@@ -635,6 +641,15 @@ class RepoImpl implements Repo {
|
|
|
635
641
|
return url.toString();
|
|
636
642
|
}
|
|
637
643
|
|
|
644
|
+
async getImportRemoteURL(urlOptions?: GetRemoteURLOptions): Promise<string> {
|
|
645
|
+
const url = new URL(
|
|
646
|
+
`https://${this.options.storageBaseUrl}/${this.id}+import.git`
|
|
647
|
+
);
|
|
648
|
+
url.username = `t`;
|
|
649
|
+
url.password = await this.generateJWT(this.id, urlOptions);
|
|
650
|
+
return url.toString();
|
|
651
|
+
}
|
|
652
|
+
|
|
638
653
|
async getFileStream(options: GetFileOptions): Promise<Response> {
|
|
639
654
|
const ttl = resolveInvocationTtlSeconds(options, DEFAULT_TOKEN_TTL_SECONDS);
|
|
640
655
|
const jwt = await this.generateJWT(this.id, {
|
|
@@ -1428,11 +1443,16 @@ export class GitStorage {
|
|
|
1428
1443
|
...(baseRepo.sha ? { sha: baseRepo.sha } : {}),
|
|
1429
1444
|
};
|
|
1430
1445
|
} else {
|
|
1446
|
+
// Sync base repo: GitHub or generic git provider (gitlab, bitbucket, etc.)
|
|
1447
|
+
const syncRepo = baseRepo as GitHubBaseRepo | GenericGitBaseRepo;
|
|
1448
|
+
const { provider: _p, ...restSnakecased } = snakecaseKeys(
|
|
1449
|
+
baseRepo as unknown as Record<string, unknown>
|
|
1450
|
+
) as Record<string, unknown>;
|
|
1431
1451
|
baseRepoOptions = {
|
|
1432
|
-
provider: 'github',
|
|
1433
|
-
...
|
|
1452
|
+
provider: syncRepo.provider ?? 'github',
|
|
1453
|
+
...restSnakecased,
|
|
1434
1454
|
};
|
|
1435
|
-
resolvedDefaultBranch =
|
|
1455
|
+
resolvedDefaultBranch = syncRepo.defaultBranch;
|
|
1436
1456
|
}
|
|
1437
1457
|
}
|
|
1438
1458
|
|
|
@@ -1581,6 +1601,96 @@ export class GitStorage {
|
|
|
1581
1601
|
};
|
|
1582
1602
|
}
|
|
1583
1603
|
|
|
1604
|
+
/**
|
|
1605
|
+
* Create a generic git credential for a repository.
|
|
1606
|
+
* Used to authenticate sync operations for non-GitHub providers (GitLab, Bitbucket, etc.)
|
|
1607
|
+
*/
|
|
1608
|
+
async createGitCredential(
|
|
1609
|
+
options: CreateGitCredentialOptions
|
|
1610
|
+
): Promise<GitCredential> {
|
|
1611
|
+
const ttl = resolveInvocationTtlSeconds(options, DEFAULT_TOKEN_TTL_SECONDS);
|
|
1612
|
+
const jwt = await this.generateJWT(options.repoId, {
|
|
1613
|
+
permissions: ['repo:write'],
|
|
1614
|
+
ttl,
|
|
1615
|
+
});
|
|
1616
|
+
|
|
1617
|
+
const body: Record<string, unknown> = {
|
|
1618
|
+
repo_id: options.repoId,
|
|
1619
|
+
password: options.password,
|
|
1620
|
+
};
|
|
1621
|
+
if (options.username !== undefined) {
|
|
1622
|
+
body.username = options.username;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
const resp = await this.api.post(
|
|
1626
|
+
{ path: 'repos/git-credentials', body },
|
|
1627
|
+
jwt,
|
|
1628
|
+
{ allowedStatus: [409] }
|
|
1629
|
+
);
|
|
1630
|
+
if (resp.status === 409) {
|
|
1631
|
+
throw new Error('A credential already exists for this repository');
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
const data = (await resp.json()) as { id: string };
|
|
1635
|
+
return { id: data.id };
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/**
|
|
1639
|
+
* Update an existing generic git credential.
|
|
1640
|
+
*/
|
|
1641
|
+
async updateGitCredential(
|
|
1642
|
+
options: UpdateGitCredentialOptions
|
|
1643
|
+
): Promise<GitCredential> {
|
|
1644
|
+
const ttl = resolveInvocationTtlSeconds(options, DEFAULT_TOKEN_TTL_SECONDS);
|
|
1645
|
+
const jwt = await this.generateJWT('org', {
|
|
1646
|
+
permissions: ['repo:write'],
|
|
1647
|
+
ttl,
|
|
1648
|
+
});
|
|
1649
|
+
|
|
1650
|
+
const body: Record<string, unknown> = {
|
|
1651
|
+
id: options.id,
|
|
1652
|
+
password: options.password,
|
|
1653
|
+
};
|
|
1654
|
+
if (options.username !== undefined) {
|
|
1655
|
+
body.username = options.username;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
const resp = await this.api.put(
|
|
1659
|
+
{ path: 'repos/git-credentials', body },
|
|
1660
|
+
jwt,
|
|
1661
|
+
{ allowedStatus: [404] }
|
|
1662
|
+
);
|
|
1663
|
+
if (resp.status === 404) {
|
|
1664
|
+
throw new Error('Credential not found');
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
const data = (await resp.json()) as { id: string; created_at?: string };
|
|
1668
|
+
return {
|
|
1669
|
+
id: data.id,
|
|
1670
|
+
...(data.created_at ? { createdAt: data.created_at } : {}),
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
/**
|
|
1675
|
+
* Delete a generic git credential.
|
|
1676
|
+
*/
|
|
1677
|
+
async deleteGitCredential(options: DeleteGitCredentialOptions): Promise<void> {
|
|
1678
|
+
const ttl = resolveInvocationTtlSeconds(options, DEFAULT_TOKEN_TTL_SECONDS);
|
|
1679
|
+
const jwt = await this.generateJWT('org', {
|
|
1680
|
+
permissions: ['repo:write'],
|
|
1681
|
+
ttl,
|
|
1682
|
+
});
|
|
1683
|
+
|
|
1684
|
+
const resp = await this.api.delete(
|
|
1685
|
+
{ path: 'repos/git-credentials', body: { id: options.id } },
|
|
1686
|
+
jwt,
|
|
1687
|
+
{ allowedStatus: [404] }
|
|
1688
|
+
);
|
|
1689
|
+
if (resp.status === 404) {
|
|
1690
|
+
throw new Error('Credential not found');
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1584
1694
|
/**
|
|
1585
1695
|
* Get the current configuration
|
|
1586
1696
|
* @returns The client configuration
|
package/src/types.ts
CHANGED
|
@@ -48,6 +48,7 @@ export interface Repo {
|
|
|
48
48
|
createdAt: string;
|
|
49
49
|
getRemoteURL(options?: GetRemoteURLOptions): Promise<string>;
|
|
50
50
|
getEphemeralRemoteURL(options?: GetRemoteURLOptions): Promise<string>;
|
|
51
|
+
getImportRemoteURL(options?: GetRemoteURLOptions): Promise<string>;
|
|
51
52
|
|
|
52
53
|
getFileStream(options: GetFileOptions): Promise<Response>;
|
|
53
54
|
getArchiveStream(options?: ArchiveOptions): Promise<Response>;
|
|
@@ -96,7 +97,14 @@ export interface RepoOptions {
|
|
|
96
97
|
createdAt?: string;
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
export type SupportedRepoProvider =
|
|
100
|
+
export type SupportedRepoProvider =
|
|
101
|
+
| 'github'
|
|
102
|
+
| 'gitlab'
|
|
103
|
+
| 'bitbucket'
|
|
104
|
+
| 'gitea'
|
|
105
|
+
| 'forgejo'
|
|
106
|
+
| 'codeberg'
|
|
107
|
+
| 'sr.ht';
|
|
100
108
|
|
|
101
109
|
export interface PublicGitHubBaseRepoAuth {
|
|
102
110
|
/**
|
|
@@ -109,20 +117,59 @@ export interface GitHubBaseRepo {
|
|
|
109
117
|
/**
|
|
110
118
|
* @default github
|
|
111
119
|
*/
|
|
112
|
-
provider?:
|
|
120
|
+
provider?: 'github';
|
|
113
121
|
owner: string;
|
|
114
122
|
name: string;
|
|
115
123
|
defaultBranch?: string;
|
|
116
124
|
auth?: PublicGitHubBaseRepoAuth;
|
|
117
125
|
}
|
|
118
126
|
|
|
127
|
+
export interface GenericGitBaseRepo {
|
|
128
|
+
/**
|
|
129
|
+
* The git host provider. Must be one of the supported generic git providers.
|
|
130
|
+
*/
|
|
131
|
+
provider: Exclude<SupportedRepoProvider, 'github'>;
|
|
132
|
+
owner: string;
|
|
133
|
+
name: string;
|
|
134
|
+
defaultBranch?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Bare hostname for self-hosted instances (e.g. "gitlab.example.com").
|
|
137
|
+
* Falls back to the provider's default host when omitted.
|
|
138
|
+
*/
|
|
139
|
+
upstreamHost?: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
119
142
|
export interface ForkBaseRepo {
|
|
120
143
|
id: string;
|
|
121
144
|
ref?: string;
|
|
122
145
|
sha?: string;
|
|
123
146
|
}
|
|
124
147
|
|
|
125
|
-
export type BaseRepo = GitHubBaseRepo | ForkBaseRepo;
|
|
148
|
+
export type BaseRepo = GitHubBaseRepo | ForkBaseRepo | GenericGitBaseRepo;
|
|
149
|
+
|
|
150
|
+
export interface CreateGitCredentialOptions {
|
|
151
|
+
repoId: string;
|
|
152
|
+
username?: string;
|
|
153
|
+
password: string;
|
|
154
|
+
ttl?: number;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface UpdateGitCredentialOptions {
|
|
158
|
+
id: string;
|
|
159
|
+
username?: string;
|
|
160
|
+
password: string;
|
|
161
|
+
ttl?: number;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface DeleteGitCredentialOptions {
|
|
165
|
+
id: string;
|
|
166
|
+
ttl?: number;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface GitCredential {
|
|
170
|
+
id: string;
|
|
171
|
+
createdAt?: string;
|
|
172
|
+
}
|
|
126
173
|
|
|
127
174
|
export interface ListReposOptions extends GitStorageInvocationOptions {
|
|
128
175
|
cursor?: string;
|