@interfere/build 0.2.2 → 0.3.1
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 +17 -0
- package/dist/release-request.d.cts +2 -0
- package/dist/release-request.d.mts +2 -0
- package/dist/source-map-upload-fetch.cjs +1 -0
- package/dist/source-map-upload-fetch.d.cts +4 -0
- package/dist/source-map-upload-fetch.d.mts +4 -0
- package/dist/source-map-upload-fetch.mjs +1 -0
- package/dist/upload-source-map-chunks.cjs +1 -1
- package/dist/upload-source-map-chunks.d.cts +3 -0
- package/dist/upload-source-map-chunks.d.mts +3 -0
- package/dist/upload-source-map-chunks.mjs +1 -1
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -6,3 +6,20 @@ Use `@interfere/javascript` to call release endpoints directly. This package
|
|
|
6
6
|
provides build configuration resolution, release metadata, ordered source-map
|
|
7
7
|
chunk uploads, and local artifact cleanup. Framework integrations own the sequence
|
|
8
8
|
of API calls and only delete source maps after the server accepts the full batch.
|
|
9
|
+
|
|
10
|
+
Source-map uploads use 20 concurrent workers by default. Set
|
|
11
|
+
`INTERFERE_SOURCEMAP_UPLOAD_CONCURRENCY` to a positive integer to change the limit;
|
|
12
|
+
the `uploadSourceMapChunks` `concurrency` option takes precedence. Next.js and Vite
|
|
13
|
+
share this setting. Pass the variable through your build runner when it filters
|
|
14
|
+
environment variables, such as Turborepo's strict environment mode.
|
|
15
|
+
|
|
16
|
+
Next.js and Vite use gzip only when the signed upload session advertises support,
|
|
17
|
+
with identity uploads for payloads that do not shrink. Older servers receive
|
|
18
|
+
uncompressed chunks of at most 512 KiB. Servers advertising gzip accept chunks
|
|
19
|
+
of up to 8 MiB. Chunk offsets and reported byte counts refer to the original,
|
|
20
|
+
uncompressed content.
|
|
21
|
+
|
|
22
|
+
When calling `uploadSourceMapChunks` directly, construct the API client with
|
|
23
|
+
`fetch: sourceMapUploadFetch` from `@interfere/build/source-map-upload-fetch` and
|
|
24
|
+
pass `compression: "gzip"` to the uploader. Direct callers retain identity uploads
|
|
25
|
+
unless they opt in; Next.js and Vite configure both automatically.
|
|
@@ -36,6 +36,8 @@ export declare function resolveReleaseRequest(input: {
|
|
|
36
36
|
environmentName: string | null;
|
|
37
37
|
environmentTarget: string | null;
|
|
38
38
|
provider: "cloudflare";
|
|
39
|
+
deploymentId?: string | null | undefined;
|
|
40
|
+
trafficPercentage?: number | null | undefined;
|
|
39
41
|
scriptName: string | null;
|
|
40
42
|
versionId: string | null;
|
|
41
43
|
} | {
|
|
@@ -36,6 +36,8 @@ export declare function resolveReleaseRequest(input: {
|
|
|
36
36
|
environmentName: string | null;
|
|
37
37
|
environmentTarget: string | null;
|
|
38
38
|
provider: "cloudflare";
|
|
39
|
+
deploymentId?: string | null | undefined;
|
|
40
|
+
trafficPercentage?: number | null | undefined;
|
|
39
41
|
scriptName: string | null;
|
|
40
42
|
versionId: string | null;
|
|
41
43
|
} | {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let node_util=require("node:util"),node_zlib=require("node:zlib");const compress=(0,node_util.promisify)(node_zlib.gzip),sourceMapUploadFetch=Object.assign(async(input,init)=>{let request=new Request(input,init);if(request.method===`POST`&&new URL(request.url).pathname.endsWith(`/source-maps/sign`)&&request.headers.set(`x-interfere-source-map-compression`,`gzip`),request.headers.get(`content-encoding`)!==`gzip`)return fetch(request);let bytes=await request.arrayBuffer(),body=await compress(bytes),headers=new Headers(request.headers);return headers.delete(`content-length`),body.byteLength>=bytes.byteLength?(headers.delete(`content-encoding`),fetch(new Request(request,{body:bytes,headers,method:request.method}))):fetch(new Request(request,{body,headers,method:request.method}))},fetch);exports.sourceMapUploadFetch=sourceMapUploadFetch;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{promisify}from"node:util";import{gzip}from"node:zlib";const compress=promisify(gzip),sourceMapUploadFetch=Object.assign(async(input,init)=>{let request=new Request(input,init);if(request.method===`POST`&&new URL(request.url).pathname.endsWith(`/source-maps/sign`)&&request.headers.set(`x-interfere-source-map-compression`,`gzip`),request.headers.get(`content-encoding`)!==`gzip`)return fetch(request);let bytes=await request.arrayBuffer(),body=await compress(bytes),headers=new Headers(request.headers);return headers.delete(`content-length`),body.byteLength>=bytes.byteLength?(headers.delete(`content-encoding`),fetch(new Request(request,{body:bytes,headers,method:request.method}))):fetch(new Request(request,{body,headers,method:request.method}))},fetch);export{sourceMapUploadFetch};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const require_upload_source_map_batch=require("./upload-source-map-batch.cjs"),require_upload_source_map_request=require("./upload-source-map-request.cjs")
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const require_upload_source_map_batch=require("./upload-source-map-batch.cjs"),require_upload_source_map_request=require("./upload-source-map-request.cjs");let _interfere_types_data_source_map_upload_batch=require("@interfere/types/data/source-map-upload-batch");async function uploadSourceMapChunks(options){let{client,environment,files,releaseSlug,signed}=options,concurrency=options.concurrency??Number(process.env.INTERFERE_SOURCEMAP_UPLOAD_CONCURRENCY??20);if(!Number.isSafeInteger(concurrency)||concurrency<1)throw Error(`Source-map upload concurrency must be a positive integer`);let capability=_interfere_types_data_source_map_upload_batch.sourceMapBatchCapability.safeParse(signed.batchUpload),supportsGzip=capability.success&&capability.data.compression===`gzip`,chunkBytes=supportsGzip?8388608:524288,headers=options.compression===`gzip`&&supportsGzip?{"content-encoding":`gzip`}:void 0,controller=new AbortController;try{let sessionDeadlineMs=signed.expiresAt*1e3,assertSessionOpen=()=>{if(!Number.isFinite(sessionDeadlineMs)||Date.now()>=sessionDeadlineMs)throw Error(`Source-map upload session expired`)};assertSessionOpen();let abortSignal=AbortSignal.any([controller.signal,AbortSignal.timeout(sessionDeadlineMs-Date.now())]),expected=new Set(files.map(file=>file.path));if(signed.uploads.length!==files.length||new Set(signed.uploads.map(file=>file.path)).size!==files.length||signed.uploads.some(file=>!expected.has(file.path)))throw Error(`Source-map server returned a different batch`);let jobs=require_upload_source_map_batch.sourceMapUploadJobs(files,signed.batchUpload),totalBytes=0;return await Promise.all(Array.from({length:Math.min(concurrency,files.length)},async()=>{for(let job of jobs){if(abortSignal.throwIfAborted(),assertSessionOpen(),job.chunks){await require_upload_source_map_request.uploadSourceMapRequest(async()=>await client.releases.uploadSourceMapBatch({releaseSlug,environment,chunks:job.chunks},{abortSignal,headers}),abortSignal),totalBytes+=job.rawBytes;continue}let{file}=job,bytes=new TextEncoder().encode(file.content);for(let offset=0;offset<bytes.byteLength;offset+=chunkBytes){assertSessionOpen();let chunk=new Blob([bytes.subarray(offset,offset+chunkBytes)]);await require_upload_source_map_request.uploadSourceMapRequest(async()=>await client.releases.uploadSourceMap(chunk,releaseSlug,{environment,path:file.path,offset},{abortSignal,headers:{...headers,"x-interfere-source-map-size":String(chunk.size)}}),abortSignal)}totalBytes+=bytes.byteLength}})),assertSessionOpen(),totalBytes}finally{controller.abort()}}exports.uploadSourceMapChunks=uploadSourceMapChunks;
|
|
@@ -5,6 +5,9 @@ export declare function uploadSourceMapChunks(options: {
|
|
|
5
5
|
releaseSlug: string;
|
|
6
6
|
environment?: string | undefined;
|
|
7
7
|
signed: Interfere.SourceMapUploadSessionResponse;
|
|
8
|
+
concurrency?: number;
|
|
9
|
+
/** Requires sourceMapUploadFetch on the client; defaults to identity. */
|
|
10
|
+
compression?: "gzip";
|
|
8
11
|
files: readonly (Interfere.CompleteSourceMapFile & {
|
|
9
12
|
content: string;
|
|
10
13
|
})[];
|
|
@@ -5,6 +5,9 @@ export declare function uploadSourceMapChunks(options: {
|
|
|
5
5
|
releaseSlug: string;
|
|
6
6
|
environment?: string | undefined;
|
|
7
7
|
signed: Interfere.SourceMapUploadSessionResponse;
|
|
8
|
+
concurrency?: number;
|
|
9
|
+
/** Requires sourceMapUploadFetch on the client; defaults to identity. */
|
|
10
|
+
compression?: "gzip";
|
|
8
11
|
files: readonly (Interfere.CompleteSourceMapFile & {
|
|
9
12
|
content: string;
|
|
10
13
|
})[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sourceMapUploadJobs}from"./upload-source-map-batch.mjs";import{uploadSourceMapRequest}from"./upload-source-map-request.mjs";
|
|
1
|
+
import{sourceMapUploadJobs}from"./upload-source-map-batch.mjs";import{uploadSourceMapRequest}from"./upload-source-map-request.mjs";import{sourceMapBatchCapability}from"@interfere/types/data/source-map-upload-batch";async function uploadSourceMapChunks(options){let{client,environment,files,releaseSlug,signed}=options,concurrency=options.concurrency??Number(process.env.INTERFERE_SOURCEMAP_UPLOAD_CONCURRENCY??20);if(!Number.isSafeInteger(concurrency)||concurrency<1)throw Error(`Source-map upload concurrency must be a positive integer`);let capability=sourceMapBatchCapability.safeParse(signed.batchUpload),supportsGzip=capability.success&&capability.data.compression===`gzip`,chunkBytes=supportsGzip?8388608:524288,headers=options.compression===`gzip`&&supportsGzip?{"content-encoding":`gzip`}:void 0,controller=new AbortController;try{let sessionDeadlineMs=signed.expiresAt*1e3,assertSessionOpen=()=>{if(!Number.isFinite(sessionDeadlineMs)||Date.now()>=sessionDeadlineMs)throw Error(`Source-map upload session expired`)};assertSessionOpen();let abortSignal=AbortSignal.any([controller.signal,AbortSignal.timeout(sessionDeadlineMs-Date.now())]),expected=new Set(files.map(file=>file.path));if(signed.uploads.length!==files.length||new Set(signed.uploads.map(file=>file.path)).size!==files.length||signed.uploads.some(file=>!expected.has(file.path)))throw Error(`Source-map server returned a different batch`);let jobs=sourceMapUploadJobs(files,signed.batchUpload),totalBytes=0;return await Promise.all(Array.from({length:Math.min(concurrency,files.length)},async()=>{for(let job of jobs){if(abortSignal.throwIfAborted(),assertSessionOpen(),job.chunks){await uploadSourceMapRequest(async()=>await client.releases.uploadSourceMapBatch({releaseSlug,environment,chunks:job.chunks},{abortSignal,headers}),abortSignal),totalBytes+=job.rawBytes;continue}let{file}=job,bytes=new TextEncoder().encode(file.content);for(let offset=0;offset<bytes.byteLength;offset+=chunkBytes){assertSessionOpen();let chunk=new Blob([bytes.subarray(offset,offset+chunkBytes)]);await uploadSourceMapRequest(async()=>await client.releases.uploadSourceMap(chunk,releaseSlug,{environment,path:file.path,offset},{abortSignal,headers:{...headers,"x-interfere-source-map-size":String(chunk.size)}}),abortSignal)}totalBytes+=bytes.byteLength}})),assertSessionOpen(),totalBytes}finally{controller.abort()}}export{uploadSourceMapChunks};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/build",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Release preparation for Interfere build integrations.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"build",
|
|
@@ -71,6 +71,17 @@
|
|
|
71
71
|
"types": "./dist/upload-source-map-chunks.d.cts",
|
|
72
72
|
"default": "./dist/upload-source-map-chunks.cjs"
|
|
73
73
|
}
|
|
74
|
+
},
|
|
75
|
+
"./source-map-upload-fetch": {
|
|
76
|
+
"monorepo": "./src/source-map-upload-fetch.ts",
|
|
77
|
+
"import": {
|
|
78
|
+
"types": "./dist/source-map-upload-fetch.d.mts",
|
|
79
|
+
"default": "./dist/source-map-upload-fetch.mjs"
|
|
80
|
+
},
|
|
81
|
+
"require": {
|
|
82
|
+
"types": "./dist/source-map-upload-fetch.d.cts",
|
|
83
|
+
"default": "./dist/source-map-upload-fetch.cjs"
|
|
84
|
+
}
|
|
74
85
|
}
|
|
75
86
|
},
|
|
76
87
|
"publishConfig": {
|
|
@@ -83,16 +94,16 @@
|
|
|
83
94
|
},
|
|
84
95
|
"dependencies": {
|
|
85
96
|
"@interfere/javascript": "^0.2.1",
|
|
86
|
-
"@interfere/types": "^10.
|
|
97
|
+
"@interfere/types": "^10.3.0"
|
|
87
98
|
},
|
|
88
99
|
"devDependencies": {
|
|
89
100
|
"@interfere/typescript-config": "^9.0.2",
|
|
90
101
|
"@interfere/vitest-config": "0.0.0",
|
|
91
102
|
"@types/node": "^26.4.1",
|
|
92
|
-
"@vitest/coverage-v8": "5.0.
|
|
103
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
93
104
|
"msw": "^2.14.6",
|
|
94
105
|
"tsdown": "^0.23.0",
|
|
95
106
|
"typescript": "^7.0.2",
|
|
96
|
-
"vitest": "5.0.
|
|
107
|
+
"vitest": "5.0.5"
|
|
97
108
|
}
|
|
98
109
|
}
|