@pierre/vercel-code-storage 0.1.0
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/LICENSE +21 -0
- package/README.md +128 -0
- package/dist/index.d.ts +191 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +421 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The Pierre Computer Company
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# @pierre/vercel-code-storage
|
|
2
|
+
|
|
3
|
+
`@pierre/vercel-code-storage` let you deploy [code.storage](https://code.storage/) to Vercel. Made with love by
|
|
4
|
+
[The Pierre Computer Company](https://pierre.computer).
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
bun i @pierre/vercel-code-storage
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { VercelCodeStorage } from '@pierre/vercel-code-storage';
|
|
14
|
+
|
|
15
|
+
const store = new VercelCodeStorage({
|
|
16
|
+
codeStorage: {
|
|
17
|
+
name: process.env.ORG_NAME!,
|
|
18
|
+
key: process.env.PIERRE_PRIVATE_KEY!,
|
|
19
|
+
},
|
|
20
|
+
vercel: {
|
|
21
|
+
token: process.env.VERCEL_TOKEN!,
|
|
22
|
+
teamId: process.env.VERCEL_TEAM_ID,
|
|
23
|
+
projectName: 'my-vercel-project',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const repo = await store.findOne('my-repo');
|
|
28
|
+
if (!repo) throw new Error('repo not found');
|
|
29
|
+
|
|
30
|
+
const previewUrl = await repo.getPreviewUrl();
|
|
31
|
+
const publicUrl = await repo.getPublicUrl();
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`getPreviewUrl()` creates a Vercel preview deployment. `getPublicUrl()` creates
|
|
35
|
+
a production deployment and returns the production alias when Vercel assigns
|
|
36
|
+
one; otherwise it returns the generated deployment URL.
|
|
37
|
+
|
|
38
|
+
## Configuration
|
|
39
|
+
|
|
40
|
+
Required environment variables:
|
|
41
|
+
|
|
42
|
+
- `ORG_NAME`: code.storage organization name.
|
|
43
|
+
- `PIERRE_PRIVATE_KEY`: code.storage private key.
|
|
44
|
+
- `VERCEL_TOKEN`: Vercel API token.
|
|
45
|
+
|
|
46
|
+
Optional environment variables:
|
|
47
|
+
|
|
48
|
+
- `VERCEL_TEAM_ID`: Vercel team scope.
|
|
49
|
+
- `VERCEL_PROJECT_NAME`: Vercel project name override.
|
|
50
|
+
- `VERCEL_ROOT_DIRECTORY`: app root within the archived repo.
|
|
51
|
+
|
|
52
|
+
## Quick Run
|
|
53
|
+
|
|
54
|
+
Before run, makesure to preset required environment variable. Deploy an existing code.storage repo to Vercel preview or production:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
# if want preview deployment
|
|
58
|
+
bun examples/deploy-preview.ts my-code-storage-repo
|
|
59
|
+
# if want production deployment
|
|
60
|
+
bun examples/deploy-production.ts my-code-storage-repo
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## API
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const store = new VercelCodeStorage({
|
|
67
|
+
codeStorage: storageOptionsOrExistingGitStorage,
|
|
68
|
+
vercel: {
|
|
69
|
+
token: process.env.VERCEL_TOKEN!,
|
|
70
|
+
teamId: process.env.VERCEL_TEAM_ID,
|
|
71
|
+
projectName: 'my-project',
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const repo = await store.findOne('my-repo');
|
|
76
|
+
const url = await repo.getPreviewUrl({
|
|
77
|
+
// App root inside the code.storage archive.
|
|
78
|
+
rootDirectory: 'new-repo/here',
|
|
79
|
+
|
|
80
|
+
// Vercel project settings. Use this for framework/build/output settings when
|
|
81
|
+
// you want to send them in the deployment payload instead of relying only on
|
|
82
|
+
// a vercel.json file in rootDirectory.
|
|
83
|
+
projectSettings: {
|
|
84
|
+
framework: 'vite',
|
|
85
|
+
buildCommand: 'npm run build',
|
|
86
|
+
outputDirectory: 'dist',
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
// Deployment env forwarded to Vercel for this deployment.
|
|
90
|
+
env: {
|
|
91
|
+
VITE_DEPLOYED_FROM: 'code-storage',
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
// New Vercel projects can opt into framework auto-detection explicitly.
|
|
95
|
+
skipAutoDetectionConfirmation: true,
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Vercel also reads `vercel.json` from the selected `rootDirectory` when that file
|
|
100
|
+
exists in the archived repo.
|
|
101
|
+
|
|
102
|
+
Deployment options include:
|
|
103
|
+
|
|
104
|
+
- `ref`: branch, tag, or commit SHA to archive from code.storage.
|
|
105
|
+
- `target`: `preview`, `production`, or another Vercel target.
|
|
106
|
+
- `projectName`: per-deploy Vercel project name override.
|
|
107
|
+
- `rootDirectory`: app root within the archived repo; this becomes the Vercel
|
|
108
|
+
deployment path.
|
|
109
|
+
- `projectSettings`: explicit Vercel project settings for new projects.
|
|
110
|
+
- `env`, `build`: Vercel deployment environment/build payloads.
|
|
111
|
+
- `skipAutoDetectionConfirmation`: forwarded to `@vercel/client`; set `true` to
|
|
112
|
+
opt into automatic framework detection for new projects.
|
|
113
|
+
- `includeGlobs`, `excludeGlobs`, `maxBlobSize`: forwarded to code.storage
|
|
114
|
+
archive creation.
|
|
115
|
+
- `wait`: set `false` to return after Vercel creates the deployment.
|
|
116
|
+
- `meta`: extra Vercel deployment metadata.
|
|
117
|
+
|
|
118
|
+
The original code.storage `Repo` is available as `repo.storage`.
|
|
119
|
+
|
|
120
|
+
Pass a valid `projectName` when creating a new Vercel project. If it is omitted,
|
|
121
|
+
`@vercel/client` may derive the project name from the temporary deployment path,
|
|
122
|
+
and Vercel will validate that derived name.
|
|
123
|
+
|
|
124
|
+
## Bun And Vercel
|
|
125
|
+
|
|
126
|
+
This SDK can be installed and run with Bun. If the repository being deployed
|
|
127
|
+
uses Bun-specific runtime behavior on Vercel, set the app's Bun version in its
|
|
128
|
+
`vercel.json`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { ArchiveOptions, CreateRepoOptions, CreateRepoOptions as CreateRepoOptions$1, FindOneOptions, FindOneOptions as FindOneOptions$1, GitStorage, GitStorage as GitStorage$1, GitStorageOptions, GitStorageOptions as GitStorageOptions$1, ListReposOptions, ListReposOptions as ListReposOptions$1, ListReposResult, ListReposResult as ListReposResult$1, Repo, Repo as Repo$1, RepoOptions, RepoOptions as RepoOptions$1 } from "@pierre/storage";
|
|
2
|
+
import { DeploymentOptions, VercelClientOptions } from "@vercel/client";
|
|
3
|
+
|
|
4
|
+
//#region src/archive.d.ts
|
|
5
|
+
interface MaterializeRepoArchiveOptions {
|
|
6
|
+
ref: string;
|
|
7
|
+
includeGlobs?: string[];
|
|
8
|
+
excludeGlobs?: string[];
|
|
9
|
+
maxBlobSize?: number;
|
|
10
|
+
}
|
|
11
|
+
interface MaterializedArchive {
|
|
12
|
+
path: string;
|
|
13
|
+
cleanup(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
interface TarEntryLike {
|
|
16
|
+
type?: string;
|
|
17
|
+
linkpath?: string;
|
|
18
|
+
}
|
|
19
|
+
declare function materializeRepoArchive(repo: Repo$1, options: MaterializeRepoArchiveOptions): Promise<MaterializedArchive>;
|
|
20
|
+
declare function isSafeArchiveEntry(entryPath: string, entry: TarEntryLike): boolean;
|
|
21
|
+
declare function isSafeArchivePath(entryPath: string): boolean;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/errors.d.ts
|
|
24
|
+
interface VercelCodeStorageErrorOptions {
|
|
25
|
+
cause?: unknown;
|
|
26
|
+
details?: unknown;
|
|
27
|
+
}
|
|
28
|
+
declare class VercelCodeStorageError extends Error {
|
|
29
|
+
readonly details?: unknown;
|
|
30
|
+
constructor(message: string, options?: VercelCodeStorageErrorOptions);
|
|
31
|
+
}
|
|
32
|
+
declare class VercelCodeStorageConfigError extends VercelCodeStorageError {
|
|
33
|
+
constructor(message: string, options?: VercelCodeStorageErrorOptions);
|
|
34
|
+
}
|
|
35
|
+
declare class CodeStorageArchiveError extends VercelCodeStorageError {
|
|
36
|
+
constructor(message: string, options?: VercelCodeStorageErrorOptions);
|
|
37
|
+
}
|
|
38
|
+
declare class VercelDeploymentError extends VercelCodeStorageError {
|
|
39
|
+
readonly eventType?: string;
|
|
40
|
+
constructor(message: string, options?: VercelCodeStorageErrorOptions & {
|
|
41
|
+
eventType?: string;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/types.d.ts
|
|
46
|
+
type CodeStorageClientInput = GitStorage$1 | GitStorageOptions$1;
|
|
47
|
+
type FindRepoInput = string | FindOneOptions$1;
|
|
48
|
+
type RepoInput = string | RepoOptions$1;
|
|
49
|
+
type DeploymentTarget = "preview" | "production" | (string & {});
|
|
50
|
+
type VercelProjectSettings = DeploymentOptions["projectSettings"];
|
|
51
|
+
type VercelDeploymentEnv = DeploymentOptions["env"];
|
|
52
|
+
type VercelBuildOptions = DeploymentOptions["build"];
|
|
53
|
+
type VercelSkipAutoDetectionConfirmation = VercelClientOptions["skipAutoDetectionConfirmation"];
|
|
54
|
+
interface VercelDeploymentEvent {
|
|
55
|
+
type: string;
|
|
56
|
+
payload: unknown;
|
|
57
|
+
action?: string;
|
|
58
|
+
link?: string;
|
|
59
|
+
}
|
|
60
|
+
type VercelDeploymentEventHandler = (event: VercelDeploymentEvent) => void | Promise<void>;
|
|
61
|
+
interface VercelCodeStorageOptions {
|
|
62
|
+
codeStorage: CodeStorageClientInput;
|
|
63
|
+
vercel: VercelDeploymentOptions;
|
|
64
|
+
deploymentAdapter?: DeploymentAdapter;
|
|
65
|
+
}
|
|
66
|
+
interface VercelDeploymentOptions {
|
|
67
|
+
token: string;
|
|
68
|
+
teamId?: string;
|
|
69
|
+
apiUrl?: string;
|
|
70
|
+
projectName?: string;
|
|
71
|
+
rootDirectory?: string | null;
|
|
72
|
+
projectSettings?: VercelProjectSettings;
|
|
73
|
+
env?: VercelDeploymentEnv;
|
|
74
|
+
build?: VercelBuildOptions;
|
|
75
|
+
force?: boolean;
|
|
76
|
+
withCache?: boolean;
|
|
77
|
+
debug?: boolean;
|
|
78
|
+
userAgent?: string;
|
|
79
|
+
skipAutoDetectionConfirmation?: VercelSkipAutoDetectionConfirmation;
|
|
80
|
+
}
|
|
81
|
+
interface DeployOptions {
|
|
82
|
+
ref?: string;
|
|
83
|
+
target?: DeploymentTarget;
|
|
84
|
+
projectName?: string;
|
|
85
|
+
rootDirectory?: string | null;
|
|
86
|
+
projectSettings?: VercelProjectSettings;
|
|
87
|
+
env?: VercelDeploymentEnv;
|
|
88
|
+
build?: VercelBuildOptions;
|
|
89
|
+
includeGlobs?: string[];
|
|
90
|
+
excludeGlobs?: string[];
|
|
91
|
+
maxBlobSize?: number;
|
|
92
|
+
force?: boolean;
|
|
93
|
+
withCache?: boolean;
|
|
94
|
+
debug?: boolean;
|
|
95
|
+
skipAutoDetectionConfirmation?: VercelSkipAutoDetectionConfirmation;
|
|
96
|
+
wait?: boolean;
|
|
97
|
+
meta?: Record<string, string>;
|
|
98
|
+
onEvent?: VercelDeploymentEventHandler;
|
|
99
|
+
}
|
|
100
|
+
interface DeploymentGitMetadata {
|
|
101
|
+
commitAuthorName?: string;
|
|
102
|
+
commitMessage?: string;
|
|
103
|
+
commitRef?: string;
|
|
104
|
+
commitSha?: string;
|
|
105
|
+
dirty?: boolean;
|
|
106
|
+
remoteUrl?: string;
|
|
107
|
+
}
|
|
108
|
+
interface DeployResult {
|
|
109
|
+
url: string;
|
|
110
|
+
publicUrl?: string;
|
|
111
|
+
deploymentId: string;
|
|
112
|
+
inspectorUrl?: string;
|
|
113
|
+
target?: string;
|
|
114
|
+
aliases: string[];
|
|
115
|
+
readyState: string;
|
|
116
|
+
}
|
|
117
|
+
interface DeploymentAdapter {
|
|
118
|
+
deploy(request: VercelDeploymentRequest): Promise<DeployResult>;
|
|
119
|
+
}
|
|
120
|
+
interface VercelDeploymentRequest {
|
|
121
|
+
projectPath: string;
|
|
122
|
+
token: string;
|
|
123
|
+
target?: string;
|
|
124
|
+
teamId?: string;
|
|
125
|
+
apiUrl?: string;
|
|
126
|
+
projectName?: string;
|
|
127
|
+
rootDirectory?: string | null;
|
|
128
|
+
projectSettings?: VercelProjectSettings;
|
|
129
|
+
env?: VercelDeploymentEnv;
|
|
130
|
+
build?: VercelBuildOptions;
|
|
131
|
+
force?: boolean;
|
|
132
|
+
withCache?: boolean;
|
|
133
|
+
debug?: boolean;
|
|
134
|
+
userAgent?: string;
|
|
135
|
+
skipAutoDetectionConfirmation?: VercelSkipAutoDetectionConfirmation;
|
|
136
|
+
wait?: boolean;
|
|
137
|
+
meta?: Record<string, string>;
|
|
138
|
+
gitMetadata?: DeploymentGitMetadata;
|
|
139
|
+
onEvent?: VercelDeploymentEventHandler;
|
|
140
|
+
}
|
|
141
|
+
interface VercelRepoOptions {
|
|
142
|
+
repo: Repo$1;
|
|
143
|
+
vercel: VercelDeploymentOptions;
|
|
144
|
+
deploymentAdapter: DeploymentAdapter;
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/repo.d.ts
|
|
148
|
+
declare class VercelRepo {
|
|
149
|
+
readonly storage: Repo$1;
|
|
150
|
+
private readonly vercel;
|
|
151
|
+
private readonly deploymentAdapter;
|
|
152
|
+
constructor(options: VercelRepoOptions);
|
|
153
|
+
get id(): string;
|
|
154
|
+
get defaultBranch(): string;
|
|
155
|
+
get createdAt(): string;
|
|
156
|
+
deploy(options?: DeployOptions): Promise<DeployResult>;
|
|
157
|
+
getPreviewUrl(options?: Omit<DeployOptions, "target">): Promise<string>;
|
|
158
|
+
getPublicUrl(options?: Omit<DeployOptions, "target">): Promise<string>;
|
|
159
|
+
private resolveGitMetadata;
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/store.d.ts
|
|
163
|
+
declare class VercelCodeStorage {
|
|
164
|
+
readonly storage: GitStorage$1;
|
|
165
|
+
private readonly vercel;
|
|
166
|
+
private readonly deploymentAdapter;
|
|
167
|
+
constructor(options: VercelCodeStorageOptions);
|
|
168
|
+
createRepo(options?: CreateRepoOptions$1): Promise<VercelRepo>;
|
|
169
|
+
findOne(input: FindRepoInput): Promise<VercelRepo | null>;
|
|
170
|
+
repo(input: RepoInput): VercelRepo;
|
|
171
|
+
listRepos(options?: ListReposOptions$1): Promise<ListReposResult$1>;
|
|
172
|
+
private wrapRepo;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/vercel.d.ts
|
|
176
|
+
interface VercelDeploymentLike {
|
|
177
|
+
id?: string;
|
|
178
|
+
url?: string;
|
|
179
|
+
inspectorUrl?: string | null;
|
|
180
|
+
target?: string | null;
|
|
181
|
+
alias?: string[];
|
|
182
|
+
readyState?: string;
|
|
183
|
+
}
|
|
184
|
+
declare function createVercelDeploymentAdapter(): DeploymentAdapter;
|
|
185
|
+
declare function createVercelClientOptions(request: VercelDeploymentRequest): VercelClientOptions;
|
|
186
|
+
declare function createVercelDeploymentOptions(request: VercelDeploymentRequest): DeploymentOptions;
|
|
187
|
+
declare function deployWithVercelClient(request: VercelDeploymentRequest): Promise<DeployResult>;
|
|
188
|
+
declare function deploymentToDeployResult(deployment: VercelDeploymentLike): DeployResult;
|
|
189
|
+
//#endregion
|
|
190
|
+
export { type ArchiveOptions, CodeStorageArchiveError, type CodeStorageClientInput, type CreateRepoOptions, type DeployOptions, type DeployResult, type DeploymentAdapter, type DeploymentGitMetadata, type DeploymentTarget, type FindOneOptions, type FindRepoInput, GitStorage, type GitStorageOptions, type ListReposOptions, type ListReposResult, type MaterializeRepoArchiveOptions, type MaterializedArchive, type Repo, type RepoInput, type RepoOptions, type VercelBuildOptions, VercelCodeStorage, VercelCodeStorageConfigError, VercelCodeStorageError, type VercelCodeStorageOptions, type VercelDeploymentEnv, VercelDeploymentError, type VercelDeploymentEvent, type VercelDeploymentEventHandler, type VercelDeploymentOptions, type VercelDeploymentRequest, type VercelProjectSettings, VercelRepo, type VercelRepoOptions, type VercelSkipAutoDetectionConfirmation, createVercelClientOptions, createVercelDeploymentAdapter, createVercelDeploymentOptions, deployWithVercelClient, deploymentToDeployResult, isSafeArchiveEntry, isSafeArchivePath, materializeRepoArchive };
|
|
191
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/archive.ts","../src/errors.ts","../src/types.ts","../src/repo.ts","../src/store.ts","../src/vercel.ts"],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { GitStorage, GitStorage as GitStorage$1 } from "@pierre/storage";
|
|
2
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { isAbsolute, join, normalize, posix, sep } from "node:path";
|
|
5
|
+
import { Readable } from "node:stream";
|
|
6
|
+
import { pipeline } from "node:stream/promises";
|
|
7
|
+
import { x } from "tar";
|
|
8
|
+
import { createDeployment } from "@vercel/client";
|
|
9
|
+
//#region src/errors.ts
|
|
10
|
+
var VercelCodeStorageError = class extends Error {
|
|
11
|
+
details;
|
|
12
|
+
constructor(message, options = {}) {
|
|
13
|
+
super(message, { cause: options.cause });
|
|
14
|
+
this.name = "VercelCodeStorageError";
|
|
15
|
+
this.details = options.details;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var VercelCodeStorageConfigError = class extends VercelCodeStorageError {
|
|
19
|
+
constructor(message, options) {
|
|
20
|
+
super(message, options);
|
|
21
|
+
this.name = "VercelCodeStorageConfigError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var CodeStorageArchiveError = class extends VercelCodeStorageError {
|
|
25
|
+
constructor(message, options) {
|
|
26
|
+
super(message, options);
|
|
27
|
+
this.name = "CodeStorageArchiveError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var VercelDeploymentError = class extends VercelCodeStorageError {
|
|
31
|
+
eventType;
|
|
32
|
+
constructor(message, options = {}) {
|
|
33
|
+
super(message, options);
|
|
34
|
+
this.name = "VercelDeploymentError";
|
|
35
|
+
this.eventType = options.eventType;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/archive.ts
|
|
40
|
+
async function materializeRepoArchive(repo, options) {
|
|
41
|
+
const response = await repo.getArchiveStream(buildArchiveOptions(options));
|
|
42
|
+
if (!response.ok) throw new CodeStorageArchiveError(await archiveErrorMessage(response), { details: {
|
|
43
|
+
repoId: repo.id,
|
|
44
|
+
ref: options.ref,
|
|
45
|
+
status: response.status,
|
|
46
|
+
statusText: response.statusText
|
|
47
|
+
} });
|
|
48
|
+
const body = response.body;
|
|
49
|
+
if (!body) throw new CodeStorageArchiveError("code.storage archive response was empty.", { details: {
|
|
50
|
+
repoId: repo.id,
|
|
51
|
+
ref: options.ref
|
|
52
|
+
} });
|
|
53
|
+
const directory = await mkdtemp(join(tmpdir(), "vercel-code-storage-"));
|
|
54
|
+
try {
|
|
55
|
+
await pipeline(Readable.fromWeb(body), x({
|
|
56
|
+
cwd: directory,
|
|
57
|
+
gzip: true,
|
|
58
|
+
strict: true,
|
|
59
|
+
filter: (entryPath, entry) => isSafeArchiveEntry(entryPath, entry)
|
|
60
|
+
}));
|
|
61
|
+
return {
|
|
62
|
+
path: directory,
|
|
63
|
+
cleanup: () => cleanupDirectory(directory)
|
|
64
|
+
};
|
|
65
|
+
} catch (error) {
|
|
66
|
+
await cleanupDirectory(directory);
|
|
67
|
+
throw new CodeStorageArchiveError("failed to extract code.storage archive.", {
|
|
68
|
+
cause: error,
|
|
69
|
+
details: {
|
|
70
|
+
repoId: repo.id,
|
|
71
|
+
ref: options.ref
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function isSafeArchiveEntry(entryPath, entry) {
|
|
77
|
+
if (!isSafeArchivePath(entryPath)) return false;
|
|
78
|
+
const type = entry.type ?? "";
|
|
79
|
+
if (type === "SymbolicLink" || type === "Link" || type === "HardLink") return false;
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
function isSafeArchivePath(entryPath) {
|
|
83
|
+
const normalizedSeparators = entryPath.replace(/\\/g, "/");
|
|
84
|
+
if (normalizedSeparators.includes("\0")) return false;
|
|
85
|
+
const normalized = posix.normalize(normalizedSeparators);
|
|
86
|
+
return normalized !== "." && !normalized.startsWith("../") && !posix.isAbsolute(normalized);
|
|
87
|
+
}
|
|
88
|
+
function buildArchiveOptions(options) {
|
|
89
|
+
const archiveOptions = { ref: options.ref };
|
|
90
|
+
if (options.includeGlobs && options.includeGlobs.length > 0) archiveOptions.includeGlobs = options.includeGlobs;
|
|
91
|
+
if (options.excludeGlobs && options.excludeGlobs.length > 0) archiveOptions.excludeGlobs = options.excludeGlobs;
|
|
92
|
+
if (typeof options.maxBlobSize === "number" && Number.isFinite(options.maxBlobSize)) archiveOptions.maxBlobSize = options.maxBlobSize;
|
|
93
|
+
return archiveOptions;
|
|
94
|
+
}
|
|
95
|
+
async function archiveErrorMessage(response) {
|
|
96
|
+
const detail = (await response.text().catch(() => "")).trim().slice(0, 500);
|
|
97
|
+
if (detail) return `code.storage archive request failed with status ${response.status}: ${detail}`;
|
|
98
|
+
return `code.storage archive request failed with status ${response.status}.`;
|
|
99
|
+
}
|
|
100
|
+
async function cleanupDirectory(directory) {
|
|
101
|
+
await rm(directory, {
|
|
102
|
+
recursive: true,
|
|
103
|
+
force: true
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/repo.ts
|
|
108
|
+
var VercelRepo = class {
|
|
109
|
+
storage;
|
|
110
|
+
vercel;
|
|
111
|
+
deploymentAdapter;
|
|
112
|
+
constructor(options) {
|
|
113
|
+
this.storage = options.repo;
|
|
114
|
+
this.vercel = options.vercel;
|
|
115
|
+
this.deploymentAdapter = options.deploymentAdapter;
|
|
116
|
+
}
|
|
117
|
+
get id() {
|
|
118
|
+
return this.storage.id;
|
|
119
|
+
}
|
|
120
|
+
get defaultBranch() {
|
|
121
|
+
return this.storage.defaultBranch;
|
|
122
|
+
}
|
|
123
|
+
get createdAt() {
|
|
124
|
+
return this.storage.createdAt;
|
|
125
|
+
}
|
|
126
|
+
async deploy(options = {}) {
|
|
127
|
+
const ref = resolveDeployRef(this.storage, options);
|
|
128
|
+
const rootDirectory = resolveOption(options, this.vercel, "rootDirectory");
|
|
129
|
+
const commitMetadata = await this.resolveGitMetadata(ref);
|
|
130
|
+
const meta = buildDeploymentMeta(this.storage.id, ref, options, commitMetadata);
|
|
131
|
+
const materialized = await materializeRepoArchive(this.storage, {
|
|
132
|
+
ref,
|
|
133
|
+
includeGlobs: options.includeGlobs,
|
|
134
|
+
excludeGlobs: options.excludeGlobs,
|
|
135
|
+
maxBlobSize: options.maxBlobSize
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
const request = buildDeploymentRequest({
|
|
139
|
+
projectPath: resolveProjectPath(materialized.path, rootDirectory),
|
|
140
|
+
token: this.vercel.token,
|
|
141
|
+
teamId: this.vercel.teamId,
|
|
142
|
+
apiUrl: this.vercel.apiUrl,
|
|
143
|
+
projectName: resolveOption(options, this.vercel, "projectName"),
|
|
144
|
+
target: options.target,
|
|
145
|
+
projectSettings: resolveOption(options, this.vercel, "projectSettings"),
|
|
146
|
+
env: resolveOption(options, this.vercel, "env"),
|
|
147
|
+
build: resolveOption(options, this.vercel, "build"),
|
|
148
|
+
force: resolveOption(options, this.vercel, "force"),
|
|
149
|
+
withCache: resolveOption(options, this.vercel, "withCache"),
|
|
150
|
+
debug: resolveOption(options, this.vercel, "debug"),
|
|
151
|
+
userAgent: this.vercel.userAgent,
|
|
152
|
+
skipAutoDetectionConfirmation: resolveOption(options, this.vercel, "skipAutoDetectionConfirmation"),
|
|
153
|
+
wait: options.wait,
|
|
154
|
+
meta,
|
|
155
|
+
gitMetadata: commitMetadata,
|
|
156
|
+
onEvent: options.onEvent
|
|
157
|
+
});
|
|
158
|
+
return await this.deploymentAdapter.deploy(request);
|
|
159
|
+
} finally {
|
|
160
|
+
await materialized.cleanup();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async getPreviewUrl(options = {}) {
|
|
164
|
+
return (await this.deploy({
|
|
165
|
+
...options,
|
|
166
|
+
target: "preview"
|
|
167
|
+
})).url;
|
|
168
|
+
}
|
|
169
|
+
async getPublicUrl(options = {}) {
|
|
170
|
+
const result = await this.deploy({
|
|
171
|
+
...options,
|
|
172
|
+
target: "production"
|
|
173
|
+
});
|
|
174
|
+
return result.publicUrl ?? result.url;
|
|
175
|
+
}
|
|
176
|
+
async resolveGitMetadata(ref) {
|
|
177
|
+
const { commit } = await this.storage.getCommit({ sha: ref });
|
|
178
|
+
return {
|
|
179
|
+
commitRef: ref,
|
|
180
|
+
dirty: false,
|
|
181
|
+
commitAuthorName: commit.authorName,
|
|
182
|
+
commitMessage: commit.message,
|
|
183
|
+
commitSha: commit.sha
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
function resolveDeployRef(repo, options) {
|
|
188
|
+
return options.ref?.trim() || repo.defaultBranch || "main";
|
|
189
|
+
}
|
|
190
|
+
function buildDeploymentMeta(repoId, ref, options, gitMetadata) {
|
|
191
|
+
return {
|
|
192
|
+
...options.meta,
|
|
193
|
+
codeStorageRepoId: repoId,
|
|
194
|
+
codeStorageRef: ref,
|
|
195
|
+
...gitMetadata.commitSha ? { codeStorageCommitSha: gitMetadata.commitSha } : {}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function resolveProjectPath(archivePath, rootDirectory) {
|
|
199
|
+
if (rootDirectory === void 0 || rootDirectory === null) return archivePath;
|
|
200
|
+
if (isAbsolute(rootDirectory)) throw new VercelDeploymentError("rootDirectory must be a relative path within the archived repo.");
|
|
201
|
+
const normalized = normalize(rootDirectory);
|
|
202
|
+
if (normalized === ".." || normalized.startsWith(`..${sep}`)) throw new VercelDeploymentError("rootDirectory must be a relative path within the archived repo.");
|
|
203
|
+
return join(archivePath, normalized);
|
|
204
|
+
}
|
|
205
|
+
function resolveOption(options, vercel, key) {
|
|
206
|
+
return Object.prototype.hasOwnProperty.call(options, key) ? options[key] : vercel[key];
|
|
207
|
+
}
|
|
208
|
+
function buildDeploymentRequest(request) {
|
|
209
|
+
return Object.fromEntries(Object.entries(request).filter(([, value]) => value !== void 0));
|
|
210
|
+
}
|
|
211
|
+
//#endregion
|
|
212
|
+
//#region src/url.ts
|
|
213
|
+
function toHttpsUrl(value) {
|
|
214
|
+
const trimmed = value.trim();
|
|
215
|
+
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) return trimmed;
|
|
216
|
+
return `https://${trimmed}`;
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/vercel.ts
|
|
220
|
+
function createVercelDeploymentAdapter() {
|
|
221
|
+
return { deploy: deployWithVercelClient };
|
|
222
|
+
}
|
|
223
|
+
function createVercelClientOptions(request) {
|
|
224
|
+
return omitUndefined({
|
|
225
|
+
token: request.token,
|
|
226
|
+
path: request.projectPath,
|
|
227
|
+
teamId: request.teamId,
|
|
228
|
+
apiUrl: request.apiUrl,
|
|
229
|
+
force: request.force,
|
|
230
|
+
withCache: request.withCache,
|
|
231
|
+
debug: request.debug,
|
|
232
|
+
projectName: request.projectName,
|
|
233
|
+
rootDirectory: request.rootDirectory,
|
|
234
|
+
userAgent: request.userAgent,
|
|
235
|
+
skipAutoDetectionConfirmation: request.skipAutoDetectionConfirmation
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function createVercelDeploymentOptions(request) {
|
|
239
|
+
return omitUndefined({
|
|
240
|
+
name: request.projectName,
|
|
241
|
+
target: request.target,
|
|
242
|
+
meta: request.meta,
|
|
243
|
+
gitMetadata: request.gitMetadata,
|
|
244
|
+
projectSettings: request.projectSettings,
|
|
245
|
+
env: request.env,
|
|
246
|
+
build: request.build
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async function deployWithVercelClient(request) {
|
|
250
|
+
const clientOptions = createVercelClientOptions(request);
|
|
251
|
+
const deploymentOptions = createVercelDeploymentOptions(request);
|
|
252
|
+
let latestDeployment;
|
|
253
|
+
const events = createDeployment(clientOptions, deploymentOptions);
|
|
254
|
+
for await (const event of events) {
|
|
255
|
+
await request.onEvent?.(event);
|
|
256
|
+
if (event.type === "created") {
|
|
257
|
+
latestDeployment = requireDeploymentPayload(event);
|
|
258
|
+
if (request.wait === false) return deploymentToDeployResult(latestDeployment);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (event.type === "ready" || event.type === "alias-assigned") {
|
|
262
|
+
latestDeployment = requireDeploymentPayload(event);
|
|
263
|
+
if (event.type === "alias-assigned") return deploymentToDeployResult(latestDeployment);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (event.type === "canceled") throw new VercelDeploymentError("Vercel deployment was canceled.", {
|
|
267
|
+
eventType: event.type,
|
|
268
|
+
details: event.payload
|
|
269
|
+
});
|
|
270
|
+
if (event.type === "error") throw new VercelDeploymentError(payloadMessage(event.payload) ?? "Vercel deployment failed.", {
|
|
271
|
+
cause: event.payload,
|
|
272
|
+
eventType: event.type,
|
|
273
|
+
details: event.payload
|
|
274
|
+
});
|
|
275
|
+
if (isFailedChecksEvent(event.type)) throw new VercelDeploymentError(payloadMessage(event.payload) ?? "Vercel deployment checks failed.", {
|
|
276
|
+
eventType: event.type,
|
|
277
|
+
details: event.payload
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
if (latestDeployment) return deploymentToDeployResult(latestDeployment);
|
|
281
|
+
throw new VercelDeploymentError("Vercel deployment completed without returning a deployment.", { details: {
|
|
282
|
+
projectPath: request.projectPath,
|
|
283
|
+
target: request.target,
|
|
284
|
+
projectName: request.projectName
|
|
285
|
+
} });
|
|
286
|
+
}
|
|
287
|
+
function deploymentToDeployResult(deployment) {
|
|
288
|
+
const url = requireString(deployment.url, "deployment url");
|
|
289
|
+
const deploymentId = requireString(deployment.id, "deployment id");
|
|
290
|
+
const target = optionalString(deployment.target);
|
|
291
|
+
const aliases = requireStringArray(deployment.alias, "deployment aliases");
|
|
292
|
+
const productionUrl = target === "production" && aliases.length > 0 ? toHttpsUrl(requireString(aliases[0], "production alias")) : void 0;
|
|
293
|
+
return {
|
|
294
|
+
url: toHttpsUrl(url),
|
|
295
|
+
publicUrl: productionUrl,
|
|
296
|
+
deploymentId,
|
|
297
|
+
inspectorUrl: deployment.inspectorUrl ?? void 0,
|
|
298
|
+
...target === void 0 ? {} : { target },
|
|
299
|
+
aliases,
|
|
300
|
+
readyState: requireString(deployment.readyState, "deployment readyState")
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function requireDeploymentPayload(event) {
|
|
304
|
+
if (!isDeploymentPayload(event.payload)) throw new VercelDeploymentError(`Vercel event "${event.type}" did not include a deployment payload.`, {
|
|
305
|
+
eventType: event.type,
|
|
306
|
+
details: event.payload
|
|
307
|
+
});
|
|
308
|
+
return event.payload;
|
|
309
|
+
}
|
|
310
|
+
function isDeploymentPayload(payload) {
|
|
311
|
+
return typeof payload === "object" && payload !== null && "url" in payload && "id" in payload;
|
|
312
|
+
}
|
|
313
|
+
function isFailedChecksEvent(type) {
|
|
314
|
+
return type === "checks-conclusion-failed" || type === "checks-v2-failed" || type === "checks-conclusion-canceled";
|
|
315
|
+
}
|
|
316
|
+
function payloadMessage(payload) {
|
|
317
|
+
if (payload instanceof Error && payload.message.trim()) return payload.message.trim();
|
|
318
|
+
if (typeof payload === "string" && payload.trim()) return payload.trim();
|
|
319
|
+
if (payload && typeof payload === "object" && "message" in payload) {
|
|
320
|
+
const message = payload.message;
|
|
321
|
+
if (typeof message === "string" && message.trim()) return message.trim();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function requireString(value, label) {
|
|
325
|
+
if (typeof value === "string" && value.trim() !== "") return value;
|
|
326
|
+
throw new VercelDeploymentError(`Vercel deployment was missing ${label}.`);
|
|
327
|
+
}
|
|
328
|
+
function optionalString(value) {
|
|
329
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
330
|
+
}
|
|
331
|
+
function requireStringArray(value, label) {
|
|
332
|
+
if (Array.isArray(value) && value.every((item) => typeof item === "string")) return value;
|
|
333
|
+
throw new VercelDeploymentError(`Vercel deployment was missing ${label}.`);
|
|
334
|
+
}
|
|
335
|
+
function omitUndefined(input) {
|
|
336
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/store.ts
|
|
340
|
+
var VercelCodeStorage = class {
|
|
341
|
+
storage;
|
|
342
|
+
vercel;
|
|
343
|
+
deploymentAdapter;
|
|
344
|
+
constructor(options) {
|
|
345
|
+
if (!options || typeof options !== "object") throw new VercelCodeStorageConfigError("VercelCodeStorage requires options.");
|
|
346
|
+
this.storage = resolveCodeStorage(options.codeStorage);
|
|
347
|
+
this.vercel = validateVercelOptions(options.vercel);
|
|
348
|
+
this.deploymentAdapter = options.deploymentAdapter ?? createVercelDeploymentAdapter();
|
|
349
|
+
}
|
|
350
|
+
async createRepo(options) {
|
|
351
|
+
const repo = await this.storage.createRepo(options);
|
|
352
|
+
return this.wrapRepo(repo);
|
|
353
|
+
}
|
|
354
|
+
async findOne(input) {
|
|
355
|
+
const repo = await this.storage.findOne(normalizeFindRepoInput(input));
|
|
356
|
+
return repo ? this.wrapRepo(repo) : null;
|
|
357
|
+
}
|
|
358
|
+
repo(input) {
|
|
359
|
+
return this.wrapRepo(this.storage.repo(normalizeRepoInput(input)));
|
|
360
|
+
}
|
|
361
|
+
async listRepos(options) {
|
|
362
|
+
return this.storage.listRepos(options);
|
|
363
|
+
}
|
|
364
|
+
wrapRepo(repo) {
|
|
365
|
+
return new VercelRepo({
|
|
366
|
+
repo,
|
|
367
|
+
vercel: this.vercel,
|
|
368
|
+
deploymentAdapter: this.deploymentAdapter
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
function resolveCodeStorage(input) {
|
|
373
|
+
if (isGitStorageLike(input)) return input;
|
|
374
|
+
return new GitStorage$1(validateCodeStorageOptions(input));
|
|
375
|
+
}
|
|
376
|
+
function isGitStorageLike(input) {
|
|
377
|
+
return typeof input === "object" && input !== null && "createRepo" in input && "findOne" in input && "repo" in input;
|
|
378
|
+
}
|
|
379
|
+
function validateCodeStorageOptions(input) {
|
|
380
|
+
if (!input || typeof input !== "object") throw new VercelCodeStorageConfigError("VercelCodeStorage requires codeStorage options or an existing GitStorage instance.");
|
|
381
|
+
const options = input;
|
|
382
|
+
if (typeof options.name !== "string" || options.name.trim() === "") throw new VercelCodeStorageConfigError("Environment/config error: missing codeStorage.name. Set ORG_NAME or pass codeStorage.name.");
|
|
383
|
+
if (typeof options.key !== "string" || options.key.trim() === "") throw new VercelCodeStorageConfigError("Environment/config error: missing codeStorage.key. Set PIERRE_PRIVATE_KEY or pass codeStorage.key.");
|
|
384
|
+
return {
|
|
385
|
+
...options,
|
|
386
|
+
name: options.name.trim()
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function validateVercelOptions(options) {
|
|
390
|
+
if (!options || typeof options !== "object") throw new VercelCodeStorageConfigError("VercelCodeStorage requires Vercel deployment options.");
|
|
391
|
+
if (typeof options.token !== "string" || options.token.trim() === "") throw new VercelCodeStorageConfigError("Environment/config error: missing vercel.token. Set VERCEL_TOKEN or pass vercel.token.");
|
|
392
|
+
return {
|
|
393
|
+
...options,
|
|
394
|
+
token: options.token.trim()
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function normalizeFindRepoInput(input) {
|
|
398
|
+
if (typeof input === "string") return { id: requireNonEmptyRepoId(input) };
|
|
399
|
+
if (!input || typeof input !== "object") throw new VercelCodeStorageConfigError("findOne requires a repository id or { id }.");
|
|
400
|
+
return {
|
|
401
|
+
...input,
|
|
402
|
+
id: requireNonEmptyRepoId(input.id)
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function normalizeRepoInput(input) {
|
|
406
|
+
if (typeof input === "string") return { id: requireNonEmptyRepoId(input) };
|
|
407
|
+
if (!input || typeof input !== "object") throw new VercelCodeStorageConfigError("repo requires a repository id or repository metadata.");
|
|
408
|
+
return {
|
|
409
|
+
...input,
|
|
410
|
+
id: requireNonEmptyRepoId(input.id)
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function requireNonEmptyRepoId(id) {
|
|
414
|
+
const trimmed = id.trim();
|
|
415
|
+
if (!trimmed) throw new VercelCodeStorageConfigError("Repository id must be a non-empty string.");
|
|
416
|
+
return trimmed;
|
|
417
|
+
}
|
|
418
|
+
//#endregion
|
|
419
|
+
export { CodeStorageArchiveError, GitStorage, VercelCodeStorage, VercelCodeStorageConfigError, VercelCodeStorageError, VercelDeploymentError, VercelRepo, createVercelClientOptions, createVercelDeploymentAdapter, createVercelDeploymentOptions, deployWithVercelClient, deploymentToDeployResult, isSafeArchiveEntry, isSafeArchivePath, materializeRepoArchive };
|
|
420
|
+
|
|
421
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["extractTar","GitStorage"],"sources":["../src/errors.ts","../src/archive.ts","../src/repo.ts","../src/url.ts","../src/vercel.ts","../src/store.ts"],"sourcesContent":["export interface VercelCodeStorageErrorOptions {\n cause?: unknown;\n details?: unknown;\n}\n\nexport class VercelCodeStorageError extends Error {\n public readonly details?: unknown;\n\n constructor(message: string, options: VercelCodeStorageErrorOptions = {}) {\n super(message, { cause: options.cause });\n this.name = 'VercelCodeStorageError';\n this.details = options.details;\n }\n}\n\nexport class VercelCodeStorageConfigError extends VercelCodeStorageError {\n constructor(message: string, options?: VercelCodeStorageErrorOptions) {\n super(message, options);\n this.name = 'VercelCodeStorageConfigError';\n }\n}\n\nexport class CodeStorageArchiveError extends VercelCodeStorageError {\n constructor(message: string, options?: VercelCodeStorageErrorOptions) {\n super(message, options);\n this.name = 'CodeStorageArchiveError';\n }\n}\n\nexport class VercelDeploymentError extends VercelCodeStorageError {\n public readonly eventType?: string;\n\n constructor(\n message: string,\n options: VercelCodeStorageErrorOptions & { eventType?: string } = {}\n ) {\n super(message, options);\n this.name = 'VercelDeploymentError';\n this.eventType = options.eventType;\n }\n}\n","import type { ArchiveOptions, Repo } from '@pierre/storage';\nimport { mkdtemp, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join, posix } from 'node:path';\nimport { Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\nimport { x as extractTar } from 'tar';\n\nimport { CodeStorageArchiveError } from './errors.js';\n\nexport interface MaterializeRepoArchiveOptions {\n ref: string;\n includeGlobs?: string[];\n excludeGlobs?: string[];\n maxBlobSize?: number;\n}\n\nexport interface MaterializedArchive {\n path: string;\n cleanup(): Promise<void>;\n}\n\ninterface TarEntryLike {\n type?: string;\n linkpath?: string;\n}\n\nexport async function materializeRepoArchive(\n repo: Repo,\n options: MaterializeRepoArchiveOptions\n): Promise<MaterializedArchive> {\n const response = await repo.getArchiveStream(buildArchiveOptions(options));\n if (!response.ok) {\n throw new CodeStorageArchiveError(await archiveErrorMessage(response), {\n details: {\n repoId: repo.id,\n ref: options.ref,\n status: response.status,\n statusText: response.statusText,\n },\n });\n }\n\n const body = response.body;\n if (!body) {\n throw new CodeStorageArchiveError(\n 'code.storage archive response was empty.',\n {\n details: { repoId: repo.id, ref: options.ref },\n }\n );\n }\n\n const directory = await mkdtemp(join(tmpdir(), 'vercel-code-storage-'));\n try {\n const nodeStream = Readable.fromWeb(\n body as unknown as Parameters<typeof Readable.fromWeb>[0]\n );\n await pipeline(\n nodeStream,\n extractTar({\n cwd: directory,\n gzip: true,\n strict: true,\n filter: (entryPath: string, entry: unknown) =>\n isSafeArchiveEntry(entryPath, entry as TarEntryLike),\n })\n );\n return {\n path: directory,\n cleanup: () => cleanupDirectory(directory),\n };\n } catch (error) {\n await cleanupDirectory(directory);\n throw new CodeStorageArchiveError(\n 'failed to extract code.storage archive.',\n {\n cause: error,\n details: { repoId: repo.id, ref: options.ref },\n }\n );\n }\n}\n\nexport function isSafeArchiveEntry(\n entryPath: string,\n entry: TarEntryLike\n): boolean {\n if (!isSafeArchivePath(entryPath)) {\n return false;\n }\n\n const type = entry.type ?? '';\n if (type === 'SymbolicLink' || type === 'Link' || type === 'HardLink') {\n return false;\n }\n\n return true;\n}\n\nexport function isSafeArchivePath(entryPath: string): boolean {\n const normalizedSeparators = entryPath.replace(/\\\\/g, '/');\n if (normalizedSeparators.includes('\\0')) {\n return false;\n }\n\n const normalized = posix.normalize(normalizedSeparators);\n return (\n normalized !== '.' &&\n !normalized.startsWith('../') &&\n !posix.isAbsolute(normalized)\n );\n}\n\nfunction buildArchiveOptions(\n options: MaterializeRepoArchiveOptions\n): ArchiveOptions {\n const archiveOptions: ArchiveOptions = { ref: options.ref };\n if (options.includeGlobs && options.includeGlobs.length > 0) {\n archiveOptions.includeGlobs = options.includeGlobs;\n }\n if (options.excludeGlobs && options.excludeGlobs.length > 0) {\n archiveOptions.excludeGlobs = options.excludeGlobs;\n }\n if (\n typeof options.maxBlobSize === 'number' &&\n Number.isFinite(options.maxBlobSize)\n ) {\n archiveOptions.maxBlobSize = options.maxBlobSize;\n }\n return archiveOptions;\n}\n\nasync function archiveErrorMessage(response: Response): Promise<string> {\n const text = await response.text().catch(() => '');\n const detail = text.trim().slice(0, 500);\n if (detail) {\n return `code.storage archive request failed with status ${response.status}: ${detail}`;\n }\n return `code.storage archive request failed with status ${response.status}.`;\n}\n\nasync function cleanupDirectory(directory: string): Promise<void> {\n await rm(directory, { recursive: true, force: true });\n}\n","import type { Repo } from '@pierre/storage';\nimport { isAbsolute, join, normalize, sep } from 'node:path';\n\nimport { materializeRepoArchive } from './archive.js';\nimport { VercelDeploymentError } from './errors.js';\nimport type {\n DeployOptions,\n DeployResult,\n DeploymentAdapter,\n DeploymentGitMetadata,\n VercelDeploymentOptions,\n VercelDeploymentRequest,\n VercelRepoOptions,\n} from './types.js';\n\nexport class VercelRepo {\n public readonly storage: Repo;\n\n private readonly vercel: VercelDeploymentOptions;\n private readonly deploymentAdapter: DeploymentAdapter;\n\n constructor(options: VercelRepoOptions) {\n this.storage = options.repo;\n this.vercel = options.vercel;\n this.deploymentAdapter = options.deploymentAdapter;\n }\n\n get id(): string {\n return this.storage.id;\n }\n\n get defaultBranch(): string {\n return this.storage.defaultBranch;\n }\n\n get createdAt(): string {\n return this.storage.createdAt;\n }\n\n async deploy(options: DeployOptions = {}): Promise<DeployResult> {\n const ref = resolveDeployRef(this.storage, options);\n const rootDirectory = resolveOption(options, this.vercel, 'rootDirectory');\n const commitMetadata = await this.resolveGitMetadata(ref);\n const meta = buildDeploymentMeta(\n this.storage.id,\n ref,\n options,\n commitMetadata\n );\n const materialized = await materializeRepoArchive(this.storage, {\n ref,\n includeGlobs: options.includeGlobs,\n excludeGlobs: options.excludeGlobs,\n maxBlobSize: options.maxBlobSize,\n });\n\n try {\n const request = buildDeploymentRequest({\n projectPath: resolveProjectPath(materialized.path, rootDirectory),\n token: this.vercel.token,\n teamId: this.vercel.teamId,\n apiUrl: this.vercel.apiUrl,\n projectName: resolveOption(options, this.vercel, 'projectName'),\n target: options.target,\n projectSettings: resolveOption(options, this.vercel, 'projectSettings'),\n env: resolveOption(options, this.vercel, 'env'),\n build: resolveOption(options, this.vercel, 'build'),\n force: resolveOption(options, this.vercel, 'force'),\n withCache: resolveOption(options, this.vercel, 'withCache'),\n debug: resolveOption(options, this.vercel, 'debug'),\n userAgent: this.vercel.userAgent,\n skipAutoDetectionConfirmation: resolveOption(\n options,\n this.vercel,\n 'skipAutoDetectionConfirmation'\n ),\n wait: options.wait,\n meta,\n gitMetadata: commitMetadata,\n onEvent: options.onEvent,\n });\n\n return await this.deploymentAdapter.deploy(request);\n } finally {\n await materialized.cleanup();\n }\n }\n\n async getPreviewUrl(\n options: Omit<DeployOptions, 'target'> = {}\n ): Promise<string> {\n const result = await this.deploy({ ...options, target: 'preview' });\n return result.url;\n }\n\n async getPublicUrl(\n options: Omit<DeployOptions, 'target'> = {}\n ): Promise<string> {\n const result = await this.deploy({ ...options, target: 'production' });\n return result.publicUrl ?? result.url;\n }\n\n private async resolveGitMetadata(\n ref: string\n ): Promise<DeploymentGitMetadata> {\n const { commit } = await this.storage.getCommit({ sha: ref });\n return {\n commitRef: ref,\n dirty: false,\n commitAuthorName: commit.authorName,\n commitMessage: commit.message,\n commitSha: commit.sha,\n };\n }\n}\n\nfunction resolveDeployRef(repo: Repo, options: DeployOptions): string {\n const ref = options.ref?.trim() || repo.defaultBranch || 'main';\n return ref;\n}\n\nfunction buildDeploymentMeta(\n repoId: string,\n ref: string,\n options: DeployOptions,\n gitMetadata: DeploymentGitMetadata\n): Record<string, string> {\n return {\n ...options.meta,\n codeStorageRepoId: repoId,\n codeStorageRef: ref,\n ...(gitMetadata.commitSha\n ? { codeStorageCommitSha: gitMetadata.commitSha }\n : {}),\n };\n}\n\nfunction resolveProjectPath(\n archivePath: string,\n rootDirectory: string | null | undefined\n): string {\n if (rootDirectory === undefined || rootDirectory === null) {\n return archivePath;\n }\n\n if (isAbsolute(rootDirectory)) {\n throw new VercelDeploymentError(\n 'rootDirectory must be a relative path within the archived repo.'\n );\n }\n\n const normalized = normalize(rootDirectory);\n if (normalized === '..' || normalized.startsWith(`..${sep}`)) {\n throw new VercelDeploymentError(\n 'rootDirectory must be a relative path within the archived repo.'\n );\n }\n\n return join(archivePath, normalized);\n}\n\nfunction resolveOption<\n Key extends keyof DeployOptions & keyof VercelDeploymentOptions,\n>(\n options: DeployOptions,\n vercel: VercelDeploymentOptions,\n key: Key\n): DeployOptions[Key] | VercelDeploymentOptions[Key] {\n return Object.prototype.hasOwnProperty.call(options, key)\n ? options[key]\n : vercel[key];\n}\n\nfunction buildDeploymentRequest(\n request: VercelDeploymentRequest\n): VercelDeploymentRequest {\n return Object.fromEntries(\n Object.entries(request).filter(([, value]) => value !== undefined)\n ) as VercelDeploymentRequest;\n}\n","export function toHttpsUrl(value: string): string {\n const trimmed = value.trim();\n if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {\n return trimmed;\n }\n return `https://${trimmed}`;\n}\n","import {\n createDeployment,\n type Deployment,\n type DeploymentOptions,\n type VercelClientOptions,\n} from '@vercel/client';\n\nimport { VercelDeploymentError } from './errors.js';\nimport type {\n DeployResult,\n DeploymentAdapter,\n VercelDeploymentRequest,\n} from './types.js';\nimport { toHttpsUrl } from './url.js';\n\nexport interface VercelClientEvent {\n type: string;\n payload: unknown;\n action?: string;\n link?: string;\n}\n\ninterface VercelDeploymentLike {\n id?: string;\n url?: string;\n inspectorUrl?: string | null;\n target?: string | null;\n alias?: string[];\n readyState?: string;\n}\n\nexport function createVercelDeploymentAdapter(): DeploymentAdapter {\n return {\n deploy: deployWithVercelClient,\n };\n}\n\nexport function createVercelClientOptions(\n request: VercelDeploymentRequest\n): VercelClientOptions {\n return omitUndefined({\n token: request.token,\n path: request.projectPath,\n teamId: request.teamId,\n apiUrl: request.apiUrl,\n force: request.force,\n withCache: request.withCache,\n debug: request.debug,\n projectName: request.projectName,\n rootDirectory: request.rootDirectory,\n userAgent: request.userAgent,\n skipAutoDetectionConfirmation: request.skipAutoDetectionConfirmation,\n });\n}\n\nexport function createVercelDeploymentOptions(\n request: VercelDeploymentRequest\n): DeploymentOptions {\n return omitUndefined({\n name: request.projectName,\n target: request.target,\n meta: request.meta,\n gitMetadata: request.gitMetadata,\n projectSettings: request.projectSettings,\n env: request.env,\n build: request.build,\n });\n}\n\nexport async function deployWithVercelClient(\n request: VercelDeploymentRequest\n): Promise<DeployResult> {\n const clientOptions = createVercelClientOptions(request);\n const deploymentOptions = createVercelDeploymentOptions(request);\n\n let latestDeployment: Deployment | undefined;\n const events = createDeployment(\n clientOptions,\n deploymentOptions\n ) as AsyncIterable<VercelClientEvent>;\n\n for await (const event of events) {\n await request.onEvent?.(event);\n\n if (event.type === 'created') {\n latestDeployment = requireDeploymentPayload(event);\n if (request.wait === false) {\n return deploymentToDeployResult(latestDeployment);\n }\n continue;\n }\n\n if (event.type === 'ready' || event.type === 'alias-assigned') {\n latestDeployment = requireDeploymentPayload(event);\n if (event.type === 'alias-assigned') {\n return deploymentToDeployResult(latestDeployment);\n }\n continue;\n }\n\n if (event.type === 'canceled') {\n throw new VercelDeploymentError('Vercel deployment was canceled.', {\n eventType: event.type,\n details: event.payload,\n });\n }\n\n if (event.type === 'error') {\n throw new VercelDeploymentError(\n payloadMessage(event.payload) ?? 'Vercel deployment failed.',\n {\n cause: event.payload,\n eventType: event.type,\n details: event.payload,\n }\n );\n }\n\n if (isFailedChecksEvent(event.type)) {\n throw new VercelDeploymentError(\n payloadMessage(event.payload) ?? 'Vercel deployment checks failed.',\n {\n eventType: event.type,\n details: event.payload,\n }\n );\n }\n }\n\n if (latestDeployment) {\n return deploymentToDeployResult(latestDeployment);\n }\n\n throw new VercelDeploymentError(\n 'Vercel deployment completed without returning a deployment.',\n {\n details: {\n projectPath: request.projectPath,\n target: request.target,\n projectName: request.projectName,\n },\n }\n );\n}\n\nexport function deploymentToDeployResult(\n deployment: VercelDeploymentLike\n): DeployResult {\n const url = requireString(deployment.url, 'deployment url');\n const deploymentId = requireString(deployment.id, 'deployment id');\n const target = optionalString(deployment.target);\n const aliases = requireStringArray(deployment.alias, 'deployment aliases');\n const productionUrl =\n target === 'production' && aliases.length > 0\n ? toHttpsUrl(requireString(aliases[0], 'production alias'))\n : undefined;\n\n return {\n url: toHttpsUrl(url),\n publicUrl: productionUrl,\n deploymentId,\n inspectorUrl: deployment.inspectorUrl ?? undefined,\n ...(target === undefined ? {} : { target }),\n aliases,\n readyState: requireString(deployment.readyState, 'deployment readyState'),\n };\n}\n\nfunction requireDeploymentPayload(event: VercelClientEvent): Deployment {\n if (!isDeploymentPayload(event.payload)) {\n throw new VercelDeploymentError(\n `Vercel event \"${event.type}\" did not include a deployment payload.`,\n { eventType: event.type, details: event.payload }\n );\n }\n return event.payload;\n}\n\nfunction isDeploymentPayload(payload: unknown): payload is Deployment {\n return (\n typeof payload === 'object' &&\n payload !== null &&\n 'url' in payload &&\n 'id' in payload\n );\n}\n\nfunction isFailedChecksEvent(type: string): boolean {\n return (\n type === 'checks-conclusion-failed' ||\n type === 'checks-v2-failed' ||\n type === 'checks-conclusion-canceled'\n );\n}\n\nfunction payloadMessage(payload: unknown): string | undefined {\n if (payload instanceof Error && payload.message.trim()) {\n return payload.message.trim();\n }\n if (typeof payload === 'string' && payload.trim()) {\n return payload.trim();\n }\n if (payload && typeof payload === 'object' && 'message' in payload) {\n const message = payload.message;\n if (typeof message === 'string' && message.trim()) {\n return message.trim();\n }\n }\n return undefined;\n}\n\nfunction requireString(\n value: string | null | undefined,\n label: string\n): string {\n if (typeof value === 'string' && value.trim() !== '') {\n return value;\n }\n throw new VercelDeploymentError(`Vercel deployment was missing ${label}.`);\n}\n\nfunction optionalString(value: string | null | undefined): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value : undefined;\n}\n\nfunction requireStringArray(\n value: string[] | undefined,\n label: string\n): string[] {\n if (Array.isArray(value) && value.every((item) => typeof item === 'string')) {\n return value;\n }\n throw new VercelDeploymentError(`Vercel deployment was missing ${label}.`);\n}\n\nfunction omitUndefined<T extends Record<string, unknown>>(input: T): T {\n return Object.fromEntries(\n Object.entries(input).filter(([, value]) => value !== undefined)\n ) as T;\n}\n","import {\n GitStorage,\n type CreateRepoOptions,\n type FindOneOptions,\n type GitStorageOptions,\n type ListReposOptions,\n type ListReposResult,\n type Repo,\n type RepoOptions,\n} from '@pierre/storage';\n\nimport { VercelCodeStorageConfigError } from './errors.js';\nimport { VercelRepo } from './repo.js';\nimport type {\n CodeStorageClientInput,\n DeploymentAdapter,\n FindRepoInput,\n RepoInput,\n VercelCodeStorageOptions,\n VercelDeploymentOptions,\n} from './types.js';\nimport { createVercelDeploymentAdapter } from './vercel.js';\n\nexport class VercelCodeStorage {\n public readonly storage: GitStorage;\n\n private readonly vercel: VercelDeploymentOptions;\n private readonly deploymentAdapter: DeploymentAdapter;\n\n constructor(options: VercelCodeStorageOptions) {\n if (!options || typeof options !== 'object') {\n throw new VercelCodeStorageConfigError(\n 'VercelCodeStorage requires options.'\n );\n }\n this.storage = resolveCodeStorage(options.codeStorage);\n this.vercel = validateVercelOptions(options.vercel);\n this.deploymentAdapter =\n options.deploymentAdapter ?? createVercelDeploymentAdapter();\n }\n\n async createRepo(options?: CreateRepoOptions): Promise<VercelRepo> {\n const repo = await this.storage.createRepo(options);\n return this.wrapRepo(repo);\n }\n\n async findOne(input: FindRepoInput): Promise<VercelRepo | null> {\n const repo = await this.storage.findOne(normalizeFindRepoInput(input));\n return repo ? this.wrapRepo(repo) : null;\n }\n\n repo(input: RepoInput): VercelRepo {\n return this.wrapRepo(this.storage.repo(normalizeRepoInput(input)));\n }\n\n async listRepos(options?: ListReposOptions): Promise<ListReposResult> {\n return this.storage.listRepos(options);\n }\n\n private wrapRepo(repo: Repo): VercelRepo {\n return new VercelRepo({\n repo,\n vercel: this.vercel,\n deploymentAdapter: this.deploymentAdapter,\n });\n }\n}\n\nfunction resolveCodeStorage(input: CodeStorageClientInput): GitStorage {\n if (isGitStorageLike(input)) {\n return input;\n }\n return new GitStorage(validateCodeStorageOptions(input));\n}\n\nfunction isGitStorageLike(input: CodeStorageClientInput): input is GitStorage {\n return (\n typeof input === 'object' &&\n input !== null &&\n 'createRepo' in input &&\n 'findOne' in input &&\n 'repo' in input\n );\n}\n\nfunction validateCodeStorageOptions(\n input: CodeStorageClientInput\n): GitStorageOptions {\n if (!input || typeof input !== 'object') {\n throw new VercelCodeStorageConfigError(\n 'VercelCodeStorage requires codeStorage options or an existing GitStorage instance.'\n );\n }\n\n const options = input as GitStorageOptions;\n if (typeof options.name !== 'string' || options.name.trim() === '') {\n throw new VercelCodeStorageConfigError(\n 'Environment/config error: missing codeStorage.name. Set ORG_NAME or pass codeStorage.name.'\n );\n }\n if (typeof options.key !== 'string' || options.key.trim() === '') {\n throw new VercelCodeStorageConfigError(\n 'Environment/config error: missing codeStorage.key. Set PIERRE_PRIVATE_KEY or pass codeStorage.key.'\n );\n }\n\n return { ...options, name: options.name.trim() };\n}\n\nfunction validateVercelOptions(\n options: VercelDeploymentOptions\n): VercelDeploymentOptions {\n if (!options || typeof options !== 'object') {\n throw new VercelCodeStorageConfigError(\n 'VercelCodeStorage requires Vercel deployment options.'\n );\n }\n if (typeof options.token !== 'string' || options.token.trim() === '') {\n throw new VercelCodeStorageConfigError(\n 'Environment/config error: missing vercel.token. Set VERCEL_TOKEN or pass vercel.token.'\n );\n }\n return { ...options, token: options.token.trim() };\n}\n\nfunction normalizeFindRepoInput(input: FindRepoInput): FindOneOptions {\n if (typeof input === 'string') {\n return { id: requireNonEmptyRepoId(input) };\n }\n if (!input || typeof input !== 'object') {\n throw new VercelCodeStorageConfigError(\n 'findOne requires a repository id or { id }.'\n );\n }\n return { ...input, id: requireNonEmptyRepoId(input.id) };\n}\n\nfunction normalizeRepoInput(input: RepoInput): RepoOptions {\n if (typeof input === 'string') {\n return { id: requireNonEmptyRepoId(input) };\n }\n if (!input || typeof input !== 'object') {\n throw new VercelCodeStorageConfigError(\n 'repo requires a repository id or repository metadata.'\n );\n }\n return { ...input, id: requireNonEmptyRepoId(input.id) };\n}\n\nfunction requireNonEmptyRepoId(id: string): string {\n const trimmed = id.trim();\n if (!trimmed) {\n throw new VercelCodeStorageConfigError(\n 'Repository id must be a non-empty string.'\n );\n }\n return trimmed;\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pierre/vercel-code-storage",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Deploy code.storage repositories to Vercel from TypeScript.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"LICENSE",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsdown --clean",
|
|
25
|
+
"dev": "tsdown --watch --log-level error",
|
|
26
|
+
"format": "oxfmt .",
|
|
27
|
+
"format:check": "oxfmt --check .",
|
|
28
|
+
"test": "bun test",
|
|
29
|
+
"tsc": "tsc --noEmit --pretty",
|
|
30
|
+
"prepublishOnly": "bun run build"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@pierre/storage": "^1.9.0",
|
|
34
|
+
"@vercel/client": "^17.5.12",
|
|
35
|
+
"tar": "^7.5.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/bun": "^1.3.14",
|
|
39
|
+
"@types/node": "^25.0.3",
|
|
40
|
+
"oxfmt": "^0.52.0",
|
|
41
|
+
"tsdown": "^0.22.0",
|
|
42
|
+
"typescript": "^5.9.3"
|
|
43
|
+
}
|
|
44
|
+
}
|