@pierre/storage 1.2.2 → 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/package.json CHANGED
@@ -1,45 +1,45 @@
1
1
  {
2
- "name": "@pierre/storage",
3
- "version": "1.2.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
- }
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
 
@@ -1437,11 +1443,16 @@ export class GitStorage {
1437
1443
  ...(baseRepo.sha ? { sha: baseRepo.sha } : {}),
1438
1444
  };
1439
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>;
1440
1451
  baseRepoOptions = {
1441
- provider: 'github',
1442
- ...snakecaseKeys(baseRepo as unknown as Record<string, unknown>),
1452
+ provider: syncRepo.provider ?? 'github',
1453
+ ...restSnakecased,
1443
1454
  };
1444
- resolvedDefaultBranch = baseRepo.defaultBranch;
1455
+ resolvedDefaultBranch = syncRepo.defaultBranch;
1445
1456
  }
1446
1457
  }
1447
1458
 
@@ -1590,6 +1601,96 @@ export class GitStorage {
1590
1601
  };
1591
1602
  }
1592
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
+
1593
1694
  /**
1594
1695
  * Get the current configuration
1595
1696
  * @returns The client configuration
package/src/types.ts CHANGED
@@ -97,7 +97,14 @@ export interface RepoOptions {
97
97
  createdAt?: string;
98
98
  }
99
99
 
100
- export type SupportedRepoProvider = 'github';
100
+ export type SupportedRepoProvider =
101
+ | 'github'
102
+ | 'gitlab'
103
+ | 'bitbucket'
104
+ | 'gitea'
105
+ | 'forgejo'
106
+ | 'codeberg'
107
+ | 'sr.ht';
101
108
 
102
109
  export interface PublicGitHubBaseRepoAuth {
103
110
  /**
@@ -110,20 +117,59 @@ export interface GitHubBaseRepo {
110
117
  /**
111
118
  * @default github
112
119
  */
113
- provider?: SupportedRepoProvider;
120
+ provider?: 'github';
114
121
  owner: string;
115
122
  name: string;
116
123
  defaultBranch?: string;
117
124
  auth?: PublicGitHubBaseRepoAuth;
118
125
  }
119
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
+
120
142
  export interface ForkBaseRepo {
121
143
  id: string;
122
144
  ref?: string;
123
145
  sha?: string;
124
146
  }
125
147
 
126
- 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
+ }
127
173
 
128
174
  export interface ListReposOptions extends GitStorageInvocationOptions {
129
175
  cursor?: string;